From 6a3e1317c75af02e6a4d3d1cb336ed79b86e59df Mon Sep 17 00:00:00 2001 From: Robin Lindner Date: Tue, 1 Feb 2022 21:03:35 +0100 Subject: [PATCH] `SafeFileHandle` `FileStatus` (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [RateLimiting] Dequeue items when queuing with NewestFirst (#63377) * Don't reuse registers in Debug mode (#63698) Co-authored-by: Bruce Forstall * Add IsKnownConstant jit helper and optimize 'str == ""' with str.StartsWith('c') (#63734) Co-authored-by: Miha Zupan Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> * - mono_wasm_new_external_root for roots on stack (#63997) - temp_malloc helper via linear buffer in js - small refactorings Co-authored-by: Katelyn Gadd * [Arm64] Don't use D-copies in CopyBlock (#63588) * Increase the maximum number of internal registers allowd per node in src/coreclr/jit/lsra.h * Based on discussion in https://github.com/dotnet/runtime/issues/63453 don't allocate a SIMD register pair if the JIT won't be able to use Q-copies in src/coreclr/jit/lsraarmarch.cpp * Update CodeGen to reflect that Q-copies should be used only when size >= 2 * FP_REGSIZE_BYTES and using of them makes the instruction sequence shorter in src/coreclr/jit/codegenarmarch.cpp * Update comment - we don't use D-copies after that change in src/coreclr/jit/codegenarmarch.cpp * Disable hot reload tests for AOT configurations (#64006) * Bump Explicit-layout value types with no fields to at minimum 1 byte size. (#63975) * Add runtime-extra-platforms pipeline to have matching runtime PR and Rolling builds (#62564) * Add runtime-extended-platforms pipeline to have matching runtime PR and Rolling builds * Fix evaluate changed paths condition for the extra pipeline * PR Feedback and fix condition * Move MacCatalyst back to staging, disable tvOS tests * Disable browser wasm windows legs * Make ILStubGenerated event log ModuleID corresponding to that on other events (#63974) * Retries for flaky WMI test (#64008) * [arm64] JIT: Redundant zero/sign extensions after ldrX/ldrsX (#62630) * JIT: fix up switch map for out-of-loop predecessor (#64014) If we have a loop where some of the non-loop predecessors are switchs, and we add pre-header to the loop, we need to update the switch map for those predecessors. Fixes #63982. * Update StructMarshalling design now that DisableRuntimeMarshallingAttribute is approved (#63765) Co-authored-by: Elinor Fung * Fix Crossgen2 bug #61104 and add regression test (#63956) The issue tracks the runtime regression failure where Crossgen2-compiled app is unable to locate a type with non-ASCII characters in its name. The failure was caused by the fact that Crossgen2 was incorrectly zero-extending the individual UTF8 characters when calculating the hash whereas runtime is sign-extending them. Thanks Tomas * Fix invalid threading of nodes in rationalization (#64012) The code in question assumes that the ASG will be reversed and thus threads "simdTree" before "location" in the linear order. That dependency, while valid, because "gtSetEvalOrder" will always reverse ASGs with locals on the LHS, is unnecessary and incorrect from the IR validity point of view. Fix this by using "InsertAfter" instead of manual node threading. * Check if the child object is in the heap range before get_region_plan_gen_num (#63828) * Check if the child object is in the heap range before object_gennum (#63970) * 'cmeq' and 'fcmeq' Vector64.Zero/Vector128.Zero ARM64 containment optimizations (#62933) * Initial work * Added a comma to display * Cleanup * Fixing build * More cleanup * Update comment * Update comment * Added CompareEqual Vector64/128 with Zero tests * Do not contain op1 for now * Wrong intrinsic id used * Removing generated tests * Removing generated tests * Added CompareEqual tests * Supporting containment for first operand * Fix test build * Passing correct register * Check IsVectorZero before not allocing a register * Update comment * Fixing test * Minor format change * Fixed formatting * Renamed test * Adding AdvSimd_Arm64 tests: * Adding support for rest of 'cmeq' and 'fcmeq' instructions * Removing github csproj * Minor test fix * Fixed tests * Fix print * Minor format change * Fixing test * Added some emitter tests * Feedback * Update emitarm64.cpp * Feedback * [Arm64] Keep unrolling InitBlock and CopyBlock up to 128 bytes (#63422) * Add INITBLK_LCL_UNROLL_LIMIT and CPBLK_LCL_UNROLL_LIMIT of 128 bytes in src/coreclr/jit/targetarm64.h * Keep unrolling InitBlock up to INITBLK_LCL_UNROLL_LIMIT bytes when dstAddr points to the stack in src/coreclr/jit/lowerarmarch.cpp * Keep unrolling CopyBlock up to CPBLK_LCL_UNROLL_LIMIT bytes when both srcAddr and dstAddr point to the stack in src/coreclr/jit/lowerarmarch.cpp * Add ProcessLinkerXmlBase to NativeAOT (#63666) Add Xml Parsing linker files as a reference source to NativeAOT Rename NativeAOT ProcessLinkerXmlBase version to ProcessXmlBase (uses XmlReader) Add ProcessLinkerXmlBase from linker and fix it so it can be used in NativeAOT (uses XPath) * Fix gc_heap::remove_ro_segment (#63473) * Fix OpenSSL version check in GetAlpnSupport The previous check failed 3.0.0 because the Minor was 0 and Build was 0. It could probably be rewritten to be `>= new Version(1, 0, 2)`, but that'd require more thinking. * Fix issues with verify_regions, clear_batch_mark_array_bits. (#63798) Details: - we cannot verify the tail of the region list from background GC, as it may be updated by threads allocating. - fix case in clear_batch_mark_array_bits where end is equal to the very end of a segment and we write into uncommitted memory in the mark_array. - bgc_clear_batch_mark_array_bits did some checks and then called clear_batch_mark_array_bits which repeated the exact same checks. Renamed clear_batch_mark_array_bits to bgc_batch_mark_array_bits and removed the old copy, removed the declaration for clear_batch_mark_array_bits. * [debugger][wasm] Added support for non user code attribute (#63876) * Hidden methods and step through methods behave the same way. * Perpared flow for setting JustMyCode in the future. * Tests for JustMyCode setting before debug launch. * Transformed into dynamic JustMyCode change flow. * JustMyCode disabled, first 3 cases solved. * Finished behavior for JMC disabled (with 1 difference). * JMC enabled: stepIn np bp + stepIn bp + resume bp. * Functional version (with minor deviations from expected behavior). * Refactoring. * All tests for NonUserCode work. * Fix line number after adding code above. * Fix error in merge. * Removing duplicated tests. * [wasm][debugger] Added support for stepper boundary attribute (#63991) * Hidden methods and step through methods behave the same way. * Perpared flow for setting JustMyCode in the future. * Tests for JustMyCode setting before debug launch. * Transformed into dynamic JustMyCode change flow. * JustMyCode disabled, first 3 cases solved. * Finished behavior for JMC disabled (with 1 difference). * JMC enabled: stepIn np bp + stepIn bp + resume bp. * Functional version (with minor deviations from expected behavior). * Refactoring. * All tests for NonUserCode work. * Fix line number after adding code above. * Stepper boundary with tests. * Save information about multiple decorators. * Fix error in merge. * Polish the PR build doc (#64036) * [wasm] WebSocket tests on NodeJS (#63441) - NPM package with WS. - Restore npm during build. - Load npm modules in test-main.js. Co-authored-by: Pavel Savara * Fix dependency in runtime-official.yml (#64040) After https://github.com/dotnet/runtime/pull/62564 the `hostedOs` value is included in the job name. * [API Implementation]: System.Diagnostics.CodeAnalysis.StringSyntaxAttribute (#62995) * Add StringSyntaxAttribute * Fix attribute declaration and add usage * Address PR feedback Co-authored-by: Stephen Toub * Reduce the memory footprint of HttpHeaders (#62981) * Change HttpHeaders backing store to an array * Reduce the size of HeaderDescriptor to 1 object * Update UnitTests, fix GetOrCreateHeaderInfo * Switch to a dictionary after ArrayThreshold headers * Add unit tests * Use storeValueRef naming consistently * Workaround field layout regression (#63005) * Mark _descriptor on HeaderDescriptor as nullable * Remove HeaderDescriptor.Descriptor and add HasValue, IsKnownHeader, Equals * Simplify HttpHeaderParser.Separator logic * Add comments on HasValue checks * Lazily group headers by name * Add a header ordering+grouping test * Make use of the _count field * Revert all HeaderDescriptor changes from PR * Switch back to always grouping by name * Assert that the collection is not empty in GetEnumeratorCore * Optimize AddHeaders for empty collections * Reference the Roslyn bug issue * Assert that multiValues are never empty * Don't preserve a Dictionary across Clear * Add comment about why a custom HeaderEntry type is used * Disable DirectoryLongerThanMaxLongPathWithExtendedSyntax_ThrowsException (#64044) * Add test coverage for frozen objects and GC interaction (#64030) * Test coverage for frozen objects and GC interaction * Update Preinitialization.cs * Remove Type.MakeGenericType dependency from source generation (#64004) * Remove Type.MakeGenericType dependency from srcgen * address feedback * add trimmer warning suppression * address feedback * Add ns2.0 support to System.Formats.Cbor (#62872) * Add ns2.0 support to System.Formats.Cbor * Add NetFrameworkMinimum to tfms * Add ReadHalf and WriteHalf to compatibility suppressions * Remove unwanted comment * Exception sets: debug checker & fixes (#63539) * Add a simple exception sets checker * Add asserts to catch missing nodes * Fix normal VN printing * Fix JTRUE VNs * Fix PHI VNs * Update VNs for "this" ARGPLACE node * Tolerate missing VNs on PHI_ARGs We do not update them after numbering the loops. (Though perhaps we should) * Tolerate unreachable blocks * Fix exception sets for VNF_PtrTo VNFuncs * Add VNUniqueWithExc * Add VNPUniqueWithExc * Fix arrays * Consistently give location nodes VNForVoid And always add exception sets for them. This will simplify the exception set propagation code for assignments. * Fix CSE * Fix GT_RETURN * Fix LCLHEAP * Fix GT_ARR_ELEM * Fix unique HWI * Fix unique SIMD * Fix GT_SWITCH * Fix CKFINITE * Fix HWI loads * Fix fgValueNumberAddExceptionSetForIndirection The method does not need to add the exception set for the base address. Additionally, the way it did add the sets, by unioning with normal value numbers, lost all exceptions not coming from the base address. This was fine for the unary loads, but broke the HWI loads that could have exceptions coming from not just the address. * Fix GT_RETFILT * Fix INIT_VAL * Fix DYN_BLK * Fix FIELD_LIST * De-pessimize CkFinite * Add a test for HWIs * Add a test for LCLHEAP * Change test to check for store block operators (#60878) * Update XUnit to 2.4.2-pre.22 (#63948) * Update to Xunit build 2.4.2-pre.13 Also pick up latest pre-release of analyzers * Disambiguate calls to Assert.Equals(double,double,int) Xunit added a new Assert overload that caused a lot of ambiguous calls. https://github.com/xunit/xunit/issues/2393 Workaround by casting to double. * Fix new instances of xUnit2000 diagnostic * Workaround xUnit2002 issue with implicit cast Works around https://github.com/xunit/xunit/issues/2395 * Disable xUnit2014 diagnostic This diagnostic forces the use of Assert.ThrowsAsync for any async method, however in our case we may want to test that a method will throw synchronously to avoid regressing that behavior by moving to the async portion of the method. * Use AssertExtensions to test for null ArgumentException.ParamName Workaround https://github.com/xunit/xunit/issues/2396 * Update to Xunit 2.4.2-pre.22 * Fix another ArugmentException.ParamName == null assert * Preserve OBJ/BLK on the RHS of ASG (#63268) One of my upcoming changes will need this information to accurately detect type mismatch in "fgValueNumberBlockAssignment". * Revert "Temporarily disable coredumps during library testing on macOS (#63742)" (#64057) This reverts commit 2c28e63f9360280011a3b03c1ca6dc0edce1fae4. Fixes #63761 * Performance: Fix Browser Wasm job not being found for dependent jobs (#64058) * Figure out the name that browser wasm now uses. * linux to the Browser wasm depends on name. Update the browser wasm dependson name to match the new one found in the pipeline. * Fix exception propagation over HW exception frame on macOS arm64 (#63596) * Fix exception propagation over HW exception frame on macOS arm64 There is a problem unwinding over the PAL_DispatchExceptionWrapper to the actual hardware exception location. The unwinder is unable to get distinct LR and PC in that frame and sets both of them to the same value. This is caused by the fact that the PAL_DispatchExceptionWrapper is just an injected fake frame and there was no real call. Calls always return with LR and PC set to the same value. The fix unifies the hardware exception frame unwinding with Linux where we had problems unwinding over signal handler trampoline, so PAL_VirtualUnwind skips the trampoline and now also the PAL_DispatchExceptionWrapper frame by copying the context of the exception as the unwound context. * Reenable DllImportGenerator.Unit.Tests * Add StringSyntax attribute to Regex.pattern field (#64063) I missed adding this one in my initial audit. It'll be exceedingly rare for a developer to manually write code that assigns a string to this protected field, but every source-generated regex does so, and thus any colorization VS provides will benefit looking at the source-generated code. * Sync shared code from aspnetcore (#64059) Co-authored-by: JamesNK * Read the System.GC.CpuGroup settings in runtimeconfig.json (#64067) * Log message of unexpected exception in ThrowsAny (#64064) * Log message of unexpected exception in ThrowsAny * Update AssertExtensions.cs * Enable some browser legs on the extra-platforms pipeline (#64065) * Enable some browser legs on the extra-platforms pipeline * Flow platform parameter from helix queues templates * Fix another condition * Allow CreateScalarUnsafe to be directly contained by hwintrinsics that support scalar loads (#62407) * Ensure that floating-point constants can be contained by hardware intrinsics * Allow CreateScalarUnsafe to be directly contained by hwintrinsics that support scalar loads * Rename IsContainableHWIntrinsicOp to TryGetContainableHWIntrinsicOp and improve handling * Ensure that NI_AVX2_BroadcastScalarToVector128/256 are properly tracked as MaybeMemoryLoad * Applying formatting patch * Ensure a few other "maybe memory" and special memory operand size cases are handled * Applying formatting patch * Remove commented code (#63869) * Add pmi_path argument to superpmi.py script and use it in the superpmi-collect pipeline. (#63983) * Add -pmi_path argument to superpmi.py collect command and use it to set PMIPATH environment variable in src/coreclr/scripts/superpmi.py * Set pmi_path to $(SuperPMIDirectory)\crossgen2 * Print a warning if -pmi_path or -pmi_location is specified while --pmi is not in src/coreclr/scripts/superpmi.py * Move setting of PMIPATH environment variable under `if self.coreclr_args.pmi is True:` in src/coreclr/scripts/superpmi.py * Move pmi argument validation to setup_args() in src/coreclr/scripts/superpmi.py * Clone root_env if we are going to set PMIPATH environment variable in src/coreclr/scripts/superpmi.py * Update the macOS CoreCLR building documentation. (#63932) This updates the documentation to refer to the up-to-date location of requirements and prerequisites. * Introduce RandomAccess.SetLength (#63992) * don't Flush readonly MemoryMappedViewAccessor on disposal (#63794) * don't Flush if it's impossible to write * address code review feedback: apply same optimization to MemoryMappedViewStream * Implement System.Runtime.CompilerServices.DisabledRuntimeMarshallingAttribute on CoreCLR-family of runtimes/type systems (#63320) * Add the DisableRuntimeMarshallingAttribute to the build. * Add initial test suite * Implement support in IL stubs for the "disabled runtime marshalling" feature. * Add testing for inlining IL stubs. * Block SetLastError and LCID support when DisableRuntimeMarshallingAttribute is applied. * Bump NativeAOT-only R2R version header (missed previously) * Implement support in crossgen2 and NativeAOT * Clean up the test tree and update the tests to fail more reliably when bugs are present. Fix a bug that was uncovered when the tests were refactored. * Fix NativeAOT and clean up crossgen2 * Add a test for NoPreserveSig with DisableRuntimeMarshalling * Assign hr in SUCCEEDED macro. * PR feedback. * Block varargs in disabled marshalling mode. * Fix typo * Block types that have a field that is auto-layout somewhere in their layout. * Fix typo * Revert the AutoLayoutOrHasAutoLayoutFIeld check in the "marshalling enabled" case * Only set scope when it isn't null (it's null for some cases). * Fix narrowing conversion failure. * First pass simple implementation in Mono * Fix assert to still work for the built-in marshalling system * S_FALSE is a thing * Fix type load failures caused by eager type handle loading. * Get MethodILScope from the calling method when available (this covers all cases where we need it) * Add const modifier. * Try 2 to fix const modifiers * Fix compilation of NativeAOT jitinterface * Fix type lookup in Mono * Use try_get model for getting the attribute type in the case of failure. Fix mono implementation for looking up the attribute. * Handle void and generic instantiations * Update auto-layout check to check recursively in layout. * Enhance test suite with more tests for UnmanagedCallersOnly, generics, and the like. Fix AutoLayout test. * Fix IL and a few typos * Set a value in the padding for easier debugging. * Create sig->marshalling_disabled to track when marshalling is disabled, which is separate from the concept of "is this signature a P/Invoke" * Fix running test suite on Mono + Mini JIT * Fix recursive type load failure by only checking the "has auto-layout or field with auto-layout" for value types. * Fix mono windows build. * Feedback from Michal. * Fix bug in EcmaAssembly.HasAssemblyCustomAttribute * Make the runtime flavor check in the wrapper generator case-invariant * Use helper method since various different platforms/configurations throw different exceptions for these scenarios. * Fix AutoLayout test refactor and use a dummy value for the padding field in both enabled and disabled scenarios. * Add an explicit test for using enums as they're a little weird and needed some special-casing. * Fix build-time test filtering in xunit wrapper generator. * Fix some x86-specific issues * Add a nice big comment block. * Fix x86 * Refactor tests so we can skip one on Mono since Char->char lossy conversion is not supported. * Disable test in issues.targets until an alternative solution is reached. * Add another SkipOnMono attribute in the "Enabled" test suite. * Apply UnmangedFunctionPointerAttribute to help hint to the Mono LLVM AOT compiler to compile the managed->native thunks at aot-time * Unify on "runtime marshalling" terminology * Clean up unused usings. * Address Jan's feedback except for applying the attribute to CoreLib. * PR feedback. * Mono throws an InvalidProgramException for varargs * Fix copy-paste issue. * Make sure we use the P/Invoke's Module and not the caller's module when deciding if runtime marshalling is enabled for a varargs P/Invoke call. * Handle how LLVM AOT reports the failure to handle varargs (EEE) * Make ILLink validation steps in libs incrementally buildable (#64041) * Make ILLink validation steps in libs incrementally buildable Both the illink-oob and the illink-sharedframework targets don't define Inputs and Outputs which makes them run during no-op incremental builds. This change defines Inputs and Outputs based on what's used during the target's execution so that if the input assemblies or the illink assembly itself haven't changed, the step will be skipped. Also renaming properties and items to make them more readable and consistent. As these target files are "extensions" of the src.proj file and aren't shared anywhere, they can be treated like logic inside a project file and hence prefixing properties and items with an underscore "_" isn't necessary. * Fix broken callstacks in interpreter on MonoVM. (#60338) * Fix some broken callstacks in interpreter. * Fix build error. * Initial WASI support prototype (#63890) * Add StringSyntaxAttribute.Json (#64081) * [main] Update dependencies from 5 repositories (#64002) Co-authored-by: dotnet-maestro[bot] Co-authored-by: Přemek Vysoký * Fix crash when VS4Mac is debugging VS4Mac arm64 (#64085) Fix crash when VS4Mac is debugging VS4Mac arm64 Issue: https://github.com/dotnet/runtime/issues/64011 * ILVerify: Handle readonly references in ldfld (#64077) * ILVerify: Handle readonly references in ldfld Fixes #63953 * Fix test name Co-authored-by: Michal Strehovský * Avoid additional local created for delegate invocations (#63796) Very often 'this' is already a local and we can avoid creating another local. * [wasm][debugger] Apply changes on wasm using sdb protocol. (#63705) * Apply changes on wasm using sdb protocol. * conflict * Merge conflict. * Fix merge * Fix compilation error. * Fixed IsFloatPositiveZero from returning 'true' on non-constant double operands (#64083) * Fixed IsFloatPositiveZero from returning 'true' on non-constant double operands * Update src/coreclr/jit/gentree.h Co-authored-by: Egor Bogatov Co-authored-by: Egor Bogatov * Ensure several helper intrinsics are correctly imported and handled (#63972) * Ensure several helper intrinsics are correctly imported and handled * Ensure that Sum for TYP_INT/UINT on Arm64 is correctly handled * Respond to PR feedback and ensure ExtractMostSignificantBits for Vector64 on Arm64 also uses AddPairwise * Applying formatting patch * Ensure the clsHnd is correct * Fix the remaining musl failures * Ensure that we aren't sign-extending TYP_BYTE (System.SByte) for ExtractMostSignificantBits * Ensure an assert is correct on x64 * Ensure Vector64.Dot on Arm64 uses AddPairwise, not AddAcross * Apply formatting patch * RegexNode cleanup (#64074) No functional changes, just code cleanup: - Move node types into a RegexNodeKind enum - Rename some of the kinds to make them more descriptive - Rename node.Next to node.Parent to better describe its purpose - Add a bunch of comments about node kinds * Refactor optimizing morph for commutative operations (#63251) * Create "fgOptimizeCommutativeArithmetic" And just move code from "fgMorphSmpOp" to it. Just one diff: better comma throw propagation in an ILGEN method. * Refactor the function Split it into specialized variants for each operator, delete redundant code, fix up one case of wrong typing for a constant in the MUL -> SHIFT optimization. One CSE diff due to different VNs because of the typing change for the constant (int -> long). Many text diffs: "mov x3, 5" => "mov w3, 5". * Do not set GTF_NO_CSE for sources of block copies (#63462) It is not necessary, the compiler fully supports locals on the RHS of a struct assignment. Not marking these results in a CQ improvement, from struct (including SIMD) CSEs and global constant propagation into promoted fields. * Handle embedded assignments in copy propagation (#63447) * Clean things up a little Delete redundant conditions, use "LclVarDsc*", rename locals for clarity. * Delete a redundant condition For actual def nodes, GTF_VAR_CAST will never be set, it is only set in "optNarrowTree" for uses. For "def nodes" that are actually uses (parameters), the VNs will never match anyway. * Handle embedded assignments in copy propagation Previously, as the comments in copy propagation tell us, it did not handle "intervening", or not-top-level definitions of locals, instead opting to maintain a dedicated kill set of them. This is obviously a CQ problem, but also a TP one, as it meant there had to be a second pass over the statement's IR, where the definitions would be pushed on the stack. This change does away with that, instead pushing new definitions as they are encountered in execution order, and simultaneously propagating on uses. Notably, this means the code now needs to look at the real definition nodes, i. e. ASGs, not the LHS locals, as those are encountered first in canonical execution order, i. e. for a tree like: ``` ASG LCL_VAR V00 "def" ADD LCL_VAR V00 LCL_VAR V00 ``` Were we to use the "def" as the definition point, we would wrongly push it as the definition on the stack, even as the assignments itself hasn't happened yet at that point. There are nice diffs with this change, all resulting from unblocked propagations, and mostly coming from setup arguments under calls. * Simplify optIsSsaLocal * Update format script permissions so it can be called on Unix systems directly. (#64107) * Revert "Enable System.Text.Json tests on netfx (#63803)" (#64108) This reverts commit 34794bc5f2bcdbaa9057bb07b8764e2bb6a411a2. * Make ApiCompat.proj incrementally buildable (#64037) * Make ApiCompat.proj incrementally buildable In https://github.com/dotnet/runtime/pull/64000, I noticed that ApiCompat.proj never builds incrementally. Even though the RunApiCompat target has Inputs and Outputs, those aren't defined too late inside the target to have any effect. Moving them out and declare the generated response file as an output. Also simplifying some msbuild logic and renaming some properties as underscore prefixes in project files don't make sense if the property isn't reserved in any way. * Update ApiCompat.proj * Remove enable drawing on unix switch (#64084) * Remove enable drawing on unix switch * Update some tests and not run tests that need Drawing on non Windows * PR Feedback, just turn off the switch * Address-expose locals under complex local addresses in block morphing (#63100) * Handle complex local addresses in block morphing In block morphing, "addrSpill" is used when the destination or source represent indirections of "complex" addresses. Unfortunately, some trees in the form of "IND(ADDR(LCL))" fall into this category. If such an "ADDR(LCL)" is used as an "addrSpill", the underlying local *must* be marked as address-exposed. Block morphing was using a very simplistic test for when that needs to happen, essentially only recognizing "ADDR(LCL_VAR/FLD)". But it is possible to have a more complicated pattern as "PrepareDst/Src" uses "IsLocalAddrExpr" to recognize indirect stores to locals. Currently it appears impossible to get a mismatch here as morph transforms "IND(ADD(ADDR(LCL_VAR), OFFSET))" into "LCL_FLD" (including for TYP_STRUCT indirections), but this is a very fragile invariant. Transforming TYP_STRUCT GT_FIELDs into GT_OBJs instead of GT_INDs breaks it, for example. Fix this by address-exposing the local obtained via "IsLocalAddrExpr". * Add a TODO-CQ for LCL_FLD usage * [Group 2] Enable nullable annotations for `Microsoft.Extensions.DependencyInjection` (#63836) * Annotate src * Update ResolverBuilder.Build * Update RunOnEmptyStackCore * ILEmitResolverBuilderContext constructor * Remove setter * Add assert * Enable nullable annotations for Microsoft.Extensions.Configuration.UserSecrets (#63700) * [mono] Cleanup trailing whitespace. (#64112) * Delete `GT_DYN_BLK` (#63026) * Import GT_STORE_DYN_BLK directly * Delete GT_DYN_BLK * DynBlk -> StoreDynBlk * Add some tests * Mark tests Pri-1 * Rebase and fix build * Bring back the odd early return * Ignore conversion exceptions during dictionary construction (#63792) * Extract SuperPMI into a separate component (#64035) Allows building the runtime without SPMI. `build.cmd clr` will still build SPMI. `build.cmd clr.native` will still build SPMI. `build.cmd clr.runtime` will no longer build SPMI. This is mostly motivated by NativeAOT subset builds where SPMI contributes to 10% of the native build time (nativeaot CorecLR subset builds pretty quickly compared to full CoreCLR). * Add COMWrappers to crossgen (#63969) * pipelines: Add wasm jobs (#64109) * Fixing update issue with multivalued properties #34267 (#56696) * Add custom attribute test * Adding test demonstrating issue #34267 * Solution for issue #34267 Replacing all values in property with the new collection, instead of just appending new values, leaving old values in place. * Incorporate review feedback Changing the variable name * Relax assert in ApplyEditAndContinue (#64132) Fixes #64070 * Disable NJulianRuleTest test crashing in CI (#64142) * Updating unit tests for DirectoryServices.AccountManagement (#56670) Removing old, redundant unit tests that were actually never executed Migrating old tests to new test infrastructure with configurable LDAP/AD connections * Fix MultiByteToWideChar call in pal (#64146) * Extra tests for assembly name parser. (#64022) * Dead code in native assembly name parsing * disallow `\u` escaping in assembly names * misc cleanup * forward slash is illegal escaped or not * ignore "language" attribute in assembly name ("culture" must be used) * duplicate attributes are ok if unrecognized (just add tests) * drop support for "custom" blob attribute * drop support for publickey[token]=neutral ("null" must be used) * ignore unknown assembly name attributes in mono (compat) * disallow \0 anywhere in the assembly name * disallow \0 in assembly names on mono (compat) * only check for embedded nulls when parsing * fix mono build * make GCC happy * couple test scenarios for publickey vs. publickeytoken (CoreRT parser might trip on these) * produce errors on duplicate known attributes in mono * Dispose LdapConnections used by ValidateCredentials (#62036) Ensure that cached LdapConnection instances created by PrincipalContext.ValidateCredentials are disposed when the corresponding PrincipalContext is disposed. Fix #62035 * Add runtime support for `ref` fields (#63985) * Add mono and coreclr runtime support for ref fields * Update Reflection.Emit tests to validate ref fields. Add test for TypedReference as a ref field. * Spmi replay asmdiffs mac os arm64 (#64119) * Split unix-arm64 into linux-arm64 and osx-arm64 in src/coreclr/scripts/superpmi-replay.proj * Split unix-arm64 into linux-arm64 and osx-arm64 in src/coreclr/scripts/superpmi-asmdiffs.proj * Add all subdirectories of $(SuperPMIDirectory) as PMIPATH in src/coreclr/scripts/superpmi-collect.proj * Update NativeAOT codegen and Crossgen2 for CreateSpan (#63977) - Make sure FieldRVA pointers remain aligned as required by the code generator - Use the same Packing Size approach as the IL Linker will use (See jbevain/cecil#817 for details) - Compilers that generate CreateSpan will need to follow that trick to be compatible with rewriters. - Provide ECMA spec augment describing packing size detail * Add alignment to mapped field stream (#63305) * Align MappeFieldDataStream at 8 byte boundary * Add test to verify that the mapped field rva data blob is aligned to ManagedPEBuilder.MappedFieldDataAlignment * Only align when the mapped field data is of size not equal to 0 * Implement hash and HMAC stream one shots This implements hashing and HMAC statics for streams. Additionally, "LiteHmac" and "LiteHash" were introduced. The existing HMAC and hash provider functionality do some bookkeeping we don't need for resetting. Since we do not need to use these hash handles after the digest has been finalized, resetting is unnecessary work. For HMAC, that also means keeping a copy of the key around for some implementations which we don't need to do. The LiteHash and LiteHmac types are implemented as structs with a common interface. To avoid boxing, generics are used and constrained to the interface where possible. The Browser implementation just defers to the existing HashDispenser rather than do anything novel. The HashProviderCng is somewhat specialized in its ability to reset. It did up-front check to determine if the platform supported reusable hash providers, and further had a single implementation for HMAC and Digests. The current Lite hash design requires that they remain separate types. * Title and message resources should be enforced to exist to prevent printing empty messages (#64151) Sync ILLink.Shared folder with the latest version in dotnet/linker main branch List of changes include: - Enforce title and message resources to exist to prevent printing empty messages - All diagnostics produced by linker now have a DiagnosticId, a title and a message - Schema for xml link attributes file - Added a readme file to the ILLink.Shared project to keep track of the commit is being used from dotnet/linker * Allow generating Dwarf version 5 (#63988) Contributes to https://github.com/dotnet/runtimelab/issues/1738. * Re-enable failing long path test (#64113) * Port MD4 managed implementation from mono/mono (#62074) Porting MD4 managed implementation from mono/mono (MD4.cs and MD4Managed.cs). It adds: - an internal class in the System.Net.Security with a single HashData method for now; - a set of related MD 4 unit tests to System.Net.Security.Unit.Tests project. * Fix one source of perf regression in GCHeap::Alloc. This impacts the System.Collections.CtorFromCollectionNonGeneric family of benchmarks. (#64091) These benchmarks manage to make GCHeap::Alloc into a hotspot, so the call to IsHeapPointer() at the end matters for performance. * Add blsr (#63545) * Fix FileSystemAclExtensions.Create when passing a null FileSecurity (#61297) * Make FileSecurity parameter nullable. * Add missing ArgumentException message for FileMode.Append. * Refactor tests to ensure FileSecurity is tested with all FileMode and FileSystemRights combinations. Separate special cases. * Remove exception that throws when FileSecurity is null. Ensure we have logic that can create a FileHandle when FileSecurity is null. Fix bug where FileShare.Inheritable causes IOException because it is being unexpectedly passed to the P/Invoke (it should just be saved in the SECURITY_ATTRIBUTES struct). Add documentation to mention this parameter as optional. Ensure all exceptions match exactly what we have in .NET Framework, with simpler logic. * Address suggestions Co-authored-by: carlossanlop * Tune FP CSEs live across a call better (#63903) The problem was that the comparison of a weighted refcount, which usually has the order of hundreds or tens, with a small digit like "4" was too weak and missed some cases where we were still trying to CSE cheaps floats across calls and ending up with lots of stack shuffling. Fix this by using different tuning parameters, namely the costs estimated for the uses and defs (increase them to account for the spills and reloads). * [main] Update dependencies from dotnet/arcade dotnet/icu dotnet/xharness dotnet/emsdk (#64098) Co-authored-by: dotnet-maestro[bot] * Update zip extraction to never throw any exceptions when the LastWriteTime update fails (#63912) * Use kebab-case in FB automation labels (#64048) * Onboard new Triage & PR Boards (#64198) * Exclusively use GitHub teams for Libraries area mentions (#64199) * Reduce buffer size used in XmlReader when using Async mode (#63459) The current choice of AsyncBufferSize resulted in the character buffer in the XmlTextReader being allocated on the Large Object Heap (LOH) Fixes https://github.com/dotnet/runtime/issues/61459 * Ignoring leading dot when comparing cookie domains (#64038) * ignoring leading dot when comparin cookie domain * Simplify cookie comparing logic to equality and moving it to CookieComparer to fix the build * Domain comparing optimizarion and more unit tests * small check optimization * Renaming method * Add missing handle function enter/return macros (#64061) The mono_field_static_get_value method uses a handle, but did not set up enter/exit macros properly, so this handle was leaked. Some code in Unity calls this embedding API method pretty often, which can lead to the mark stack overflowing in the GC code. * Drop support for .NET 5 SDK (#64186) We had to duplicate a lot of Microsoft.NET.ILLink.targets logic. * Implement IEquatable on value types overriding Equals (and enable CA1066/1077) (#63690) * [mono] Temporarily disable two tests that fail on arm64 LLVM FullAOT. (#64180) * Delete stale reference in System.Drawing.Primitives (#64202) * Respond to feedback in GenerateMultiTargetRoslynComponentTargetsFile (#63943) * Respond to feedback in GenerateMultiTargetRoslynComponentTargetsFile Two small follow up changes from #58446 - Fix a type-o that breaks incremental build. Forgot to use MSBuild property syntax - Instead of having the infrastructure hard-code removing 'Abstractions', packages can set their own Disable source gen property name. * PR feedback * Use the static HashData(Stream) method in more places * Add executable bit to tizen sh files (#64216) * Bump Intellisensense package version to latest from `dotnet7-transport` (#63352) * Ensure that we aren't accidentally generating instructions for unsupported ISAs (#64140) * Assert that the ISA of the set intrinsic ID is supported * Ensure gtNewSimdCmpOpAllNode and gtNewSimdCmpOpAnyNode don't generate AVX2 instructions when not supported * Ensure codegen for Vector128.Dot when SSSE3 is disabled is correct * Update src/coreclr/jit/hwintrinsiccodegenarm64.cpp Co-authored-by: Jan Kotas * Ensure Vector256.Sum has a check for AVX2 Co-authored-by: Jan Kotas * Don't reference .NETFramework shims in libraries product or test composition (#64193) * Don't reference .NETFramework shims Stop referencing .NETFramework shims in libraries ref or source projects as those are supplementary and shouldn't impact the product composition. * [Android][libs] Enable Internal.Console.Write in System.Private.CoreLib (#63949) * [Android][libs] Enable Internal.Console.Write in System.Private.CoreLib * [docs] Add debugging System.Private.CoreLib Internal.Console.Write * Elaborate on debugging corelib log * Address feedback * Install v8 and Prebuild wasm (#64100) * Port Mono to Raspberry Pi, ship as new linux-armv6 RID (#62594) * Initial ARMv6 arch addition. Builds mono runtime, not CoreCLR (Mono already supports the CPU arch subset used by Raspberry Pi, whilst porting CoreCLR to e.g. VFPv2 would be major work) * Build small clr subset on ARMv6, it's needed for SDK and we want to check it works * Fix remote unwind (#64220) The _OOP_find_proc_info was setting only a couple of members of the unw_dyn_info_t instance on stack. So the remaining ones had random values. The load_offset was a recently added member to the struct. When we have updated libunwind, this change came in. The load_offset was random and that has broken unwindign as this offset is subtracted from the IP when looking up unwind info. The fix clears the whole struct. I have verified that the issue we had no longer happens with the fix. * Put back FindCaseSensitivePrefix regex alternation support (#64204) * Put back FindCaseSensitivePrefix alternation support * Fix the bug from the initial version, and add more comments * Update tests to expect RemoteExecutor to check exit code (#64133) * update generation_allocation_size correctly for SIP regions (#64176) SIP regions need to update the corresponding generation's generation_allocation_size and since this can be more than 1 gen older than the region's gen, we need to make all generation's alloc size get updated. * Android remove backward timezones (#64028) Fixes #63693 It was discovered that Android produces duplicate TimeZone DisplayNames among all timezone IDs in GetSystemTimeZones. These duplicate DisplayNames occur across TimeZone IDs that are aliases, where all except one are backward timezone IDs. If a name is changed, put its old spelling in the 'backward' file From the Android TimeZone data file tzdata, it isn't obvious which TimeZone IDs are backward (I find it strange that they're included in the first place), however we discovered that on some versions of Android, there is an adjacent file tzlookup.xml that can aid us in determining which TimeZone IDs are "current" (not backward). This PR aims to utilize tzlookup.xml when it exists and post-filter's the Populated TimeZone IDs in the AndroidTzData instance by removing IDs and their associated information (byteoffset and length) from the AndroidTzData instance if it is not found in tzlookup.xml. This is using the assumption that all non-backward TimeZone IDs make it to the tzlookup.xml file. This PR also adds a new TimeZoneInfo Test to check whether or not there are duplicate DisplayNames in GetSystemTimeZones * Update main branding to preview2 (#64219) * Catch UnicodeEncodeErrors (#64251) * Make XmlSerializer.Generator targets incremental (#64191) * Make XmlSerializer.Generator targets incremental Adding inputs and outputs to make XmlSerializer.Generator incremental * Make sure that shared memory object name meets the length requirements (#64099) Co-authored-by: Stephen Toub * Fix PAL_wprintf for wide characters (#64181) * [main] Update dependencies from dotnet/runtime dotnet/llvm-project (#64205) * Update dependencies from https://github.com/dotnet/runtime build 20220123.5 Microsoft.NETCore.ILAsm , Microsoft.NETCore.DotNetHostPolicy , Microsoft.NETCore.DotNetHost , Microsoft.NETCore.App.Runtime.win-x64 , System.Runtime.CompilerServices.Unsafe , runtime.native.System.IO.Ports , Microsoft.NET.Sdk.IL , System.Text.Json From Version 7.0.0-alpha.1.22066.4 -> To Version 7.0.0-alpha.1.22073.5 * Update dependencies from https://github.com/dotnet/llvm-project build 20220123.1 runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22070.1 -> To Version 1.0.0-alpha.1.22073.1 Co-authored-by: dotnet-maestro[bot] * Delete unused ApiCompat baseline files (#64190) * Delete unused ApiCompat baseline files * Delete ApiCompatBaseline.netfx.netstandardOnly.txt * Remove manual .NETFramework baseline validation * Delete ApiCompatBaseline.netcoreapp.netfx461.ignore.txt * Delete ApiCompatBaseline.netcoreapp.netfx461.txt * Improve Regex handling of anchors (#64177) * Improve Regex handling of anchors - Extend search for leading anchor to support alternations. This means that an expression like `^abc|^def` will now observe the leading `^` whereas previously it didn't. - Add a FindFirstChar optimization that jumps to the right position for a pattern that matches a computeable max length and ends with an end anchor. * Address PR feedback * Add the exception set for `ObjGetType` (#64106) * Model NRE for ObjGetType * Add tests * [ILVerify] Fix casting check for arrays of generic parameters with class constraints (#64259) Fixes #63999 * Use lower call count threshold for tiering in debug builds (#60945) * Use lower call count threshold for tiering in debug builds To exercise more paths during tests, see https://github.com/dotnet/runtime/pull/60886 * Skip tests using AsyncIO in FileSystemAclExtensionsTests where it's not supported (#64212) The mono runtime does not yet support AsyncIO on Windows and there were some tests failing on CI because of it. Fixes #64221 * Correct JsonNode.Root doc (#64238) * Take ARMv6 out of PlatformGroup All (#64267) * Take ARMv6 out of PlatformGroup All, CoreCLR assumes this means full support Co-authored-by: Alexander Köplinger * Only send to Helix for rolling build, due to small Helix queue (#64274) * Add ref field runtime feature indication (#64167) * Add ref field runtime feature indication Co-authored-by: Stephen Toub * Faster IndexOf for substrings (#63285) * Improve "lastChar == firstChar" case, also, use IndexOf directly if value.Length == 1 * Try plain IndexOf first, to optimize cases where even first char of value is never met * add 1-byte implementation * copyrights * fix copy-paste mistake * Initial LastIndexOf impl * More efficient LastIndexOf * fix bug in Char version (we need two clear two lowest bits in the mask) & temporarily remove AdvSimd impl * use ResetLowestSetBit * Fix bug * Add two-byte LastIndexOf * Fix build * Minor optimizations * optimize cases with two-byte/two-char values * Remove gotos, fix build * fix bug in LastIndexOf * Make sure String.LastIndexOf is optimized * Use xplat simd helpers - implicit ARM support * fix arm * Delete \ * Use Vector128.IsHardwareAccelerated * Fix build * Use IsAllZero * Address feedback * Address feedback * micro-optimization, do-while is better here since mask is guaranteed to be non-zero * Address feedabc * Use clever trick I borrowed from IndexOfAny for trailing elements * give up on +1 bump for SequenceCompare * Clean up * Clean up * fix build * Add debug asserts * Clean up: give up on the unrolled trick - too little value from code bloat * Add a test * Fix build * Add byte-specific test * Fix build * Update IndexOfSequence.byte.cs * [main] Update dependencies from dotnet/arcade dotnet/xharness dotnet/icu dotnet/hotreload-utils dotnet/llvm-project (#64265) * Update dependencies from https://github.com/dotnet/arcade build 20220124.13 Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.ApiCompat , Microsoft.DotNet.XUnitExtensions , Microsoft.DotNet.GenAPI , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.GenFacades , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.Helix.Sdk From Version 2.5.1-beta.22071.6 -> To Version 2.5.1-beta.22074.13 * Update dependencies from https://github.com/dotnet/xharness build 20220124.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 1.0.0-prerelease.22071.1 -> To Version 1.0.0-prerelease.22074.1 * Update dependencies from https://github.com/dotnet/icu build 20220124.5 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-preview.2.22071.2 -> To Version 7.0.0-preview.2.22074.5 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220124.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.0.2-alpha.0.22069.1 -> To Version 1.0.2-alpha.0.22074.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20220124.2 runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22067.2 -> To Version 11.1.0-alpha.1.22074.2 Co-authored-by: dotnet-maestro[bot] * Add CancellationToken to TextReader.ReadXAsync (#61898) Co-authored-by: Adam Sitnik Co-authored-by: Stephen Toub * Restrict parallelism in LLVM FullAOT compile, to prevent OOM (#63800) * Restrict parallelism in FullAOT compile, to prevent OOM * Reduce parallelism further, due to more OOM * Moved AssemblyName helpers to managed (#62866) * Moved ComputePublicKeyToken to managed * Managed assembly name parsing (adapted from nativeaot) * Fix for HostActivation failures. * PR feedback (RuntimeAssemblyName is back to CoreRT + other comments) * remove AssemblyNameNative::Init form the .hpp * remove AppX compat ifdef * renamed instance fields to convention used in C# * `Argument_InvalidAssemblyName` should be `InvalidAssemblyName`. Majority of use is `FileLoadException`. * remove `this.` * PR feedback (assign to fileds, bypass properties) * missed this change in the rebase * "low-hanging fruit" perf tweaks. * move one-user helpers to where they are used. * removed ActiveIssue for #45032 * remove AssemblyNameHelpers.cs form corelib * Remove the List when detecting duplicates. Support PublicKey. * whitespace * Fix managed implementation to match the new tests. * Some minor cleanup. * Do not validate culture too early * PR feedback * use SR.InvalidAssemblyName * Report the input string when throwing FileLoadException * tweaked couple comments * Disable RegexReductionTests tests on browser * Fix formatting of resource string where excess arguments are passed (#63824) * Fix formatting of resource string where excess arguments are passed. #63607 * Fix BuildCharExceptionArgs and ECCurve.Validate * Fix CA2208 * Fix CA2208. Remove paramName becaus it is in error message * Code review fixes * Code review fixes * Add Regex.Count string overloads (#64289) * Clarify purpose of PDB Document hashing (#64306) Fixes #63505 * Fix arm64/PInvoke so that NESTED_ENTRY/NESTED_END labels match. (#64296) This was exposed by building on arm64 with gcc-12, wherein the assembler complained about not being able to evaluate the constant expression for .size for the symbol on NESTED_END. Since the symbol on NESTED_END is not referenced anywhere else in the code base, I concluded that it was wrong, and NESTED_ENTRY was right. I have not tested this on anything but arm64 + gcc-12 * When decommitting, leaving one instead of two pages in regions case. (#64243) * Ensure that canceled Task.Delays invoke continuations asynchronously from Cancel (#64217) * Add gen folder moving gen projects from src folder (#64231) * Fix minor typos in GC documentation. (#64298) * Explicitly specify four subdirectories to use as part of the paths for -pmi_path arguments and expand the paths on a remote machine in src/coreclr/scripts/superpmi-collect.proj (#64308) * Disable RegexReductionTests on browser (#64312) * Add UnreachableException (#63922) * [mono] Recognize new names for Xamarin.iOS etc assemblies (#64278) They are being renamed in https://github.com/xamarin/xamarin-macios/pull/13847 * Remove usage of codecvt from corerun (#64157) * Remove usage of codecvt from corerun * Update src/coreclr/hosts/corerun/corerun.cpp Co-authored-by: Aaron Robinson Co-authored-by: Aaron Robinson * Refactor FileStatus.Unix. (#62721) * Refactor FileStatus.Unix. - Moves InitiallyDirectory out of FileStatus into FileSystemInfo. In FileSystemInfo it can be a readonly field making its usage clearer. And FileStatus can then directly be used to implement some FileSystem methods without allocating an intermediate FileInfo/DirectoryInfo. - Treat not exists/exist as initialized states to avoid wrongly assuming initialized means the file cache is valid, which isn't so when the file does not exist. - Use 0 for tracking uninitialized to make default(FileStatus) uninitialized. * Fix unique VNs for `ADDR`s (#64230) * Add the test * Fix unique VNs for ADDRs They need to keep the exception sets. * Implemented hierarchy of attributes. (#64201) * Implemented hierarchy of attributes. * Shortened. * Fixed overlooked test naming and simplified. * Partial refactor. * Update the managed type system to more gracefully fail when calling a varargs method. (#64286) * Update the managed type system to more gracefully fail when calling a varargs method. * Use ThrowHelper instead of manually throwing the exception. * Update src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs Co-authored-by: Jan Kotas * [mono] Add some missing Internal.Runtime.CompilerServices.Unsafe intrinsics. (#64314) * Remove usage of FEATURE_CORESYSTEM (#63850) * Remove usage of FEATURE_CORESYSTEM from coreclr. * [main] Update dependencies from dotnet/arcade dotnet/runtime-assets (#64331) * Update dependencies from https://github.com/dotnet/arcade build 20220125.6 Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.ApiCompat , Microsoft.DotNet.XUnitExtensions , Microsoft.DotNet.GenAPI , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.GenFacades , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.Helix.Sdk From Version 2.5.1-beta.22074.13 -> To Version 2.5.1-beta.22075.6 * Update dependencies from https://github.com/dotnet/runtime-assets build 20220125.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22060.1 -> To Version 7.0.0-beta.22075.1 Co-authored-by: dotnet-maestro[bot] * Fixes bad log method generation in certain cases. (#64311) In certain cases when developer by mistake places ILogger, Exception, or LogLevel in the message template, the code generator will produce the expected warning and makes sure the code will indeed compile and run correctly. Prior to this fix, the code generator would fail to compile with when either of ILogger, Exception or LogLevel were placed in message template incorrectly. Fixes #64310 * Fix IsMutuallyAuthenticated on Linux and OSX (#63945) * WIP - prepared a failing test * Fix IsMutuallyAuthenticated on Linux * Fix failing unit tests * Minor cleanup * Port changes to OSX * Fix comment * Invoke cert selection inline, don't allocate new credentials on Linux/OSX * Fix tests on OSX * Code review feedback * Move tests to separate file * Fix build * Fix Failing tests * Support {Last}IndexOfAny with sets after {lazy} loops (#64254) When emitting backtracking loops, the loop consumes as much and then backtracks through the consumed input. Rather than doing this one character by one character, we previously added use of LastIndexOf to search for the next place the literal after the loop matches. We can also augment that to use IndexOfAny to search for a small set that comes after a loop instead of a literal. Similarly when emitting backtracking lazy loops, rather than consuming one character and trying the rest of the expression and then consuming another character and trying the rest of the expression, we previously added an optimization to use IndexOf{Any} to find the next possible location of a match based on the literal that comes after the lazy loop. And we can similarly augment that to support a small set after the lazy loop. This is particularly helpful for IgnoreCase, as we're on a path to replacing literals with sets that contain all equivalent casings of that character. * Fix race conditions in SystemEvents shutdown logic (#62773) * Fix race conditions in SystemEvents shutdown logic When the application is terminated through Restart Manager the event broadcasting window will get the `WM_CLOSE` message. The message gets handled by passing it to `DefWndProc` which calls `DestroyWindow` on the window itself thus making the window handle invalid. The `Shutdown` method expects the window handle to be valid to post `WM_QUIT` message to terminate the thread running the message loop but that's no longer possible under these conditions. Additionally there's second race condition with the `s_eventThreadTerminated` event that is created during shutdown and set conditionally. A race condition between the threads could cause it to be created when the window message thread is already shutting down and thus it would never be set. Waiting for it in the `Shutdown` method would be cause a deadlock. This thread is also completely unnecessary since a `Join` is performed on the thread itself. The fix has several changes that act together: - `s_eventThreadTerminated` event is removed completely in favor of only relying on `Thread.Join` - `WM_DESTROY` message is detected (which happens as a result of WM_CLOSE calling `DefWndProc` which in turn calls `DestroyWindow`) and handled by shutting down the message loop thread - The message loop itself is rewritten to use standard `GetMessageW` loop. The reasoning on why it was not used seems not to be valid anymore since AppDomain shutdowns are performed differently * Add unit test. * Add braces * Add marshaller for TypeLoad failure cases (#64317) This is marshaller used when there incorrect configuration of marshaller applied to fields mostly * Add additional loop table asserts (#64126) 1. Assert that top-level loops are basic block disjoint 2. Assert LPFLG_ITER related flags are legal In addition: 1. Create a `optClearLoopIterInfo` phase to clear various bits in the loop table that are known to no longer be valid, to prevent bad asserts or JitDump output on their values. 2. Move the EndPhase call in Phase::PostPhase happens early, not late. This causes any subsequent asserts due to post-phase checking to be marked with the correct phase, in cases where there was a nested phase executed (such as liveness re-computation). 3. Convert PHASE_INSERT_GC_POLLS to use EndPhase checking 4. Convert fgDetermineFirstCodeBlock to return a PhaseStatus 5. Some minor cleanup in optUpdateLoopsBeforeRemoveBlock() (this was extracted from some bigger changes) * Moved AssemblyName helpers to managed (part 2) (#63915) * implement GetAssemblyName via dynamic call to MetadataReader * A few more file-locking tests. * fix #28153 * no need for version when getting MetadataReader * rename the argument to match AssemblyName * perf tweaks * use memory-mapped file to read metadata * adjust tests for the new implementation * use "bufferSize: 1" when stream is going to be mapped. * null-conditional operator. * do Dispose before re-throwing * get rid of the platform-specific/native stuff * remove assemblyname.hpp * remove `VerifyIsAssembly()` * PR feedback * put back gStdMngIEnumerableFuncs and the others * Fix several bugs in NullabilityInfoContext. (#64143) * Fix several bugs in NullabilityInfoContext. * Reverse ASG(CLS_VAR, ...) (#63957) This helps with register allocation. Consider: ``` ***** BB01 STMT00001 ( 0x000[E-] ... ??? ) N003 ( 18, 10) [000003] -ACXG------- * ASG ref $c0 N001 ( 3, 4) [000002] ----G--N---- +--* CLS_VAR ref Hnd=0x8fec230 Fseq[hackishFieldName] N002 ( 14, 5) [000000] --CXG------- \--* CALL ref CscBench.GetMscorlibPathCore $c0 ``` The rationalizer will rewrite it to what is effectively: ``` ***** BB01 STMT00001 ( 0x000[E-] ... ??? ) N004 ( 18, 12) [000003] -ACXG---R--- * ASG ref N003 ( 3, 6) [000002] n---G--N---- +--* IND ref N002 ( 1, 4) [000006] H----------- | \--* CLS_VAR_ADDR byref Hnd=0x8fec230 N001 ( 14, 5) [000000] --CXG------- \--* CALL ref CscBench.GetMscorlibPathCore ``` And the final LIR will look like: ``` [000006] ------------ IL_OFFSET void INLRT @ 0x000[E-] N001 ( 3, 4) [000002] ----G--N---- t2 = CLS_VAR_ADDR byref Hnd=0x8fec230 N002 ( 14, 5) [000000] --CXG------- t0 = CALL ref CscBench.GetMscorlibPathCore $c0 /--* t2 byref +--* t0 ref N003 ( 18, 10) [000003] -A-XG------- * STOREIND ref [000007] ------------ IL_OFFSET void INLRT @ 0x00A[E-] N001 ( 0, 0) [000004] ------------ RETURN void $180 ``` Since this store must use a barrier, `CLS_VAR_ADDR` won't be contained and will have to be evaludated separately. Because its value is live across a call, it'll get spilled and reloaded. Reversing the ASG fixes the problem: ``` ------------ BB01 [000..00B) (return), preds={} succs={} [000006] ------------ IL_OFFSET void INLRT @ 0x000[E-] N001 ( 14, 5) [000000] --CXG------- t0 = CALL ref CscBench.GetMscorlibPathCore $c0 N002 ( 3, 4) [000002] ----G--N---- t2 = CLS_VAR_ADDR byref Hnd=0x8fec230 /--* t2 byref +--* t0 ref N003 ( 18, 10) [000003] -A-XG------- * STOREIND ref [000007] ------------ IL_OFFSET void INLRT @ 0x00A[E-] N001 ( 0, 0) [000004] ------------ RETURN void $180 ``` * Fixes a few issues for dprintf on OSX (#64076) * [Codespaces] Make it possible to run wasm samples in the browser (#64277) With these changes, running the following in the Codespace will open the local browser to a page served from the codespace hosting the WASM sample: ```console cd src/mono/sample/wasm/browser make make run-browser ``` * Set EMSDK_PATH in .devcontainer.json We provision Emscripten as part of the devcontainer prebuild. Set EMSDK_PATH to allow rebuilding the wasm runtime to work without any additional ceremony * Install dotnet-serve into .dotnet-tools-global * [wasm] Don't try to open browser if running in Codespaces * .devcontainer: add global tools dir to PATH * .devcontainer: forward port 8000 This enables running the mono wasm samples in the local browser: * [wasm] samples: also check for dotnet-serve on the path On Codespaces we install dotnet-serve on the PATH but not where `dotnet tool list` can see it * remove onAutoForward: notify - it's the default * Adjust the path of v8 depends if running in a dev container * Check if we're running in any Docker container, not just Codespaces Co-authored-by: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> * Remove workarounds for RemoteExecutor (dotnet/arcade#5865) (#64360) * Simplify the creation of diagnostics using DiagnosticId (#64250) Simplify the creation of diagnostics using DiagnosticId Add missing NativeAOT DiagnosticId, resource message, and resource title Refactor code to use new diagnostic overloads Add overloads to log errors Change IL1005 from a warning to an error Add resilient mode option to NativeAOT Add ability to create informational messages * Trying to fix issue #63788: "NetworkChange.NetworkAddressChanged event leaks threads on Linux (#63963) * Trying to fix issue #63788: "NetworkChange.NetworkAddressChanged event leaks threads on Linux" * Adding socket receive timeout to native method + functional test * Update src/native/libs/System.Native/pal_networkchange.c ManickaP replaced tabs with spaces Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> * Using setsockopt after socket was successfully set, checking setsockopt result. * Adding support for conditional network address changed functional test * Adding support for conditional network address changed functional test * Using reference checking method to determine if socket is changed as suggested by user @tmds * Test method update * Test method update due to some failing tests * Removing yield return from test * Reverting back to yield and adding ToArray() when testing if ps is available * Socket wrapper is now nullable * Update src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs Co-authored-by: vdjuric Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> * Vector256.IsHardwareAccelerated to return true only on AVX2 (#64345) * Override all `Read` methods in `NullTextReader` and `NullStreamReader` (#64301) * #51371 fixed failing test in iossimulator (#63877) * #51371 fixed failing test in iossimulator * #51371 added skiptestexception * #51371 added space after reference * #51371 fixed remaining failing tests * #51371 whitespace issue * #51371 removed extra spaces * Squashed commit of the following: commit 36cdb5fc0c38cbb44291114e48e2b202ff37db01 Author: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Thu Jan 20 11:03:02 2022 +0100 [wasm][debugger] Added support for stepper boundary attribute (#63991) * Hidden methods and step through methods behave the same way. * Perpared flow for setting JustMyCode in the future. * Tests for JustMyCode setting before debug launch. * Transformed into dynamic JustMyCode change flow. * JustMyCode disabled, first 3 cases solved. * Finished behavior for JMC disabled (with 1 difference). * JMC enabled: stepIn np bp + stepIn bp + resume bp. * Functional version (with minor deviations from expected behavior). * Refactoring. * All tests for NonUserCode work. * Fix line number after adding code above. * Stepper boundary with tests. * Save information about multiple decorators. * Fix error in merge. commit 5a523cf27a9b73e61adb1408f21b5e75a2246d9e Author: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Thu Jan 20 10:26:06 2022 +0100 [debugger][wasm] Added support for non user code attribute (#63876) * Hidden methods and step through methods behave the same way. * Perpared flow for setting JustMyCode in the future. * Tests for JustMyCode setting before debug launch. * Transformed into dynamic JustMyCode change flow. * JustMyCode disabled, first 3 cases solved. * Finished behavior for JMC disabled (with 1 difference). * JMC enabled: stepIn np bp + stepIn bp + resume bp. * Functional version (with minor deviations from expected behavior). * Refactoring. * All tests for NonUserCode work. * Fix line number after adding code above. * Fix error in merge. * Removing duplicated tests. commit 8f2c84f02b74dbbe6e1f02dc9be37cf3ee288d6e Author: Peter Sollich Date: Thu Jan 20 10:06:45 2022 +0100 Fix issues with verify_regions, clear_batch_mark_array_bits. (#63798) Details: - we cannot verify the tail of the region list from background GC, as it may be updated by threads allocating. - fix case in clear_batch_mark_array_bits where end is equal to the very end of a segment and we write into uncommitted memory in the mark_array. - bgc_clear_batch_mark_array_bits did some checks and then called clear_batch_mark_array_bits which repeated the exact same checks. Renamed clear_batch_mark_array_bits to bgc_batch_mark_array_bits and removed the old copy, removed the declaration for clear_batch_mark_array_bits. commit e4bfedd847990795eb28cda4008b5ff4c58fd561 Author: Jeremy Barton Date: Thu Jan 20 00:06:28 2022 -0800 Fix OpenSSL version check in GetAlpnSupport The previous check failed 3.0.0 because the Minor was 0 and Build was 0. It could probably be rewritten to be `>= new Version(1, 0, 2)`, but that'd require more thinking. commit 2cf6b0d07309a3c19938f4c886fe13e8d5cc28ee Author: Andrew Au Date: Wed Jan 19 20:57:41 2022 -0800 Fix gc_heap::remove_ro_segment (#63473) commit 65a5d0e8a3027f2b240d098f47327ba3e1f743b1 Author: Tlakaelel Axayakatl Ceja Date: Wed Jan 19 19:46:45 2022 -0800 Add ProcessLinkerXmlBase to NativeAOT (#63666) Add Xml Parsing linker files as a reference source to NativeAOT Rename NativeAOT ProcessLinkerXmlBase version to ProcessXmlBase (uses XmlReader) Add ProcessLinkerXmlBase from linker and fix it so it can be used in NativeAOT (uses XPath) commit f1c8b10ef824c5abf0c851f610ab0961ca31693f Author: Egor Chesakov Date: Wed Jan 19 19:43:26 2022 -0800 [Arm64] Keep unrolling InitBlock and CopyBlock up to 128 bytes (#63422) * Add INITBLK_LCL_UNROLL_LIMIT and CPBLK_LCL_UNROLL_LIMIT of 128 bytes in src/coreclr/jit/targetarm64.h * Keep unrolling InitBlock up to INITBLK_LCL_UNROLL_LIMIT bytes when dstAddr points to the stack in src/coreclr/jit/lowerarmarch.cpp * Keep unrolling CopyBlock up to CPBLK_LCL_UNROLL_LIMIT bytes when both srcAddr and dstAddr point to the stack in src/coreclr/jit/lowerarmarch.cpp commit a5158df084780e52005e4dcbd02ee091542e06d0 Author: Will Smith Date: Wed Jan 19 18:44:19 2022 -0800 'cmeq' and 'fcmeq' Vector64.Zero/Vector128.Zero ARM64 containment optimizations (#62933) * Initial work * Added a comma to display * Cleanup * Fixing build * More cleanup * Update comment * Update comment * Added CompareEqual Vector64/128 with Zero tests * Do not contain op1 for now * Wrong intrinsic id used * Removing generated tests * Removing generated tests * Added CompareEqual tests * Supporting containment for first operand * Fix test build * Passing correct register * Check IsVectorZero before not allocing a register * Update comment * Fixing test * Minor format change * Fixed formatting * Renamed test * Adding AdvSimd_Arm64 tests: * Adding support for rest of 'cmeq' and 'fcmeq' instructions * Removing github csproj * Minor test fix * Fixed tests * Fix print * Minor format change * Fixing test * Added some emitter tests * Feedback * Update emitarm64.cpp * Feedback commit 68a923a24edb47f1d0e3c38a69d4091a7587bfc4 Author: Andrew Au Date: Wed Jan 19 17:59:07 2022 -0800 Check if the child object is in the heap range before object_gennum (#63970) commit 752569f66bcde98fcc4dd1e651f9f1f138184c5c Author: Andrew Au Date: Wed Jan 19 17:58:39 2022 -0800 Check if the child object is in the heap range before get_region_plan_gen_num (#63828) commit 5cefc0f9e618e2d8b38d7de67bbd8a50adb9646f Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Thu Jan 20 04:23:50 2022 +0300 Fix invalid threading of nodes in rationalization (#64012) The code in question assumes that the ASG will be reversed and thus threads "simdTree" before "location" in the linear order. That dependency, while valid, because "gtSetEvalOrder" will always reverse ASGs with locals on the LHS, is unnecessary and incorrect from the IR validity point of view. Fix this by using "InsertAfter" instead of manual node threading. commit 93dc760481bdde2c463d725c2927b9da8787eb98 Author: Tomáš Rylek Date: Thu Jan 20 01:52:15 2022 +0100 Fix Crossgen2 bug #61104 and add regression test (#63956) The issue tracks the runtime regression failure where Crossgen2-compiled app is unable to locate a type with non-ASCII characters in its name. The failure was caused by the fact that Crossgen2 was incorrectly zero-extending the individual UTF8 characters when calculating the hash whereas runtime is sign-extending them. Thanks Tomas commit 94b699cc6f6b88c6de1d13152143d32285c59555 Author: Jeremy Koritzinsky Date: Wed Jan 19 16:46:00 2022 -0800 Update StructMarshalling design now that DisableRuntimeMarshallingAttribute is approved (#63765) Co-authored-by: Elinor Fung commit a618086f53fa755732697fba171a16e8bf67900a Author: Andy Ayers Date: Wed Jan 19 16:01:16 2022 -0800 JIT: fix up switch map for out-of-loop predecessor (#64014) If we have a loop where some of the non-loop predecessors are switchs, and we add pre-header to the loop, we need to update the switch map for those predecessors. Fixes #63982. commit 7f828a7e6b712bdeab02d75160249cd13c26a467 Author: Egor Bogatov Date: Thu Jan 20 02:08:10 2022 +0300 [arm64] JIT: Redundant zero/sign extensions after ldrX/ldrsX (#62630) commit ae1b755cd074745b0f09e826d3c7064b2a8f20dd Author: Dan Moseley Date: Wed Jan 19 16:07:53 2022 -0700 Retries for flaky WMI test (#64008) commit 54eec5d1f4d7ded21e33e65c63ada26afe80b208 Author: Elinor Fung Date: Wed Jan 19 14:23:48 2022 -0800 Make ILStubGenerated event log ModuleID corresponding to that on other events (#63974) commit 97fec41a752f067f4d6dde170073300e1184693b Author: Santiago Fernandez Madero Date: Wed Jan 19 14:18:21 2022 -0800 Add runtime-extra-platforms pipeline to have matching runtime PR and Rolling builds (#62564) * Add runtime-extended-platforms pipeline to have matching runtime PR and Rolling builds * Fix evaluate changed paths condition for the extra pipeline * PR Feedback and fix condition * Move MacCatalyst back to staging, disable tvOS tests * Disable browser wasm windows legs commit 826e03e4b984d3bb76b2ead5f6ebb847be9c616f Author: Jeremy Koritzinsky Date: Wed Jan 19 14:08:07 2022 -0800 Bump Explicit-layout value types with no fields to at minimum 1 byte size. (#63975) commit 6f8d8b20a0c78dcfc09ea7a43db48a9a4e055e13 Author: Ankit Jain Date: Wed Jan 19 16:41:04 2022 -0500 Disable hot reload tests for AOT configurations (#64006) commit 675c16711007536120fa2ef7b69224e44299d1e3 Author: Egor Chesakov Date: Wed Jan 19 12:59:49 2022 -0800 [Arm64] Don't use D-copies in CopyBlock (#63588) * Increase the maximum number of internal registers allowd per node in src/coreclr/jit/lsra.h * Based on discussion in https://github.com/dotnet/runtime/issues/63453 don't allocate a SIMD register pair if the JIT won't be able to use Q-copies in src/coreclr/jit/lsraarmarch.cpp * Update CodeGen to reflect that Q-copies should be used only when size >= 2 * FP_REGSIZE_BYTES and using of them makes the instruction sequence shorter in src/coreclr/jit/codegenarmarch.cpp * Update comment - we don't use D-copies after that change in src/coreclr/jit/codegenarmarch.cpp commit ac4c7fb9457a8b0972686b017d82367d7a9bf1ca Author: Pavel Savara Date: Wed Jan 19 20:59:01 2022 +0100 - mono_wasm_new_external_root for roots on stack (#63997) - temp_malloc helper via linear buffer in js - small refactorings Co-authored-by: Katelyn Gadd commit 65db54e2a92a2ef8ba8a75c70990e78f21818e18 Author: Egor Bogatov Date: Wed Jan 19 22:23:45 2022 +0300 Add IsKnownConstant jit helper and optimize 'str == ""' with str.StartsWith('c') (#63734) Co-authored-by: Miha Zupan Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> commit ded841a690e73c04ebdc86c681893bf9fd372751 Author: Egor Bogatov Date: Wed Jan 19 22:22:49 2022 +0300 Don't reuse registers in Debug mode (#63698) Co-authored-by: Bruce Forstall commit 67848f23d51562bd2e54f6490f5aad22f57baffe Author: Brennan Date: Wed Jan 19 11:01:24 2022 -0800 [RateLimiting] Dequeue items when queuing with NewestFirst (#63377) commit 12f434db114e629854e7d5eb966e07d24e243712 Author: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed Jan 19 20:42:27 2022 +0200 Fix for Werror=use-after-free in PAL (#63954) * Fix for Werror=use-after-free in PAL * Delete Local{Alloc,Free} * Delete LMEM_* macros * Delete PAL_dladdr commit bbbfba31b61a2299c434172f709716325c073ef8 Author: Stephen Toub Date: Wed Jan 19 12:27:25 2022 -0500 Use IndexOf in StringBuilder.Replace(char, char) (#63913) commit df049b9a23c5182bf7f26f224b69bf1f47f9dc2f Author: Dan Moseley Date: Wed Jan 19 09:26:30 2022 -0700 Disable 2 SMTP tests on checked runtime (#63947) commit 8604989022950ef38f94b9150043b31d81f061a5 Author: Maksym Koshovyi Date: Wed Jan 19 17:49:39 2022 +0200 [Group 5] Enable nullable annotations for `Microsoft.Extensions.Configuration.Json` (#63694) * Nullable enable commit a8c1408084714a7db13db7eb5cae10b209d9c096 Author: TobiasLaving <95348503+TobiasLaving@users.noreply.github.com> Date: Wed Jan 19 16:04:02 2022 +0100 Update runtime.json with manjaro information (#63338) Without specifying runtime on manjaro we cannot run the projects. FYI: Manjaro has a "ID_LIKE" param in os_release that has arch as input. Perhaps that would be another way forward. commit 31f20c54ad56946a506d705261a5445930b56d29 Author: Stephen Toub Date: Wed Jan 19 09:57:04 2022 -0500 Improve auto-atomicity for conditionals (#63299) - Allow for automatically making loops that end conditional branches be atomic - Allow for using a following expression conditional to make a prior loop atomic - Allow conditionals to influence the computed minimum length commit 8fe0467efd29d952fc2afbf302c1d8a1bb3b2fa5 Author: Maxim Lipnin Date: Wed Jan 19 16:55:40 2022 +0300 Take MacCatalyst into account in EnvironmentTests.WorkingSet_Valid test (#63995) Follow-up on https://github.com/dotnet/runtime/pull/63934 commit b042bc3043f3f7f475f5bd6e8f58df2952dd9250 Author: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed Jan 19 14:15:57 2022 +0100 Avoid allocating byte array when setting ALPN list on Linux (#63674) * Avoid allocating byte array when setting ALPN list * Code review feedback * Apply suggestions from code review Co-authored-by: Stephen Toub * Slice the stackalloc'd buffer to correct length Co-authored-by: Miha Zupan * Code review fixes Co-authored-by: Stephen Toub Co-authored-by: Miha Zupan commit 34794bc5f2bcdbaa9057bb07b8764e2bb6a411a2 Author: Krzysztof Wicher Date: Wed Jan 19 13:45:01 2022 +0100 Enable System.Text.Json tests on netfx (#63803) * Enable System.Text.Json tests on netfx * use NETFRAMEWORK define * disable another two test cases after rebase * disable last test case which repros only on CI for me * add p2p only on netfx commit e54df94bc9a5e1e064835be817d3e9ac773e1d9a Author: Eirik Tsarpalis Date: Wed Jan 19 11:59:34 2022 +0000 Replace "needs more info" label with "needs-author-action" (#63899) commit a5292a6b54ca743efe2e5b6776864efb7c7702a5 Author: Olivier Giniaux Date: Wed Jan 19 12:56:54 2022 +0100 Fix profiling objectsallocatedbyclass (#63814) * Add test for ObjectsAllocatedByClass profiler callbacks * Fix ObjectsAllocatedByClass profiler callbacks based on wrong flag * Fix wrong args in test log Co-authored-by: Olivier Giniaux commit 6e4dfbfe2db42c9c67f1094dd65ec683c44e3457 Author: Stephen Toub Date: Wed Jan 19 06:53:36 2022 -0500 Improve reductions for Regex empty / nothing nodes (#63695) commit 777c353c767c588824a489ad39238fef01c80f4e Author: Stephen Toub Date: Wed Jan 19 06:53:24 2022 -0500 Extend regex switch alternation optimization to IgnoreCase (#63756) IgnoreCase now results in producing sets (e.g. an 'a' becomes '[Aa]') but the source generator's optimization that produces a switch statements for alternations with non-overlapping branches doesn't yet understand such sets. This augments that logic to fix that. commit a25536f790258fe68240feff864713e8d20b418c Author: Stephen Toub Date: Wed Jan 19 06:52:15 2022 -0500 Improve auto-atomicity for Regex loops (#63986) - As part of recognizing loops that could be made atomic, we currently only look at the node guaranteed to come immediately after it, e.g. in a+b+c+, when analyzing a+ we only look at the b+. That's fine in many cases, but if our expression was instead e.g. a*b*c*, we couldn't make a* atomic because we wouldn't be guaranteed it'd be followed by a b, and we wouldn't look at the subsequent nodes to determine what else might follow. When that situation occurs, we can now walk the tree to find the next node, and repeatedly do so as much as is needed in order to find the next node, enabling us to make all of those loops atomic. - We currently perform the auto-atomicity reduction for single-char loops as part of reducing concatenations. But this means we're performing that transformation at a time when the tree isn't fully formed, which means we can't necessarily reach out of a concatenation to what comes after it and use that to influence the atomicity. It also means we might repeat the analysis unnecessarily multiple times, because it's done as part of parenting a node. We can instead do that optimization as part of the final optimization phase, after the tree is already created. - When we find a lazy loop at the end of an expression, we can treat it as atomic, which means we can lower its max bound to its min bound. - When we encounter a loop (lazy or greedy) at the end of an expression, if it has a max bound of 1 (i.e. it's optional), we can proceed to eliminate ending backtracking with its child regardless of whether the child could be made atomic with the start of the loop, since it won't ever repeat more than once. commit eeaee44e6fe4425db044967e025255e6a12c97a9 Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed Jan 19 11:20:02 2022 +0100 [main] Update dependencies from dotnet/runtime dotnet/arcade dotnet/xharness dotnet/icu dotnet/roslyn-analyzers dotnet/llvm-project (#63737) Co-authored-by: dotnet-maestro[bot] Co-authored-by: Alexander Köplinger commit 313baef638104ed64f93e077c84547421884c91b Author: Egor Bogatov Date: Wed Jan 19 13:16:28 2022 +0300 JIT: Fix repeatable failure for max CALLSITE_DEPTH (#63966) commit a354bb152f4e505d53034c3538f971ad4c2f18ac Author: Stephen Toub Date: Wed Jan 19 04:10:27 2022 -0500 Address follow-up feedback to CachedCompletedInt32Task (#63968) commit b68cf65634bb0d6a1a7e588568959cdc33a0322c Author: Adam Sitnik Date: Wed Jan 19 08:58:20 2022 +0100 Reading beyond EOF should return 0 for FILE_FLAG_NO_BUFFERING (#63625) * move Length to SafeFileHandle, so it's cached value can be reused in more places commit ea2a98163327022e6cefb6a424de4cb4e9618277 Author: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Wed Jan 19 08:55:35 2022 +0100 [wasm][debugger] Added support for StepThroughAttribute (#63679) * Hidden methods and step through methods behave the same way. * Perpared flow for setting JustMyCode in the future. * Tests for JustMyCode setting before debug launch. * Transformed into dynamic JustMyCode change flow. * JustMyCode disabled, first 3 cases solved. * Finished behavior for JMC disabled (with 1 difference). * JMC enabled: stepIn np bp + stepIn bp + resume bp. * Functional version (with minor deviations from expected behavior). * Refactoring. commit 00e13f5482ea1156e6b37ea5d242d7f27befb8d3 Author: Adam Sitnik Date: Wed Jan 19 08:42:07 2022 +0100 Add tests for creating memory mapped files from non-seekable files (#63927) commit c66e3c49b59e0894ed3e7c41b0e78dcda22528ae Author: Michal Strehovský Date: Wed Jan 19 15:01:43 2022 +0900 Add support for libraries testing with NativeAOT (#63781) This adds support for running libraries tests with NativeAOT. It reuses the single file xunit runner since we cannot `LoadFrom` the tests on NativeAOT. The strategy is the same as for single file testing: do a publish. To do the NativeAOT publish, we include the Microsoft.DotNet.ILCompiler.targets. commit 3104ed8a3579746eaadb6280acc4fae1ae0df6ed Author: Michal Strehovský Date: Wed Jan 19 15:00:52 2022 +0900 Fix up warnings from delegate thunks (#63980) If we hit a p/invoke with a `System.Delegate` in a delegate marshalling stub, blame the delegate type, not the compiler-generated method. Apparently we marshal System.Delegate in MsQuick interop. commit 0b307c95286a4f468fbb627a66515054ff18dc87 Author: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed Jan 19 07:25:12 2022 +0200 Add managed implementation of Math/MathF.Abs (#63881) * Add managed implementation of Math/MathF.Abs * Cleanup trailing whitespaces in changeset * Delete unused _copysignf macro commit fc3875f14f310cdce716df30a94feb43db79a28a Author: Jose Perez Rodriguez Date: Tue Jan 18 19:47:09 2022 -0800 Fix case where we incorrectly select a prefix as a FindFirstChar optimization when the pattern includdes an alternation that could lead to different prefixes. (#63976) commit 454ac0a6e7584e1c02677d459d20dae5df61fb47 Author: Stephen Toub Date: Tue Jan 18 22:15:32 2022 -0500 Revert "Improve auto-atomicity for Regex loops (#63518)" (#63984) This reverts commit 557901e779a009cf4a51327963727a4d1ded0094. commit da72791c37480532e647e8f69aff3f2b7eef6049 Author: Jan Kotas Date: Tue Jan 18 18:59:04 2022 -0800 Fix System.Reflection.Metadata version in ILVerification nuget package metadata (#63965) Fixes #63944 commit b7d8f5ecfa7bceb8069448951c7fabd65bcf26a0 Author: Tarek Mahmoud Sayed Date: Tue Jan 18 18:39:37 2022 -0800 Fix Failing Globalization Test on OSX (#63971) commit 546c23804538ee751e4bb419942bc0170c3e5e06 Author: Michal Strehovský Date: Wed Jan 19 10:58:17 2022 +0900 Improve ILLink.targets integration (#63914) Runtime side of https://github.com/dotnet/sdk/pull/23470 (depends on that getting merged). Skip touching the IL Linker semaphore that tricks the target into not running. commit 557901e779a009cf4a51327963727a4d1ded0094 Author: Stephen Toub Date: Tue Jan 18 20:40:35 2022 -0500 Improve auto-atomicity for Regex loops (#63518) * Improve auto-atomicity for Regex loops - As part of recognizing loops that could be made atomic, we currently only look at the node guaranteed to come immediately after it, e.g. in a+b+c+, when analyzing a+ we only look at the b+. That's fine in many cases, but if our expression was instead e.g. a*b*c*, we couldn't make a* atomic because we wouldn't be guaranteed it'd be followed by a b, and we wouldn't look at the subsequent nodes to determine what else might follow. When that situation occurs, we can now walk the tree to find the next node, and repeatedly do so as much as is needed in order to find the next node, enabling us to make all of those loops atomic. - We currently perform the auto-atomicity reduction for single-char loops as part of reducing concatenations. But this means we're performing that transformation at a time when the tree isn't fully formed, which means we can't necessarily reach out of a concatenation to what comes after it and use that to influence the atomicity. It also means we might repeat the analysis unnecessarily multiple times, because it's done as part of parenting a node. We can instead do that optimization as part of the final optimization phase, after the tree is already created. - When we find a lazy loop at the end of an expression, we can treat it as atomic, which means we can lower its max bound to its min bound. - When we encounter a loop (lazy or greedy) at the end of an expression, if it has a max bound of 1 (i.e. it's optional), we can proceed to eliminate ending backtracking with its child regardless of whether the child could be made atomic with the start of the loop, since it won't ever repeat more than once. * Extend auto-atomicity to lazy loops commit 14ebc594b2757e29e1f73742ce37d68f855c0a3c Author: Jan Kotas Date: Tue Jan 18 17:36:09 2022 -0800 Do not register ACTIVATION_SIGNAL for secondary PAL copies (#63961) Related to #63959 commit cde93b69b6b099627d3615ec7f54cfb28b25bcde Author: Andy Ayers Date: Tue Jan 18 16:57:51 2022 -0800 JIT: yet another OSR stress mode (#62980) Existing OSR stress use existing patchpoint placement logic and alter the policy settings so that OSR methods are created more eagerly. This new version of OSR stress alters the patchpoint placement logic, to add patchpoints to more places. In conjunction with the eager policy stress above this leads to creation and execution of large numbers of OSR methods. Any IL offset in the method with an empty stack (and not in a handler) is fair game for a patchpoint, so this new method randomly adds patchpoints to the starts of blocks when stack empty (future work may extend this to mid-block stack empty points). The new mode is enabled by setting `COMPlus_JitRandomOnStackReplacement` to a non-zero value; this value represents the likelihood of adding a patchpoint at a stack-empty block start, and also factors into the random seed. (Recall this is parsed in hex, so 0x64 == 100 or larger will put a patchpoint at the start of every stack empty block). Various values are interesting because once a method reaches a patchpoint and triggers OSR, the remainder of that method's execution is in the OSR method, so later patchpoints in the original method may never be reached. So some sort of random/selective patchpoint approach (in conjunction with varying policy settings) is needed to ensure that we create an execute as many different OSR variants as possible. This PR also includes a couple of fixes exposed by local testing of this new stress mode: * The OSR prolog may end up empty, which gcencoder doesn't like. Detect this and add a `nop` for the prolog. * If we're importing the `fgEntryBB` during OSR, we don't need to schedule it for re-importation. This happens if we put a patchpoint at IL offset zero. * Update the selective dumping policy `COMPlus_JitDumpAtOSROoffset` to only dump OSR method compilations. A new test leg is added to `jit-experimental` to run with this mode enabled with a probability of 21% (0x15) and quick OSR triggers. Also included: * fix probability calc * remove obsolete assert * osr exposed does not apply to simd * only pad zero-sized OSR prolog if we're reporting generic context * Add ability to have patchpoint at specified offset. * Fix interaction of stress patchpoints and profile instrumentation. We need to force block-based instrumentation if we might have stress patchpoints. commit 93cb3559a17aca424e3ce1206a71496da2c34b69 Author: Honza Rameš Date: Wed Jan 19 01:12:18 2022 +0100 Reduce allocations in code generated by Logging generators (#61162) (#62011) commit c50185bb24ace683f2ce6c5e4351ce2104bd1349 Author: Aleksey Kliger (λgeek) Date: Tue Jan 18 18:40:42 2022 -0500 [mono] Hot Reload: initial push to support adding lambdas (#63513) Adds support for: * Adding static lambdas to existing methods, whether or not they had lambdas before. * Adding lambdas that capture `this` to existing methods that already captured `this` before * Adding new static or instance methods to existing types * Adding static fields to existing types * Adding new types (note that adding instance fields currently will fail. It'll go in in a future PR that will address https://github.com/dotnet/runtime/issues/63643). Note that reflection on newly added members isn't tested yet and likely doesn't work. Fixes https://github.com/dotnet/runtime/issues/50249 Contributes to https://github.com/dotnet/runtime/issues/57365 * Add AddStaticField test; cleanup AddLambdaCapturingThis * Add AddNestedClass testcase * hot_reload: add a comment about remaining work * move per-class metadata update info to MonoClassMetadataUpdateInfo Use a property on the class instead of a hash table in the baseline image to keep track of added fields and methods * Cleanup pass1 to check add/update against prior gen Instead of the baseline image * adding a class Working on making mono_metadata_nested_in_typedef do the right thing for nested classes Contributes to making mono_class_create_from_typedef do the right thing for nested classes. * fix: correct mutant table population when the baseline table is empty In that case the table row_size and size_bitmap of the baseline are both 0, so offset calculations don't work. In that case when we know we need to add rows to the mutant table, use the uncompressed layout (32-bit columns, always) same as the EnC delta. * Calling new methods on a nested class works * adding fields Doesn't work yet. Dies in mono_class_get_field, called from mono_field_from_token_checked. The problem we're going to have to deal with is that unlike MonoMethod which is allocated upon lookup, the MonoClassFields of a class are allocated contiguously in class initialization. And there are not really enough fields in MonoClassField to indicate "this is not an ordinary field, don't do pointer arithmetic with it". One idea is to steal a bit from MonoClassField:parent and always check it as a trigger to go on a slower path. * adding static fields Rework the delta info to store info about "members" (rather than methods and fields separately). Add a MonoClassMetadataUpdateField subclass of MonoClassField that has extra info. Add new component methods to go from a MonoClassField to an index, and from a field token to a MonoClassField. Set MonoClassField:offset to -1 to generally go down the "special static field" codepath since we will need to do some one-off work to make a storage area for added static fields. Instance fields are not supported yet and error out during the update pass for now. * fix custom attribute lookups on new classes/methods/fields * Add a sketch of HotReloadInstanceFieldTable This is a class that manages the lifetime for added instance fields for reference types that had new fields added to them by EnC It's basically ConditionalWeakTable> where the outer key is the object instance, the inner key is the fielddef token, and the value is a Store. The store has a single object? field which the location where the field's value will go. For reference types this is the reference directly, and for valuetypes and primitives, this is the boxed object (so to get the actual storage address you need to add sizeof(MonoObject)). * mono_metadata_update_get_static_field_addr two reminders: 1. The static field area needs to be GC-visible 2. We should really handle added fields on un-inited classes by allocating the instances in the normal way - in the layout algorithm. * Free MonoClassMetadataUpdateInfo when BaselineInfo is destroyed * placeholder struct for runtime class data; instance offset placeholder * static field storage Need to store the fields in a GC root, and in pinned allocations. * Implement hot_reload_get_static_field_addr() * Add mono_metadata_update_find_method_by_name Now we can find .cctor This is enough that a basic sample with an added static lambda works * Fix infinite loop * fix build * fix dynamic components builds * fix windows build * Fix inadvertent fallthru in previous fix * Report new capabilities NewTypeDefinition is not completely functional because adding instance fields is not supported yet. But adding classes with only static methods works. * tests: describe what existing tests do, add placeholder static lambda test * tests: Add AddStaticLambda test case Adding a brand new static lambda to an existing method body is supported * Destroy the runtime part of MonoClassMetadataUpdateInfo, too * rename Mono.HotReload file it has more classes than just the instance table * tests: add ActiveIssue for supporting adding instance fields * ifdef out Mono.HotReload.InstanceFieldTable it's not ready yet * Remove get_added_members from hot reload component interface Doesn't seem necessary to expose this yet. It's only used in hot_reload.c right now * Change the AddStaticLambda sample to use Func To check that lambdas with parameters work * Use a mempool allocated GSlist for the added members This avoids invalidating iterators in case we add members on one thread while another thread is iterating. If it turns out we need random access, we can switch to a GArray with locking. But so far we only ever iterate. * Use mono_get_corlib instead of passing MonoDefaults to hot_reload * use normal GENERATE_TRY_GET_CLASS_WITH_CACHE * [metadata] make m_field_set_parent and m_field_set_meta_flags inline m_ prefix functions are supposed to be inline commit d2844ebf57568de4926517c521a94a721d9c26a8 Author: Bradley Grainger Date: Tue Jan 18 15:32:16 2022 -0800 Add `UnicodeRange.ArabicExtendedB` (#63901) commit 8d5f5267d33f7703c014cc89670f1f7aa47544f9 Author: Andrii Kurdiumov Date: Wed Jan 19 05:23:32 2022 +0600 Update links to the project for DllImportGenerator (#63940) As coincidence, I think `RestoreAdditionalProjectSources` not needed anymore. commit 83b52cdc310ebd77cddff7efd772a0800a403f47 Author: Alexander Köplinger Date: Tue Jan 18 23:13:58 2022 +0100 [iOS/tvOS] Remove P/Invokes to libproc from System.Private.CoreLib (#63934) They aren't allowed by Apple when submitting to the App Store. Finishes https://github.com/dotnet/runtime/issues/61265 commit b0de23b1677fbaf4fbcde814ec0bad6f60094920 Author: Andy Gocke Date: Tue Jan 18 13:37:41 2022 -0800 Revert "Enable GC Regions by default (#59283)" (#63935) This reverts commit cf91716. This looks to be creating a lot of crashes in a lot of different unit tests on Mac. Reverting seems to halt the Mac failures (see https://dev.azure.com/dnceng/public/_build/results?buildId=1557880) Fixes #63439 commit 0266f034221188bc7d0156ba76a571c71885c68f Author: Kunal Pathak Date: Tue Jan 18 11:04:48 2022 -0800 Fix decoding errors (#63929) commit 078da6c37e2ab602fe37ab699051ef71161ce2cc Author: Bruce Forstall Date: Tue Jan 18 11:04:22 2022 -0800 Introduce `BasicBlock::KindIs()` for checking bbJumpKind (#63203) * Introduce `BasicBlock::KindIs()` for checking bbJumpKind This can simplify code that is checking for multiple `bbJumpKind` kinds with an `if` statement, where a `switch` is not warranted. It's the same usage model as `GenTree::OperIs()`. e.g., ``` if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN)) ``` * Fix argument name commit 82b8d79b6f858f0d44791e3eab36735b7093d935 Author: Shane Krueger Date: Tue Jan 18 13:56:09 2022 -0500 Fix NullabilityInfoContext.Create to properly analyze types with nested generic types (#63556) commit f04a24249835096eea1a1a66e4af03cfec5ed32b Author: Artem Kliatchkine Date: Tue Jan 18 18:18:45 2022 +0100 Set zero (infinite) options timeout in case of Timeout.InfiniteTimeSpan (#55984) (#63733) Co-authored-by: Artem Kliatchkine commit 2eb2e883dc807897fe07dd6559462e37e8613693 Author: Tomas Weinfurt Date: Tue Jan 18 09:18:29 2022 -0800 improve protocol detection in jail (#63565) * improve protocol detection in jail * add comment commit d18d6c703295555d466fb159f8dec64857f68ed9 Author: Kevin Jones Date: Tue Jan 18 12:15:11 2022 -0500 Update SAN test to account for OpenSSL 3 changes commit 64896116e66377aa8e951abb9e9505aff8a25f89 Author: Kevin Jones Date: Tue Jan 18 11:36:15 2022 -0500 Fix OpenSSL 3 reporting an OutOfMemoryException for missing private key commit 5a12420546d7f0d963bcccf082400c1b057e38ef Author: Maxim Lipnin Date: Tue Jan 18 18:21:33 2022 +0300 Remove individual exclusions for DllImportGenerator.Unit.Tests in favor of the general one for the entire set of mobile targets (#63924) commit 39ef452edcf90bae76a1e4c8c1c24209e17ac5f2 Author: Maxim Lipnin Date: Tue Jan 18 18:20:15 2022 +0300 Disable DllImportGenerator.Unit.Tests test suite on macOS+arm64+CoreCLR (#63887) commit 856e8c3510cb0aaaa3b1a1679552c03ae5308b9e Author: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue Jan 18 17:16:10 2022 +0200 Fix compilation with older gcc (#63721) commit 2f366a85444570429f8739b13bde18226a10bc86 Author: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue Jan 18 17:12:47 2022 +0200 Delete a few unused PAL APIs (#63916) * Delete _fullpath PAL API * Delete PAL_wcscspn * Delete PAL_wcstok commit 207590a7b82afa086e889f3fc695b104713f7c8e Author: Michal Strehovský Date: Wed Jan 19 00:10:36 2022 +0900 Fold coreclr/ToolBox into coreclr/tools (#63917) This separation only existed because of Razzle build sequencing of desktop CLR. It doesn't make sense for CoreCLR. The only thing the extra directory is doing now is that it breaks tab completion when navigating the CoreCLR source tree because ToolBox comes before tools alphabetically and most things live in tools. commit e30fe9b4d3afabc4acdfcaa539ecf213c16aea1a Author: Theodore Tsirpanis Date: Tue Jan 18 16:58:11 2022 +0200 Encapsulate the logic of caching the last synchronously completed task. (#61781) * Encapsulate the logic of caching the last synchronously completed task. * Apply suggestions from code review Co-authored-by: Adam Sitnik commit e6ad043996419f04b1c0ae9fea113318f61e234f Author: Michal Strehovský Date: Tue Jan 18 23:32:28 2022 +0900 Split CheckNotDisposed to allow inlining (#63863) * Split CheckNotDisposed to allow inlining `CheckNotDisposed` is not getting inlined because RyuJIT thinks it's not profitable (ldstr/newobj/throw is expensive). If we extract the rare path into a separate method, it changes the profitability math and allows inlining to happen. * Review feedback commit dfb36ae68d9a099c9b90317c97bdf485bab4121e Author: Stephen Toub Date: Tue Jan 18 09:31:12 2022 -0500 Fix a few IndexOf{Any} uses (#63852) commit 7a0388a9f1a11b723aa09aeae3436a078b32bb43 Author: Eirik Tsarpalis Date: Tue Jan 18 13:33:57 2022 +0000 Extend triage board automation to more pods (#63897) commit 8d8ef6dac58acf2ab944289c69dd46ee9e12d717 Author: Tom Deseyn Date: Tue Jan 18 11:00:35 2022 +0100 FileSystemEntry.Unix: don't make a syscall to check hidden on Linux. (#63878) commit 24bdc3844c3de6d6a3c47534411c8322ae1a7bc6 Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue Jan 18 10:41:02 2022 +0100 [main] Update dependencies from dotnet/linker (#63445) Co-authored-by: dotnet-maestro[bot] commit 126db6dd10fcf618a9ab17ed93347044cc5a3a24 Author: Michal Strehovský Date: Tue Jan 18 14:19:20 2022 +0900 Disable warnings as errors in the repro project (#63910) commit d0e2dac3a828b6afda5cff812b7b09b9dba213b7 Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Tue Jan 18 01:23:41 2022 +0300 Actually properly type primary selectors (#63752) * Use only one [out] parameter in IsFieldAddr Since only one is needed. * Actually properly type primary selectors commit d48a44f2ee2f6b4b039ca10cfd5dc01c331669f5 Author: Michal Strehovský Date: Tue Jan 18 02:11:44 2022 +0900 Separate variance information in mangled names (#63866) Fixes https://github.com/dotnet/runtimelab/issues/1821. Eventually we'll need to have a holistic look at how we mangle things. commit 6dcb03913c7d55dca824abcd21617212bef62553 Author: Jan Kotas Date: Mon Jan 17 07:46:40 2022 -0800 Delete UMThkCallFrame (#63826) * Delete UMThkCallFrame * Place UnmanagedToManagedFrame under FEATURE_COMINTEROP commit 4fac9549fea1ccbf296aeaa0861478825d70c5c3 Author: Mandar Sahasrabuddhe Date: Mon Jan 17 16:05:28 2022 +0530 Fix escaped strings for TryGetDateTime(Offset) (#63534) * Fix escaped strings for TryGetDateTime(Offset) Fix the exception thrown when the escaped DateTime(Offset) property value is unescaped and it becomes shorter than the minimum expected length. In such case the Try* method should fail and returns false. Fixes #62720 * Fix escaped strings for TryGetDateTime(Offset) Fix the exception thrown when the escaped DateTime(Offset) property value is unescaped and it becomes shorter than the minimum expected length. In such a case, the Try* method should fail and return false. Fixes #62720 * Fix escaped strings for TryGetDateTime(Offset) Fix the exception thrown when the escaped DateTime(Offset) property value is unescaped and it becomes shorter than the minimum expected length. In such a case, the Try* method should fail and return false. Fixes #62720 * Fix escaped strings for TryGetDateTime(Offset) Fix the exception thrown when the escaped DateTime(Offset) property value is unescaped and it becomes shorter than the minimum expected length. In such a case, the Try* method should fail and return false. Fixes #62720 * Fix escaped strings for TryGetDateTime(Offset) Fix the exception thrown when the escaped DateTime(Offset) property value is unescaped and it becomes shorter than the minimum expected length. In such a case, the Try* method should fail and return false. Fixes #62720 commit d72ed27cfe8656807ece255b275ca9d617af073b Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Mon Jan 17 13:11:43 2022 +0300 Treat CLS_VAR_ADDR as never null (#63844) Allows the LIR DCE to remove some indirections that were previously incorrectly thought to be throwing. Contributes to CLS_VAR deletion (by minimizing the diffs). commit bf1d4a10b998a80b92728f80aa5ebbcd5138347a Author: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Mon Jan 17 11:11:10 2022 +0100 Fix generating RunTests.sh and RunTests.cmd scripts (#63875) This fixes issue where generated RunTests.sh in the "To repro directly: " section contained unevaluated variables like RUNTIME_PATH, which prevented simple copy-pasting the code into the terminal commit ae2f60c950cc021921fce83c796cbcb5ff96c658 Author: Andrii Kurdiumov Date: Mon Jan 17 09:57:15 2022 +0600 NativeAOT: Allow Delegate and MulticastDelegate marshalling (#63219) - Closes https://github.com/dotnet/runtimelab/issues/1107 - Progress towards https://github.com/GtkSharp/GtkSharp/issues/300 commit 84926be4243143b7830e78cb7727057ed711a3cc Author: Andrii Kurdiumov Date: Mon Jan 17 07:42:08 2022 +0600 Prevent assert if stack trace has function pointer (#63787) commit 217b288cfabd2368082343c7e36e7ac0a8f96db9 Author: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Mon Jan 17 03:10:54 2022 +0200 Convert h2inc to a cmake function (#63841) * Convert h2inc to a cmake function * Reuse preprocess_file commit ec349cd8e9960ec44bf528eef52c56a87e601207 Author: Tomáš Rylek Date: Sun Jan 16 20:50:01 2022 +0100 Fix a few IL tests using the namespace syntax without an actual namespace (#63772) commit 4f34cedc8eefb2a396646a67869e784f06d7def8 Author: Tomáš Rylek Date: Sun Jan 16 20:45:15 2022 +0100 Disable the Runtime_34587 regression test with GH issue #63818 (#63819) commit bf65675a8181d5448134788a148f844d35c4f091 Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Sun Jan 16 20:21:52 2022 +0300 Compress operand kinds array and optimize `OperIsLocal` (#63253) * Delete GTK_CONST * Delete OperIsRelop * Delete GTK_RELOP * Delete GTK_LOGOP * Delete GTK_LOCAL * Compress oper kinds They now fit into 8 bits. commit 23de81782ca9cd24f024bd598563d363df29660c Author: Zoltan Varga Date: Sat Jan 15 22:05:07 2022 -0500 [mono] Disable partial generic sharing for gparams with non-enum constraints for method gparams too. (#63813) This is an optimization, but it also avoids hitting some gsharing limitations wrt calling abstract static methods from gshared code. Fixes https://github.com/dotnet/runtime/issues/60447. commit c5c7967ddccc46c84c98c0e8c7e00c3009c65894 Author: Stephen Toub Date: Sat Jan 15 20:35:25 2022 -0500 Unify string.{Last}IndexOfAny and span.{Last}IndexOfAny (#63817) * Unify string.{Last}IndexOfAny and span.{Last}IndexOfAny Currently, string.IndexOfAny delegates to span.IndexOfAny (MemoryExtensions) for 1 through 5 values, and for more than it, it falls back to its own "probabilistic map"-based implementation, which tries to avoid looping through each value character for each character in the input. span.IndexOfAny doesn't do that, instead always looping through every char for every input char. This PR moves the logic from string into MemoryExtensions and then has string unconditionally delegate to span. string.LastIndexOfAny in contrast would only delegate to span's implementation if the values list actually only had a single character in it; otherwise, it would again fall back to its own "probabilistic map"-based implementation. This PR again moves that fallback into MemoryExtensions, with string unconditionally delegating to it. MemoryExtensions also has LastIndexOf overloads for 2 and 3 items, so rather than using the probabilistic path for those, it delegates to the existing overloads. * Address PR feedback commit 1e22b3f00501e8263af571ad74cb043fb3407b70 Author: Jeremy Koritzinsky Date: Sat Jan 15 12:59:33 2022 -0800 Refactor the "produce an RSP file" step into a separate step from the "run ILC" step to make it easier to generate the RSP file on the fly (#63820) commit fd2883f7bb60e75df6edcec58ac7bc79ecd10196 Author: Jan Kotas Date: Sat Jan 15 12:21:07 2022 -0800 Delete notifyexternals.* (#63835) Leftovers from loader lock MDA commit 78dea7ff6599dd851210df6db330ee3b58f5294c Author: Stephen Toub Date: Sat Jan 15 10:28:53 2022 -0500 Add Regex FindFirstChar optimization for a literal after an atomic loop (#63477) * Add Regex FindFirstChar optimization for a literal after an atomic loop If after all of our analysis we can't find anything to IndexOf{Any} as part of finding the next match location, we'll also look for a literal (a single char, a string of chars, or a set of a small number of chars) following an unbounded atomic set loop that starts the pattern. In that case, we can IndexOf for the literal, and then walk backwards through the characters prior to it looking for the beginning of the match. * Extend optimization to Setloop/lazy in addition to Setloopatomic commit c30d55ec5b584e26186a85adedf313c81a64269c Author: Tanner Gooding Date: Sat Jan 15 05:00:18 2022 -0800 Perform some minor code cleanup of the System.Numerics and System.Runtime.Intrinsics namespaces (#63753) * Ensure the System.Numerics and System.Runtime.Intrinsics namespaces are using explicit type when "not apparent" to match repo conventions * Ensure the System.Runtime.Intrinsics types are using TARGET_64BIT to match project convention * Improving some docs and simplifying names where possible commit a2e017dc876729678d7874706086bd444f010bcf Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Sat Jan 15 15:42:31 2022 +0300 Fix MOffset size estimate (#63766) commit 9db60963097adac1c25a5117d3918de17e1b5fb1 Author: Egor Bogatov Date: Sat Jan 15 15:20:36 2022 +0300 JIT: Mark constant arguments of HWINTRINSIC nodes as DONT_CSE (#63442) commit 20e6ec1a43cab03cd2d48f9fad32d56e83787ea0 Author: Geoff Kizer Date: Sat Jan 15 04:03:03 2022 -0800 Avoid unnecessary string allocation in HttpRuleParser.GetHostLength (#63641) * avoid unnecessary string allocation in HttpRuleParser.GetHostLength Co-authored-by: Geoffrey Kizer commit 25d999b5a6711fc6d2ffc42fa38a58ec865a7232 Author: Stephen Toub Date: Sat Jan 15 06:50:49 2022 -0500 Improve use of {Last}IndexOf{Any} in Regex loops (#63428) * Improve .*string to LastIndexOf "string" rather than just 's' * Enable .*string LastIndexOf optimization in the face of an UpdateBumpalong If the loop starts the expression, we will have inserted an UpdateBumpalong node, but that was then interfering with detecting a subsequent character/string. * Use IndexOf{Any} in lazy loop backtracking * Improve how sets are described in comments * Change RealWorld tests to be invoked once per engine To help with debugging * Address PR feedback commit 386f87139c7fe48f6b733e3cae6d09128c827192 Author: Aleksey Kliger (λgeek) Date: Sat Jan 15 04:05:03 2022 -0500 [metadata] Use MonoDefaults from components without hacks (#63822) commit 692052e016407e6eb11feeaee5269625c3ee741a Author: Ankit Jain Date: Fri Jan 14 23:52:13 2022 -0500 Split `sendtohelixhelp.proj` to extract wasm, and mobile bits to separate files. (#63373) Extract wasm, and mobile specific bits from sendtohelixhelp.proj into … .. separate files, so they can be easier to manage. - the platform specific properties are set in their respective files (for eg `sendtohelixhelp-wasm.proj`) - a new target `BuildHelixCommand` is extracted from `BuildHelixWorkItems`, which runs first - and essentially builds `@(HelixCommand)` - Platform specific targets can run via `$(BuildHelixWorkItemsDependsOn)` - which then add any "special" helix work items - `BuildHelixWorkItems` in the main file supports adding for the regular case, which is controlled by `$(EnableDefaultBuildHelixWorkItems)`. Also, fixes https://github.com/dotnet/runtime/issues/52137 commit 9daaab152ff1c0794ee21645bf57acf444f900ff Author: Anton Firszov Date: Sat Jan 15 03:15:26 2022 +0100 serialize SendPacketsAsync tests (#63702) commit 40047f2a82595546eadbabf9e438f7592eb1f002 Author: Stephen Toub Date: Fri Jan 14 20:48:36 2022 -0500 Improve Regex UpdateBumpalong optimization for non-atomic and lazy loops (#63398) * Improve handling of UpdateBumpalong for non-atomic loops For atomic greedy loops, UpdateBumpalong is serving its purpose: upon consuming as much as possible for the loop, base.runtextpos is set to that position so that the next time FindFirstChar runs, it'll start from at least that location. However, for non-atomic greedy loops, with base.runtextpos being set to the ending position after each backtracking, we end up inadvertently voiding any benefits of the UpdateBumpalong, as we end up overwriting the further position with the shorter position. A simple tweak to that, only setting the position if it's greater, yields significant benefits, in particular when there's no match. * Add more tests for lazy loops These just duplicate the greedy loop tests and tweak them for lazy. * Insert UpdateBumpalong for lazy loops as well * Address PR feedback commit 513fe2863ad5ec6dc453d223d4b60f787a0ffa78 Author: Tomáš Rylek Date: Sat Jan 15 00:36:58 2022 +0100 More duplicate projects under JIT/Methodical/NaN to delete (#63771) commit 2692407f03ce8b648c54daa4d3a3eb534132edc9 Author: Santiago Fernandez Madero Date: Fri Jan 14 13:36:50 2022 -0800 Build all packages on source-build even when in servicing (#63755) commit e1c69cc75a4c51ea3e3011a084f74b486b2dbc88 Author: Tomáš Rylek Date: Fri Jan 14 21:47:44 2022 +0100 Move localloc/common library under JIT folder (#63510) In today source tree we have five different libraries named 'common'. This change is a first step in deduplicating their names; I have also moved the library under the JIT/ folder as it's used not only by JIT/jit64 tests but also by Methodical and Regression tests. Thanks Tomas commit 3a83c5ca772a1a74e1707474c1d05c283f264a2f Author: Jan Kotas Date: Fri Jan 14 12:47:18 2022 -0800 Delete unused method (#63797) commit 02e22b02975d50944220e6e9a494af491487c6a9 Author: Tomáš Rylek Date: Fri Jan 14 21:00:01 2022 +0100 Remove string[] args from Main methods under JIT/Methodical (#63770) In most cases the arguments were formal and not really used so I just fixed the Main method signature. In a bunch of cases the command-line arguments supported variant functionality of the test case but I haven't found any test projects that would be exercising this functionality. I don't think it makes sense to keep untested code paths so I deleted the logic pertaining to non-empty command-line arguments. In the particular case of stringintern tests, each test apparently had a TestSameObjRef and TestDiffObjRef variant, triggered by command-line arguments. I tried to run TestDiffObjRef but it ended up failing left and right - not suprising for untested code logic - so I also deleted the TestDiffObjRef variants as I suppose the invariants previously tested there no longer hold. Thanks Tomas commit 562606671166edb60234c5062f69b35f6b2ac5c9 Author: Egor Chesakov Date: Fri Jan 14 10:44:07 2022 -0800 Enable superpmi-collect pipeline on macOS arm64 (#63691) * Enable superpmi-collect on macOS Arm64 in eng/pipelines/coreclr/superpmi-collect.yml * Add -platform argument and use the value for determining what Helix queue to use in src/coreclr/scripts/superpmi_collect_setup.py * Pass platform to superpmi_collect_setup.py in eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml * Copy *.dylib on macOS and *.so on Linux in src/coreclr/scripts/superpmi_collect_setup.py * Install azure-storage-blob in eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml * Remove macOS/x64 from platforms list in eng/pipelines/coreclr/superpmi-collect.yml * Add "CoreCLR Product Build OSX x64 checked" that produces required artifacts that consumed by macOS/arm64 superpmi-collect-job * Fix typo in libraries_test_assets should correspond to target arch in eng/pipelines/coreclr/templates/superpmi-collect-job.yml * Update a comment indicating what Helix queues are used for macOS in src/coreclr/scripts/superpmi_collect_setup.py * Workaround https://github.com/dotnet/sdk/issues/23430 in src/coreclr/scripts/superpmi_benchmarks.py * Enable macOS/arm64 benchmarks collection in eng/pipelines/coreclr/superpmi-collect.yml commit a991e1349e4325770d8e2ddf085184a68cd2555b Author: Elinor Fung Date: Fri Jan 14 10:49:26 2022 -0500 Make ObjectiveC tests in System.Runtime.InteropServices.Tests check exit code for remote execution (#63769) commit 33179fa0ac1ab75bb09e5cc7ed63aa6629c51411 Author: Maksym Koshovyi Date: Fri Jan 14 17:49:06 2022 +0200 [Group 5] Enable nullable annotations for `Microsoft.Extensions.Configuration.Ini` (#60368) * Add annotations * Use pattern matching * NetCoreAppMinimum * ReadLine won't return null * Update src/libraries/Microsoft.Extensions.Configuration.Ini/ref/Microsoft.Extensions.Configuration.Ini.csproj Co-authored-by: Eric Erhardt * Add comment * Revert non-nullable change Co-authored-by: Eric Erhardt commit 3956126d55e32203a8926a54a8ee3090b3e69749 Author: MSDN.WhiteKnight <35516665+MSDN-WhiteKnight@users.noreply.github.com> Date: Fri Jan 14 20:33:03 2022 +0500 Fix typo in SRM package description (#63782) commit d568a3fec2c9a2e7341466a28f88f52558fddf6c Author: Tarek Mahmoud Sayed Date: Fri Jan 14 07:27:32 2022 -0800 Introduce Activity.IsStopped Property (#63713) Co-authored-by: Dan Moseley commit 0b527a201f4c286f13ef8b829bbd1651bdad7a52 Author: Zoltan Varga Date: Fri Jan 14 08:07:47 2022 -0500 Fix a style issue. (#63776) commit b184ee0393aaf0395a69e70590d5c529e8c93ccf Author: Adam Sitnik Date: Fri Jan 14 10:04:11 2022 +0100 MemoryMappedFile: don't check for file existence if there is no need (#63754) Co-authored-by: Stephen Toub commit c96869a6d10a235b5a26c9e15d685fabc7f87cb0 Author: Michal Strehovský Date: Fri Jan 14 17:03:22 2022 +0900 Disable annoying warnings in the repro project (#63777) We have repo-wide WarnAsError that makes this super annoying in a repro project. commit b7e0a85ab6111b77ad19a1c2db0dedcedded4940 Author: Qiao <35673267+shushanhf@users.noreply.github.com> Date: Fri Jan 14 14:33:20 2022 +0800 [LoongArch64] add all the coreclr-build-config files (#62889) commit 1ba80f698c85b525545f1a13c02eb405588b0461 Author: Andrii Kurdiumov Date: Fri Jan 14 12:20:45 2022 +0600 Remove errors during first run of runpaltests.h (#62642) * Remove errors during first run of runpaltests.h If you run `runpaltests.h` for first time, you will see 2 errors about file or folder not found. First error comes from using `RELATIVE_PATH_TO_PAL_TESTS` which does not used anywhere, except maybe some platform where you can `cd` to non-existing folder. In that case 3rd parameter to script would be interpreted incorrectly. I doubt that, but who know what's somewhere deep in infra. Second error is entirely preventable, since `cd $PAL_TEST_OUTPUT_DIR` does not affect anything until subsequent `cd $PAL_TEST_OUTPUT_DIR` on line 118. Discovered here https://github.com/dotnet/runtime/pull/62625#issuecomment-991172978 * Remove not nescessary cd * Fix * oopsie commit 27fdc2d22f8717c7b0ba254ae9ef2900d00f5e7a Author: Stephen Halter Date: Thu Jan 13 17:20:28 2022 -0800 Avoid deadlock with ConfigurationManager (#62209) Co-authored-by: Eric Erhardt commit 2c28e63f9360280011a3b03c1ca6dc0edce1fae4 Author: Alexander Köplinger Date: Thu Jan 13 22:17:54 2022 +0100 Temporarily disable coredumps during library testing on macOS (#63742) System.Runtime.InteropServices.Tests seems to produce >10GB of coredumps which overwhelms CI. commit 79e40e35ce3e218ad2d81259572e462b56bfd807 Author: Kevin Jones Date: Thu Jan 13 15:04:36 2022 -0500 Add public constants for HMAC and hash sizes commit c912a1532a1bb653a21a3749aaad7c5fb556ae01 Author: Kevin Jones Date: Thu Jan 13 14:07:55 2022 -0500 Change non-breaking spaces (U00A0) to a plain space in code files (#63688) commit ec0c7f3a91b9fc47f7a867f0b997ba34560302e7 Author: Aaron Robinson Date: Thu Jan 13 12:20:43 2022 -0500 Add negative tests for by-ref in UnmanagedCallersOnly scenarios. (#63711) commit c78d9fa3edb2ae8e14f0529566c20d33a2512cab Author: Maxim Lipnin Date: Thu Jan 13 19:08:27 2022 +0300 Disable System.Drawing.Common.Tests test suite on Windows+Mono (#63726) commit 048e1a395523f1855c054d01a3f1f4c55d873ea4 Author: Simon Rozsival Date: Thu Jan 13 16:57:12 2022 +0100 [Android] Throw PNSE for unavailable network information (#63633) * Update tests * Add android specific implementation * Add UnsupportedOSPlatform attributes * Fix typo * Remove unnecessary file reference * Clean-up code * Minor code clean-up * Remove dictionary * Refactoring * Revert comment change commit 77bdad50a01f3a330c03b093544245d39620314b Author: Alexander Köplinger Date: Thu Jan 13 16:06:39 2022 +0100 Bump to macOS 10.14 minimum in libs and mono builds too (#63682) https://github.com/dotnet/runtime/pull/62822 bumped the minimum CMAKE_OSX_DEPLOYMENT_TARGET to 10.14, but the libs.native and mono parts of the build still used the old 10.13 value. In build-native.sh for libs.native we can actually remove the explicit setting since we're already setting it in eng/native/configurecompiler.cmake. commit 01cdd1dcaebcc9f2ab36027204142a6703a1b70b Author: Pavel Savara Date: Thu Jan 13 15:42:08 2022 +0100 [wasm] Emscripten uses `require` even when targeting ES6. This deals with the consequences. (#63718) commit a13ee96335ea4c41cfe273855611caec4c35cae8 Author: Thays Grazia Date: Thu Jan 13 09:53:43 2022 -0300 [wasm][debugger] Fixing error after receiving loaded_files = null (#63591) * Fixing #39301 * Addressing @radical comments * Sending the error toconsole in the browser. * Applying @radical suggestion. * Update src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs Co-authored-by: Ankit Jain * Update src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html Co-authored-by: Ankit Jain * Space -> tabs * Fix compilation error. Co-authored-by: Ankit Jain commit 64c05a3bcb4e71ee9972a3fb47eb4d3e061d3462 Author: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Thu Jan 13 12:58:37 2022 +0300 Reconfigure the field sequences for statics (#62632) * Reconfigure the field sequences for statics To make the "boxed static" and, in th… * Clean up RegexCode opcodes and debug-only tracing (#64346) * Clean up RegexCode opcodes and debug-only tracing No functional changes (other than deleting some useless debug-only tracing). Cleans up RegexCode's const int opcodes by moving them into a dedicated enum, and cleans up some unused debugging-related code. We may want to remove even more, but I at least wanted to get rid of RegexOptions.Debug so that we didn't have the extra option littered throughout the code. * Address PR feedback * Run Pi tests on a different queue, which runs ARM32 tests (#64353) I blogged about the negative performance implications of this in 2019 (CP15 memory barriers are emulated on ARMv8 kernels, and issue an all-core pipeline flush and ~1000 cycle penalty; the performance loss scales exponentially with the number of cores in the system) * [mono] Avoid inlining the wrappers used by CALLI. (#64290) They contain an LMF and the inlining removes it. Fixes https://github.com/dotnet/runtime/issues/64073. * JIT: Clone ADDR(LCL) for DUP (#64171) * [mono] Always store to allocas in OP_LLVM_OUTARG_VT (#64303) OP_LLVM_OUTARG_VT will, for some argument passing conventions, create an alloca and mirror its source SSA value into this alloca. If such an OP_LLVM_OUTARG_VT is first encountered in a basic block that does not contain the definition of the SSA value being mirrored, then sibling basic blocks (e.g. a loop body that may sometimes be skipped) can use garbage data if they also have OP_LLVM_OUTARG_VT opcodes referring to the same SSA values. This commit works around this by unconditionally storing the source OP_LLVM_OUTARG_VT value into its associated alloca. The resulting IR would be a little easier to read if we eagerly stored to an alloca mirror exactly once at each value's definition, but that would require more work to implement. Fixes JIT/SIMD/VectorExp_ro/VectorExp_ro. See https://github.com/dotnet/runtime/issues/64179. * Remove some of the unused resource strings (#64379) * Fix minor things in comments to DllImportGenerator (#64088) * ARM64: Avoid LEA for volatile IND (#64354) Co-authored-by: Kunal Pathak * [docs] Collecting stack traces with native symbols on WebAssembly (#64383) * [docs] Collecting stack traces with native symbols on WebAssembly * Apply suggestions from code review Co-authored-by: Larry Ewing Co-authored-by: Ankit Jain Co-authored-by: Larry Ewing Co-authored-by: Ankit Jain * Add attributes for required members (#64287) * Add attributes for required members Closes https://github.com/dotnet/runtime/issues/64248. * Address PR feedback * Update src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems * Address PR feedback * fix arm64 genInstrWithConstant (#64368) * 2 fixes related to commit/decommit (#64316) fixed 2 bugs related to commit/decommit - in committed_size we need to get the committed in free correctly with the region_free_list change. in decommit_heap_segment_pages_worker we need the right data type for comparing heap_segment_committed with new_committed as the latter could be before the former. * Build ILCompiler NuGet packages (#63212) This is using the same strategy we used to build the package in the runtimelab repo. * [mono] Re-enable tests that call MakeGenericType with non-RuntimeType arguments (#64344) * [mono] Re-enable tests that call MakeGenericType with non-RuntimeType arguments Fixes https://github.com/dotnet/runtime/issues/32743 The actual fix was in https://github.com/dotnet/runtime/pull/58014 * [wasm] Disable some logging generator tests `Microsoft.Extensions.Logging.Generators.Tests.LoggerMessageGeneratorEmitterTests.*` `Microsoft.Extensions.Logging.Generators.Tests.LoggerMessageGeneratorParserTests.*` .. failing like: ``` [18:09:38] fail: [FAIL] Microsoft.Extensions.Logging.Generators.Tests.LoggerMessageGeneratorParserTests.NotPartial [18:09:38] info: System.ArgumentException : Empty path name is not legal. (Parameter 'path') [18:09:38] info: at System.IO.Strategies.FileStreamHelpers.ValidateArguments(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, Int64 preallocationSize) [18:09:38] info: at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, Int64 preallocationSize) [18:09:38] info: at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) [18:09:38] info: at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync) [18:09:38] info: at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share) [18:09:38] info: at Roslyn.Utilities.StandardFileSystem.OpenFile(String filePath, FileMode mode, FileAccess access, FileShare share) [18:09:38] info: at Roslyn.Utilities.CommonCompilerFileSystemExtensions.OpenFileWithNormalizedException(ICommonCompilerFileSystem fileSystem, String filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileShare) [18:09:38] info: at Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(String path, MetadataReferenceProperties properties, DocumentationProvider documentation) [18:09:38] info: at SourceGenerators.Tests.RoslynTestUtils.CreateTestProject(IEnumerable`1 references, Boolean includeBaseReferences) [18:09:38] info: at SourceGenerators.Tests.RoslynTestUtils.RunGenerator(ISourceGenerator generator, IEnumerable`1 references, IEnumerable`1 sources, Boolean includeBaseReferences, CancellationToken cancellationToken) [18:09:38] info: at Microsoft.Extensions.Logging.Generators.Tests.LoggerMessageGeneratorParserTests.RunGenerator(String code, Boolean wrap, Boolean inNamespace, Boolean includeBaseReferences, Boolean includeLoggingReferences, CancellationToken cancellationToken) [18:09:38] info: at Microsoft.Extensions.Logging.Generators.Tests.LoggerMessageGeneratorParserTests.NotPartial() [18:09:38] info: --- End of stack trace from previous location --- ``` .. due to https://github.com/dotnet/runtime/issues/52062 . * Disable RegistrationBuilderTests that require ref emit on platforms that don't support it Co-authored-by: Ankit Jain * Disable ipv6 lookup tests when needed (#64313) * Disable ipv6 lookup tests when needed * comment * nit * Temporarily disable EC file import tests (#64397) * Fix Xamarin assembly names in HttpClientHandler (#64385) Update to match the new names from https://github.com/xamarin/xamarin-macios/pull/13847 * Align rva fields in reflection emit (#63430) In support of CreateSpan (#60948), improve alignment for RVA static pre-initialized fields to align memory blocks which may contain long, ulong, or double primitive arrays on 8 byte boundaries. Mono fix is more involved - Fix Ref-Emit generated RVA statics - Set the HasFieldRVA bit. NOTE: earlier code that attempts to set the bit doesn't actually do that as the FieldRVA bit is in FieldAttributes.ReservedMask which is masked away in the FieldBuilder constructor - Fix the Swizzle lookup. We should not be using the 8 byte swizzle in the final else clause. - Enhance ref-emitted field to allow for use with CreateSpan - Ref-emitted fields should specify a pack size appropriate for minimum alignment of the CreateSpan targetted data - Respect the packing_size specified so that RVA static fields generated for CreateSpan can be properly aligned Fixes #62314 * [JIT] Use byteCount when deciding what instruction sequence to use in genCodeForCpBlkUnroll (#64315) * Add regression test for https://github.com/dotnet/runtime/issues/64125 * Don't base decision whether to use ldp/stp or ldr/str for CopyBlock based on a distance between dstOffsetAligned and endDstOffset. The value can increase when dstOffset is updated and can lead to an un-encodable ldp instruction offset if before we were validating ldr/str path in src/coreclr/jit/codegenarmarch.cpp * Update tests per feedback * Try disabling the test for wasm and monointerpreter * Fix ExitDetectionNotBlockedByHandler test (#64407) * enable osr stress tests for libraries and add fixes (#64116) * add osr plus stress tests for libraries * (Fix) have tier0 method always report generics context, then OSR method can just use that * Add ability to suppress patchpoints by hash. * Dump IR after patchpoints phase, if any were added * (Fix) Fix bug in recursive tail call detection -- if we devirtualize we need to update the method handle we use. OSR methods rely on getting this detection right so they know if they need to import the method entry block. * (Fix) refine OSR enabling/backoff to opt logic. With OSR enabled, we were forcing too many methods to be optimized. * reorder phase whitelist to more closely match phase order * Fix DateOnly and TimeOnly Formatting using interpolated strings (#64398) * gcc compilations for ARM64 can not initialize extern "C" variables. (#64239) * Clang compilations for ARM64 can not initialize extern "C" variables. Some versions of clang targeted to ARM64 do not allow extern "C" variables to be initialized at the point of extern "C" declarations, although this many not be caught until the assembler of linker is run, at which time an illegal relocation type is discovered. Per advice from Jan Vorlicek. * Change 6 initialized extern "C" declarations to split declaration and initialization. This seems to remove 2*6==12 warning errors initialized and declared ‘extern’ some of which were errors with modern gcc on ARM64. * Correctly declare extern "C" ... JIT_WriteBarrier_Loc and companion. * Add Metrics UpDownCounter (#64365) Co-authored-by: Noah Falk * Change condition on RegexReductionTests to be explicit about trimming (#64411) * Removing `tiVerificationNeeded` in the JIT (#64356) * Removing tiVerificationNeeded in the JIT * Removed addVerifyFlag * Fixing build * format * Format fixes * Add support for byref fields in NativeAOT/crossgen2 (#64366) The only necessary changes at this point were in code shared between crossgen2 and NativeAOT. * fix ping with SendIpHeader on FreeBSD (#63531) * fix ping with SendIpHeader on FreeBSD * update to fix command line and DF * add comment * Throw during renegotiation if there is incomplete received TLS frame (#64066) We need to check both if there is unread data from previous TLS frame, or if there is incomplete incoming TLS frame * AltTrailingSlash tests should actually use AltDirectorySeparatorChar (#64437) * Remove Native AOT pointer to runtimelab (#64429) * Delete null comparisons of non-null arguments (#64435) * Fix NativeAOT official build (#64432) Official builds are currently not building NativeAOT CoreLib. For unknown reasons the official build splits native build and managed build of the CoreCLR partition. We had a convenient clr.nativeaotlibs subset that built both the native part and managed part. Managed part can't be built without the native part, so it makes sense. To satisfy official build's weirdness, we need to split this into two subsets so that we can tell the official build to build the managed part. (Official builds already build everything in the native part, so we're good there.) * Remove empty Dispose method in InflaterManaged (#64443) * [mono][windows] Disable Microsoft.Extensions.Logging.Generators.TestsLoggerMessageGeneratorEmitterTests with ActiveIssue (#64436) Addresses #64344 (comment) ... and skips System.Reflection.Emit.Tests.ModuleBuilderDefineInitializedData.DefineInitializedData_EnsureAlignmentIsMinimumNeededForUseOfCreateSpan test which requires reflection emit and fails on tvOS arm64 leg. * #51371 removed CaseInsensitivePlatforms and CaseSensitivePlatforms parameters (#64440) * [wasm][debugger] Move the breakpoint line after applying changes (#64359) When hot-reloading code with new lines added, VS automatically updates the breakpoints by sending Remove/SetBreakpoint commands. Add a test case for the reload, with simulated VS part. * pass the argument forward (#64445) * Ignore non-X509 certificates in SignedCms This allows for AttributeCertificateV1/AttributeCertificateV2/OtherCertificate entries in the SignedCms without causing a decode error. That data is not presented to callers via the SignedCms object, but the behavior is consistent with SignedCms on .NET Framework and its underlying WinCryptMsg counterpart. Co-authored-by: Jeremy Barton * Use a non-generic TaskCompletionSource in SystemIPGlobalProperties. (#64423) * Fix BigInteger outerloop test failure (#64402) * Don't disable LEA for byrefs (#64444) * Expand System.Runtime.InteropServices.NFloat to support the APIs required by Xamarin (#64234) * Expand System.Runtime.InteropServices.NFloat to support the APIs required by Xamarin * Apply suggestions from code review Co-authored-by: Rolf Bjarne Kvinge * Adding NFloat tests (p1) * Temporarily disable negative conversions involving nfloat->nint * Adjusting the skip condition for the Mono failures * Adding additional tests covering the NFloat.Is* APIs * Fixing the IsNormal and IsSubnormal test to account for 64-bit vs 32-bit Co-authored-by: Rolf Bjarne Kvinge * Add/use ArgumentException.ThrowIfNullOrEmpty (#64357) Adds ArgumentException.ThrowIfNullOrEmpty and then uses it in a bunch of places around the tree. Most of the replaced places used a resource string for the message, and I used it in places where it didn't feel like we were losing any meaningful information by centralizing on the single shared string, but I didn't use it in places where the resource string message used in the empty case conveyed something that seemed useful, e.g. a recommendation on what to use instead of an empty string. There are a few places where I allowed for order of exception throws to change in the case where there were multiple user errors and the validation for a single argument was split, e.g. I changed a few cases of: ```C# if (arg1 is null) throw new ArgumentNullException(...); if (arg2 is null) throw new ArgumentNullException(...); if (arg1.Length == 0) throw new ArgumentException(...); if (arg2.Length == 0) throw new ArgumentException(...); ``` to: ```C# ArgumentException.ThrowIfNullOrEmpty(arg1); ArgumentException.ThrowIfNullOrEmpty(arg2); ``` even though it'll produce a different exception for `M("", null)` than it would previously. Technically a breaking change, but given this is a case of multiple usage errors and all the exceptions are ArgumentException-based, I think it's acceptable. I wanted to get this in before we do the massive !! conversion, as I expect !! auto-fixes will make it a bit harder to roll this out. I explicitly did not do anything to roll out use of ArgumentNullException.ThrowIfNull, except in cases where I was modifying a method to use ArgumentException.ThrowIfNullOrEmpty, in which case for consistency I changed anything else in the function that could have been using ThrowIfNull to do so. * Commutative morph optimizations (#64122) * Optimize order of morphing "fgMorphCommutative" exposes information to the later transforms that make them more precise. For example, "MUL(MUL(X, CONST1), CONST2)" is now morphed properly into a single "mul" instead of one "mul" plus a shift and lea in case "CONST2" was a viable candidate for "mulshift". Another example is how "fgMorphCommutative" can end up with an "ADD(X, 0)" that was only being discarded in lowering. * Fold (x + 0) => 0 for LONGs on 32 bit * Enable one opt outside global morph No reason not to. Just a few diffs. * Disable mulshift on ARM/64 No LEAs - no point. * Remove pinning from StringBuilder (#64405) Switch from pointers to refs to avoid pinning the inputs. As part of this, I also consolidated the fast-path that was there specifically for string inputs to also apply to span inputs, char arrays, pointers, etc. * Check for CMAKE_C_COMPILER_ID not CXX (#64226) * Check for CMAKE_C_COMPILER_ID not CXX In some cases, CMAKE_CXX_COMPILER_ID might not be populated, which causes the toolchaine prefix checks to be ignored, which causes the build to look for `ranlib` not `llvm-ranlib`, which causes it to use XCode ranlib instead of Android NDK ranlib for builds, which doesn't work. Hopefully (we'll see what CI says) this doesn't regress other builds. Closes: #55412 * Update eng/native/configuretools.cmake Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> * Use llvm-objcopy, not GNU, on Android It's available in r21 (which we use today) and works for r23 (which has no GNU objcopy any more and breaks without this change) Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> * remove support for Ssl2 (#64322) * remove support for Ssl2 * update test * update exeception type * remove Sslv2 test * Fix JIT rolling build issue with non-JIT changes (#64480) When uploading a JIT rolling build, use the git hash of the most recent JIT change, not the git hash that was actually built. This handles the case where a JIT change kicked off an AzDO pipeline, but the pipeline didn't start until after one or more additional changes were merged. The AzDO pipelines appear to fetch with `-depth=20`, which should provide enough history for almost any case. Fixes #64392 * More cleanups in assembly loader area (#63157) * GetManifestFile() --> GetPEAssembly() * GetManifestImport() -> GetMDImport() * removed GetCurrentAssembly(), GetLoadedAssembly() * removed GetCurrentModule(), GetLoadedModule() * fix * removed DomainFile::ModuleIterator * renamed Assembly::GetManifestModule() --> GetModule() * Removed Assembly::ModuleIterator * move most fields off DomainAssembly * DomainAssembly is a complete proxy * some DomainFile --> DomainAssembly renames. * deleted DomainFile class * renamed files * a few minor cleanups * DomainAssembly does not need to have VPTR_. Couple other changes. * More DomainFile --> DomainAssembly renames * More DomainFile --> DomainAssembly renames * a few more renames * removed domainassembly.inl * domainassembly.h cleanup * make gcc happy * couple more changes * fixed build after rebasing * PR feedback * more PR feedback * JIT: fix x86 codegen issue (#64476) We were not calling `genProduceReg` in one case, leading to a missing def and liveness assert. Normally this would have been a temp assign followed by a copy to a local; evidently we don't track liveness for temps and so don't notice the missing def, and the subsequent copy defs the local and all seems well. Forward sub gets rid of the copy and exposes the issue under jit stress. * Temporarily disable test Runtime_60035 failing with Crossgen2 (#64420) * [mono] Fix r8->i conversion on amd64/arm64. (#64467) Fixes https://github.com/dotnet/runtime/issues/64386. * Remove CheckForOverflowUnderflow (#63825) * Remove set false to CheckForOverflowUnderflow due to it is disabled by default * Use checked instead of CheckForOverflowUnderflow * Remove command-line arguments from Main methods in ILPROj projects (#64482) In my recent change I fixed C# test projects to stop using command-line arguments. This follow-up change complements it by applying the same transformation to IL projects. In most cases the arguments were ignored so the transformation was trivial; in the special case of twoEndFinallys.il the argument array is passed to the method TwoEndFinallys so I patched it to allocate a zero-sized string array instead (there are no tests passing actual command-line arguments to the test app). Thanks Tomas * [wasm] Cancel pending ReadableStream on Dispose or cancelationToken (#64285) - call cancel when disposing ReadableStream - add unit test for the scenario - enabled cancelation tests for browser - fixed few cancelation issues Co-authored-by: Larry Ewing * Use const enums in typescript since regular enums generate extremely bad code (#64486) To get good behavior in typescript, your enums need to be 'const enum', otherwise it generates some really gross JS with runtime overhead. * Fix layout and GCInfo for ByRef fields. (#64422) * Fix the GCInfo for types containing ByRef fields. Update tests to use recursion and validate GCStress scenarios. * Update stack walking for ref field discovery. * Indicate the TypedReference is a value type during field initialization. - This was missed in the initial support for ref fields. * Fold inbox crypto into one assembly (#64307) * Fold S.S.C.Csp into System.Security.Cryptography This change leaves the tests in System.Security.Cryptography.Csp.Tests.dll, because the crypto test infrastructure has not yet been upgraded to allow for two algorithm provider tests in the same assembly (e.g. not both Aes.Create() and AesCryptoServiceProvider can be tested) * Change CryptoConfig string lookups to typeof for CSP types * Fold S.S.C.Cng into S.S.Cryptography * Fold S.S.C.OpenSsl into S.S.Cryptography * Fold S.S.C.X509Certificates into S.S.Cryptography * Fix dependent projects * Fix ApiCompat errors * Self-feedback * Use typeof where now possible in CryptoConfig * Don't use CNG's PKCS8 export for default EC objects * RSA should probably function on Unix * Fix nullability state of ChainPal.BuildChain across OSes * Remove bad assert * Special case macOS ECC data keys in CopyWithPrivateKey * Undo some of the string resurrections * Add missing Obsolete attribute * Fix UnobservedTaskException on Http2's SendPingAsync (#64494) Wrap the SendPingAsync function with LogExceptions in Http2Connection.cs to avoid any exception here being caught as an UnobservedTaskException. Fix #64450 Signed-off-by: Shubhanshu Saxena * Permit longer chain building fetching for dynamic revocation tests This is meant to address the flakiness where chain building can time out for very busy CI machines. The test fixture is already outerloop, so extending the timeout should not adversely affect CI inner loop performance. * [mono] Fix downcast check in Array.CopySlow (#64469) * Add regression test for object[] -> Int32Enum[] array copy where each element in the source array is the appropriate type * Fix downcast check in slow array copy When we have to resort to checking element by element, compare the type of each actual element with the destination type. In particular, not the destinations underlying type when it's an enum - we don't want to allow unrelated enums using the same representation to copy over. Fixes https://github.com/dotnet/runtime/issues/64387 * Move SafeHandle implementation to FileStatus. Co-authored-by: Brennan Co-authored-by: Egor Bogatov Co-authored-by: Bruce Forstall Co-authored-by: Miha Zupan Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Co-authored-by: Pavel Savara Co-authored-by: Egor Chesakov Co-authored-by: Ankit Jain Co-authored-by: Jeremy Koritzinsky Co-authored-by: Santiago Fernandez Madero Co-authored-by: Elinor Fung Co-authored-by: Dan Moseley Co-authored-by: Andy Ayers Co-authored-by: Tomáš Rylek Co-authored-by: Andrew Au Co-authored-by: Will Smith Co-authored-by: Tlakaelel Axayakatl Ceja Co-authored-by: Jeremy Barton Co-authored-by: Peter Sollich Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Co-authored-by: Maxim Lipnin Co-authored-by: Marek Fišera Co-authored-by: Pavel Savara Co-authored-by: Alexander Köplinger Co-authored-by: Stephen Toub Co-authored-by: Michal Strehovský Co-authored-by: Eirik Tsarpalis Co-authored-by: David Cantú Co-authored-by: yowl Co-authored-by: Eric StJohn Co-authored-by: Jan Kotas Co-authored-by: Parker Bibus Co-authored-by: Jan Vorlicek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: JamesNK Co-authored-by: Tanner Gooding Co-authored-by: Wrzucher Co-authored-by: Kevin Jones Co-authored-by: Adam Sitnik Co-authored-by: Viktor Hofer Co-authored-by: Johan Lorensson Co-authored-by: Steve Sanderson Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: dotnet-maestro[bot] Co-authored-by: Přemek Vysoký Co-authored-by: Mike McLaughlin Co-authored-by: Jakob Botsch Nielsen Co-authored-by: Thays Grazia Co-authored-by: Andy Gocke Co-authored-by: Maksym Koshovyi Co-authored-by: Zoltan Varga Co-authored-by: Pavel Ivanov Co-authored-by: Floris Westerman Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Vladimir Sadov Co-authored-by: Julius Hardt Co-authored-by: Aaron Robinson Co-authored-by: David Wrighton Co-authored-by: Wraith Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Co-authored-by: carlossanlop Co-authored-by: Eaton Zveare Co-authored-by: Jeff Handley Co-authored-by: Christopher Moore Co-authored-by: Katya Sokolova Co-authored-by: Joshua Peterson Co-authored-by: imhameed Co-authored-by: Eric Erhardt Co-authored-by: Gleb Balykov Co-authored-by: Mitchell Hwang <16830051+mdh1418@users.noreply.github.com> Co-authored-by: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Co-authored-by: Jo Shields Co-authored-by: Maoni Stephens Co-authored-by: Kunal Pathak Co-authored-by: Koundinya Veluri Co-authored-by: Steve Pfister Co-authored-by: Steve Harter Co-authored-by: Bradley Grainger Co-authored-by: Roman Marusyk Co-authored-by: Robert Henry Co-authored-by: Maryam Ariyan Co-authored-by: Bar Arnon Co-authored-by: Tom Deseyn Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Co-authored-by: Filip Navara Co-authored-by: Andrii Kurdiumov Co-authored-by: madelson <1269046+madelson@users.noreply.github.com> Co-authored-by: Aleksey Kliger (λgeek) Co-authored-by: Vladimir Djurić Co-authored-by: vdjuric Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> Co-authored-by: Meri Khamoyan <96171496+mkhamoyan@users.noreply.github.com> Co-authored-by: Larry Ewing Co-authored-by: Fred Silberberg Co-authored-by: Tarek Mahmoud Sayed Co-authored-by: Noah Falk Co-authored-by: Tomas Weinfurt Co-authored-by: Marek Safar Co-authored-by: Theodore Tsirpanis Co-authored-by: Rolf Bjarne Kvinge Co-authored-by: Katelyn Gadd Co-authored-by: Shubhanshu Saxena <54344426+shubhanshu02@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- .devcontainer/Dockerfile | 9 + .devcontainer/devcontainer.json | 19 +- .devcontainer/scripts/onCreateCommand.sh | 8 + .github/fabricbot.json | 2810 ++++- .gitignore | 1 + Directory.Build.props | 1 + NuGet.config | 1 + THIRD-PARTY-NOTICES.TXT | 29 + docs/coding-guidelines/libraries-packaging.md | 7 + docs/design/features/standalone-gc-loading.md | 2 +- .../DllImportGenerator/StructMarshalling.md | 73 +- docs/design/specs/Ecma-335-Augments.md | 10 + docs/design/specs/PortablePdb-Metadata.md | 2 + docs/pr-builds.md | 94 + docs/pr-guide.md | 63 +- docs/project/glossary.md | 5 +- docs/workflow/building/coreclr/nativeaot.md | 2 +- .../building/coreclr/osx-instructions.md | 43 +- .../debugging/libraries/debugging-corelib.md | 7 + .../workflow/debugging/mono/wasm-debugging.md | 130 +- eng/CodeAnalysis.src.globalconfig | 4 +- eng/CodeAnalysis.test.globalconfig | 2 +- eng/Subsets.props | 15 +- eng/Version.Details.xml | 252 +- eng/Versions.props | 127 +- eng/build.sh | 6 +- eng/common/cross/arm/tizen-build-rootfs.sh | 0 eng/common/cross/arm/tizen-fetch.sh | 0 eng/common/cross/build-rootfs.sh | 12 +- eng/common/cross/toolchain.cmake | 11 +- eng/common/internal/NuGet.config | 7 + eng/common/post-build/publish-using-darc.ps1 | 28 +- eng/common/templates/job/execute-sdl.yml | 19 +- eng/common/templates/job/onelocbuild.yml | 18 +- eng/common/templates/jobs/jobs.yml | 10 +- .../channels/generic-internal-channel.yml | 190 - .../channels/generic-public-channel.yml | 192 - .../templates/post-build/common-variables.yml | 69 - .../templates/post-build/post-build.yml | 626 +- .../post-build/setup-maestro-vars.yml | 124 +- eng/common/templates/steps/source-build.yml | 2 +- eng/formatting/format.sh | 0 eng/liveBuilds.targets | 3 + eng/native/build-commons.sh | 6 +- eng/native/configurecompiler.cmake | 19 + eng/native/configureplatform.cmake | 13 + eng/native/configuretools.cmake | 10 +- eng/native/functions.cmake | 6 +- eng/native/init-os-and-arch.sh | 4 + eng/native/tryrun.cmake | 6 +- eng/packaging.targets | 7 +- eng/pipelines/common/global-build-job.yml | 11 +- eng/pipelines/common/platform-matrix.yml | 29 +- .../templates/runtimes/run-test-job.yml | 7 +- eng/pipelines/common/variables.yml | 14 +- eng/pipelines/common/xplat-setup.yml | 19 +- .../coreclr/templates/build-jit-job.yml | 6 +- eng/pipelines/coreclr/templates/build-job.yml | 6 +- .../coreclr/templates/helix-queues-setup.yml | 1 + eng/pipelines/coreclr/templates/perf-job.yml | 2 +- .../libraries/helix-queues-setup.yml | 72 +- eng/pipelines/libraries/outerloop-mono.yml | 8 +- eng/pipelines/libraries/outerloop.yml | 18 +- eng/pipelines/libraries/run-test-job.yml | 4 + eng/pipelines/libraries/variables.yml | 2 +- eng/pipelines/runtime-community.yml | 4 +- ...manual.yml => runtime-extra-platforms.yml} | 633 +- eng/pipelines/runtime-official.yml | 2 +- eng/pipelines/runtime-staging.yml | 357 +- eng/pipelines/runtime.yml | 218 +- eng/pipelines/runtimelab.yml | 4 +- eng/targetingpacks.targets | 4 +- eng/testing/RunnerTemplate.sh | 3 +- eng/testing/WasmRunnerTemplate.cmd | 2 +- eng/testing/WasmRunnerTemplate.sh | 2 +- eng/testing/default.rd.xml | 81 + eng/testing/tests.props | 1 + eng/testing/tests.singlefile.targets | 26 +- eng/testing/tests.wasm.targets | 4 +- eng/testing/xunit/xunit.props | 1 + global.json | 10 +- .../Microsoft.ILVerification.pkgproj | 2 +- src/coreclr/CMakeLists.txt | 1 - .../System.Private.CoreLib.csproj | 2 - .../Diagnostics/SymbolStore/SymAddressKind.cs | 49 - .../System/Diagnostics/SymbolStore/Token.cs | 39 - .../src/System/Math.CoreCLR.cs | 8 - .../System/Reflection/AssemblyName.CoreCLR.cs | 29 - .../System/Reflection/Emit/AssemblyBuilder.cs | 18 +- .../System/Reflection/Emit/FieldBuilder.cs | 9 +- .../src/System/Reflection/Emit/ILGenerator.cs | 6 +- .../System/Reflection/Emit/MethodBuilder.cs | 12 +- .../System/Reflection/Emit/ModuleBuilder.cs | 48 +- .../System/Reflection/Emit/PropertyBuilder.cs | 5 +- .../src/System/Reflection/Emit/TypeBuilder.cs | 50 +- .../src/System/Reflection/MdImport.cs | 2 + .../src/System/RuntimeHandles.cs | 5 +- .../src/System/RuntimeType.CoreCLR.cs | 2 +- src/coreclr/ToolBox/CMakeLists.txt | 2 - src/coreclr/binder/assemblybindercommon.cpp | 2 +- src/coreclr/binder/bindertracing.cpp | 4 +- src/coreclr/binder/inc/assemblyidentity.hpp | 5 - src/coreclr/binder/inc/bindertracing.h | 2 +- src/coreclr/binder/inc/stringlexer.hpp | 16 +- src/coreclr/binder/inc/stringlexer.inl | 164 +- .../binder/inc/textualidentityparser.hpp | 11 +- src/coreclr/binder/stringlexer.cpp | 28 +- src/coreclr/binder/textualidentityparser.cpp | 71 +- src/coreclr/build-runtime.cmd | 5 +- src/coreclr/build-runtime.sh | 2 +- .../classlibnative/float/floatdouble.cpp | 9 - .../classlibnative/float/floatsingle.cpp | 21 - src/coreclr/classlibnative/inc/floatdouble.h | 1 - src/coreclr/classlibnative/inc/floatsingle.h | 1 - src/coreclr/clrdefinitions.cmake | 1 - src/coreclr/components.cmake | 1 + src/coreclr/debug/daccess/daccess.cpp | 97 +- src/coreclr/debug/daccess/dacdbiimpl.cpp | 154 +- src/coreclr/debug/daccess/dacdbiimpl.h | 26 +- .../debug/daccess/dacdbiimplstackwalk.cpp | 16 +- src/coreclr/debug/daccess/dacimpl.h | 35 +- src/coreclr/debug/daccess/request.cpp | 30 +- src/coreclr/debug/daccess/task.cpp | 24 +- src/coreclr/debug/di/breakpoint.cpp | 2 +- src/coreclr/debug/di/cordb.cpp | 10 - src/coreclr/debug/di/divalue.cpp | 10 +- src/coreclr/debug/di/module.cpp | 60 +- src/coreclr/debug/di/nativepipeline.h | 22 - src/coreclr/debug/di/process.cpp | 125 +- src/coreclr/debug/di/publish.cpp | 93 +- src/coreclr/debug/di/rsappdomain.cpp | 20 +- src/coreclr/debug/di/rsclass.cpp | 12 +- src/coreclr/debug/di/rsfunction.cpp | 12 +- src/coreclr/debug/di/rsmain.cpp | 28 +- src/coreclr/debug/di/rspriv.h | 37 +- src/coreclr/debug/di/rsstackwalk.cpp | 2 +- src/coreclr/debug/di/rsthread.cpp | 36 +- src/coreclr/debug/di/rstype.cpp | 32 +- src/coreclr/debug/di/shimpriv.h | 9 - src/coreclr/debug/di/shimprocess.cpp | 225 - src/coreclr/debug/di/windowspipeline.cpp | 182 - src/coreclr/debug/ee/debugger.cpp | 140 +- src/coreclr/debug/ee/debugger.h | 22 +- src/coreclr/debug/ee/debugger.inl | 6 +- src/coreclr/debug/ee/debuggermodule.cpp | 2 +- src/coreclr/debug/ee/rcthread.cpp | 29 +- src/coreclr/debug/inc/dacdbiinterface.h | 48 +- src/coreclr/debug/inc/dacdbistructures.h | 16 +- src/coreclr/debug/inc/dacdbistructures.inl | 4 +- src/coreclr/debug/inc/dbgipcevents.h | 75 +- .../debug/shared/dbgtransportsession.cpp | 5 - src/coreclr/dlls/dbgshim/dbgshim.cpp | 11 - .../dlls/mscordac/mscordac_unixexports.src | 3 - src/coreclr/dlls/mscorrc/mscorrc.rc | 5 + src/coreclr/dlls/mscorrc/resource.h | 5 + src/coreclr/gc/gc.cpp | 141 +- src/coreclr/gc/gcconfig.h | 6 +- src/coreclr/gc/gcinterface.dac.h | 2 +- src/coreclr/gc/gcpriv.h | 14 +- src/coreclr/gc/unix/gcenv.unix.cpp | 4 + src/coreclr/hosts/corerun/corerun.cpp | 8 +- src/coreclr/hosts/corerun/corerun.hpp | 48 +- src/coreclr/hosts/corerun/dotenv.cpp | 23 +- src/coreclr/inc/bbsweep.h | 105 +- src/coreclr/inc/clrconfigvalues.h | 34 +- src/coreclr/inc/clrtypes.h | 2 +- src/coreclr/inc/dacvars.h | 2 +- src/coreclr/inc/holder.h | 9 +- src/coreclr/inc/ostype.h | 32 - src/coreclr/inc/sigparser.h | 15 + src/coreclr/inc/switches.h | 2 - src/coreclr/inc/volatile.h | 5 +- src/coreclr/inc/vptr_list.h | 5 - src/coreclr/inc/winwrap.h | 15 - src/coreclr/jit/CMakeLists.txt | 20 +- src/coreclr/jit/assertionprop.cpp | 3 +- src/coreclr/jit/block.h | 11 + src/coreclr/jit/codegenarm.cpp | 2 +- src/coreclr/jit/codegenarm64.cpp | 7 +- src/coreclr/jit/codegenarmarch.cpp | 59 +- src/coreclr/jit/codegencommon.cpp | 41 +- src/coreclr/jit/codegenlinear.cpp | 6 +- src/coreclr/jit/codegenxarch.cpp | 1 + src/coreclr/jit/compiler.cpp | 91 +- src/coreclr/jit/compiler.h | 95 +- src/coreclr/jit/compiler.hpp | 85 +- src/coreclr/jit/compphases.h | 5 +- src/coreclr/jit/copyprop.cpp | 234 +- src/coreclr/jit/earlyprop.cpp | 2 +- src/coreclr/jit/ee_il_dll.hpp | 8 - src/coreclr/jit/emit.h | 137 +- src/coreclr/jit/emitarm64.cpp | 42 +- src/coreclr/jit/emitxarch.cpp | 16 +- src/coreclr/jit/emitxarch.h | 2 +- src/coreclr/jit/error.cpp | 6 +- src/coreclr/jit/fgbasic.cpp | 67 +- src/coreclr/jit/fgdiagnostic.cpp | 91 +- src/coreclr/jit/fgehopt.cpp | 6 +- src/coreclr/jit/fginline.cpp | 4 +- src/coreclr/jit/fgopt.cpp | 49 +- src/coreclr/jit/fgprofile.cpp | 23 +- src/coreclr/jit/fgstmt.cpp | 2 +- src/coreclr/jit/flowgraph.cpp | 83 +- src/coreclr/jit/gentree.cpp | 445 +- src/coreclr/jit/gentree.h | 157 +- src/coreclr/jit/gtlist.h | 3 +- src/coreclr/jit/gtstructs.h | 6 +- src/coreclr/jit/hwintrinsic.cpp | 56 +- src/coreclr/jit/hwintrinsic.h | 19 + src/coreclr/jit/hwintrinsicarm64.cpp | 104 +- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 26 + src/coreclr/jit/hwintrinsiccodegenxarch.cpp | 58 +- src/coreclr/jit/hwintrinsiclistarm64.h | 74 +- src/coreclr/jit/hwintrinsiclistxarch.h | 80 +- src/coreclr/jit/hwintrinsicxarch.cpp | 192 +- src/coreclr/jit/importer.cpp | 1270 +-- src/coreclr/jit/inline.def | 2 + src/coreclr/jit/inlinepolicy.cpp | 22 +- src/coreclr/jit/inlinepolicy.h | 4 + src/coreclr/jit/instr.cpp | 37 +- src/coreclr/jit/instrsarm64.h | 8 +- src/coreclr/jit/instrsxarch.h | 2 +- src/coreclr/jit/jitconfigvalues.h | 18 +- src/coreclr/jit/lclmorph.cpp | 31 +- src/coreclr/jit/lclvars.cpp | 73 +- src/coreclr/jit/lir.cpp | 2 +- src/coreclr/jit/liveness.cpp | 1 - src/coreclr/jit/loopcloning.cpp | 4 +- src/coreclr/jit/lower.cpp | 104 +- src/coreclr/jit/lower.h | 10 +- src/coreclr/jit/lowerarmarch.cpp | 222 +- src/coreclr/jit/lowerxarch.cpp | 418 +- src/coreclr/jit/lsra.cpp | 16 +- src/coreclr/jit/lsra.h | 2 +- src/coreclr/jit/lsraarm64.cpp | 76 +- src/coreclr/jit/lsraarmarch.cpp | 54 +- src/coreclr/jit/lsrabuild.cpp | 17 + src/coreclr/jit/lsraxarch.cpp | 3 +- src/coreclr/jit/morph.cpp | 808 +- src/coreclr/jit/morphblock.cpp | 181 +- src/coreclr/jit/namedintrinsiclist.h | 6 +- src/coreclr/jit/optcse.cpp | 18 +- src/coreclr/jit/optimizer.cpp | 132 +- src/coreclr/jit/phase.cpp | 41 +- src/coreclr/jit/rangecheck.cpp | 2 +- src/coreclr/jit/rationalize.cpp | 13 +- src/coreclr/jit/ssabuilder.cpp | 2 +- src/coreclr/jit/targetarm64.h | 6 +- src/coreclr/jit/typeinfo.cpp | 63 +- src/coreclr/jit/valuenum.cpp | 690 +- src/coreclr/jit/valuenum.h | 8 + src/coreclr/md/enc/metamodelrw.cpp | 5 +- .../Microsoft.NETCore.Native.Publish.targets | 4 +- .../Microsoft.NETCore.Native.targets | 48 +- src/coreclr/nativeaot/Runtime/DebugHeader.cpp | 7 +- src/coreclr/nativeaot/Runtime/MethodTable.cpp | 4 - src/coreclr/nativeaot/Runtime/arm64/PInvoke.S | 2 +- .../nativeaot/Runtime/arm64/PInvoke.asm | 2 +- src/coreclr/nativeaot/Runtime/eventtrace.cpp | 1436 +-- .../nativeaot/Runtime/eventtracebase.h | 7 - src/coreclr/nativeaot/Runtime/gcrhenv.cpp | 3 +- src/coreclr/nativeaot/Runtime/startup.cpp | 7 +- src/coreclr/nativeaot/Runtime/threadstore.cpp | 6 +- .../Runtime/Augments/RuntimeAugments.cs | 5 + .../src/System.Private.CoreLib.csproj | 7 +- .../src/System/Math.CoreRT.cs | 12 - .../src/System/ModuleHandle.cs | 2 +- .../System/Reflection/AssemblyName.CoreRT.cs | 34 - .../System/Reflection/AssemblyNameHelpers.cs | 47 +- .../System/Reflection/AssemblyNameLexer.cs | 136 - .../System/Reflection/AssemblyNameParser.cs | 230 - .../Reflection/AssemblyRuntimeNameHelpers.cs | 52 + .../System/Reflection/RuntimeAssemblyName.cs | 27 +- .../src/System/Runtime/RuntimeImports.cs | 12 - .../Core/Execution/ExecutionDomain.cs | 2 +- .../BindingFlagSupport/ConstructorPolicies.cs | 2 +- .../General/TypeUnifier.NativeFormat.cs | 2 + .../Runtime/TypeInfos/RuntimeNamedTypeInfo.cs | 2 + .../Runtime/TypeParsing/TypeLexer.cs | 4 +- src/coreclr/pal/inc/pal.h | 30 +- src/coreclr/pal/inc/palprivate.h | 2 - src/coreclr/pal/inc/rt/sal.h | 4 + src/coreclr/pal/inc/unixasmmacros.inc | 2 + src/coreclr/pal/inc/unixasmmacrosarm.inc | 4 + src/coreclr/pal/src/CMakeLists.txt | 7 +- .../src/arch/arm/callsignalhandlerwrapper.S | 2 + src/coreclr/pal/src/arch/arm/context2.S | 2 + src/coreclr/pal/src/arch/arm/debugbreak.S | 2 + .../pal/src/arch/arm/exceptionhelper.S | 2 + src/coreclr/pal/src/cruntime/path.cpp | 113 - src/coreclr/pal/src/cruntime/printfcpp.cpp | 2 +- src/coreclr/pal/src/cruntime/wchar.cpp | 49 - src/coreclr/pal/src/cruntime/wchartls.cpp | 125 - .../pal/src/exception/machexception.cpp | 18 +- src/coreclr/pal/src/exception/seh-unwind.cpp | 18 +- src/coreclr/pal/src/exception/signal.cpp | 14 +- src/coreclr/pal/src/include/pal/modulename.h | 35 - src/coreclr/pal/src/include/pal/palinternal.h | 2 - src/coreclr/pal/src/include/pal/seh.hpp | 5 + src/coreclr/pal/src/init/pal.cpp | 2 +- src/coreclr/pal/src/libunwind/CMakeLists.txt | 11 +- .../pal/src/libunwind/src/CMakeLists.txt | 10 + .../libunwind/src/oop/_OOP_find_proc_info.c | 2 + src/coreclr/pal/src/loader/module.cpp | 12 +- src/coreclr/pal/src/loader/modulename.cpp | 68 - src/coreclr/pal/src/memory/local.cpp | 93 - src/coreclr/pal/src/misc/fmtmessage.cpp | 14 +- src/coreclr/pal/tests/palsuite/CMakeLists.txt | 4 - .../palsuite/c_runtime/wcstok/test1/test1.cpp | 113 - .../pal/tests/palsuite/compilableTests.txt | 4 - .../LocalAlloc/test1/LocalAlloc.cpp | 48 - .../LocalFree/test1/LocalFree.cpp | 48 - .../LocalFree/test2/LocalFree.cpp | 38 - .../LoadLibraryA/test6/loadlibrarya.cpp | 46 +- .../LoadLibraryA/test8/loadlibrarya.cpp | 57 +- .../FormatMessageW/test6/test.cpp | 20 +- .../pal/tests/palsuite/paltestlist.txt | 4 - src/coreclr/runtime-prereqs.proj | 2 +- src/coreclr/runtime.proj | 1 + src/coreclr/scripts/jitrollingbuild.py | 41 +- src/coreclr/scripts/jitutil.py | 25 +- src/coreclr/scripts/superpmi-asmdiffs.proj | 3 +- src/coreclr/scripts/superpmi-collect.proj | 12 +- src/coreclr/scripts/superpmi-replay.proj | 3 +- src/coreclr/scripts/superpmi.md | 2 +- src/coreclr/scripts/superpmi.py | 21 +- src/coreclr/tools/CMakeLists.txt | 3 + .../Common/Compiler/CompilationBuilder.cs | 7 + .../Compiler/CompilerTypeSystemContext.cs | 11 +- src/coreclr/tools/Common/Compiler/Logger.cs | 82 +- .../Compiler/Logging/MessageContainer.cs | 66 +- .../ReferenceSource/CompilerGeneratedState.cs | 15 +- ...mentationSignatureGenerator.PartVisitor.cs | 6 +- .../DocumentationSignatureParser.cs | 3 - .../ReferenceSource/MessageContainer.cs | 78 +- .../Logging/ReferenceSource/MessageOrigin.cs | 44 +- .../Logging/ReferenceSource/README.md | 2 +- .../NativeFormat/Generator/ReaderGen.cs | 1 + .../NativeFormat/NativeFormatReaderGen.cs | 1 + .../NativeFormat/NativeMetadataReader.cs | 7 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 18 +- .../JitInterface/ThunkGenerator/gen.bat | 2 +- .../Common/JitInterface/ThunkGenerator/gen.sh | 2 +- .../Common/TypeSystem/Common/CastingHelper.cs | 28 +- .../TypeSystem/Common/DefType.FieldLayout.cs | 24 + .../TypeSystem/Common/FieldLayoutAlgorithm.cs | 1 + .../Common/TypeSystem/Common/LayoutInt.cs | 2 + .../Common/MetadataFieldLayoutAlgorithm.cs | 54 +- .../Common/TypeSystem/Ecma/EcmaAssembly.cs | 2 +- .../TypeSystem/Ecma/EcmaSignatureParser.cs | 3 +- .../SymbolReader/PortablePdbSymbolReader.cs | 11 +- .../CalliMarshallingMethodThunk.Mangling.cs | 2 +- .../CalliMarshallingMethodThunk.Sorting.cs | 5 + .../IL/Stubs/CalliMarshallingMethodThunk.cs | 6 +- .../Stubs/DelegateMarshallingMethodThunk.cs | 8 + .../TypeSystem/IL/Stubs/PInvokeILEmitter.cs | 87 +- .../Interop/IL/MarshalHelpers.Aot.cs | 2 +- .../TypeSystem/Interop/IL/MarshalHelpers.cs | 45 +- .../TypeSystem/Interop/IL/Marshaller.Aot.cs | 15 + .../TypeSystem/Interop/IL/Marshaller.cs | 44 +- .../TypeSystem/Interop/IL/MarshallerKind.cs | 1 + .../TypeSystem/Interop/InteropStateManager.cs | 30 +- .../Common/TypeSystem/Interop/InteropTypes.cs | 5 + .../tools/ILVerification/ILImporter.Verify.cs | 2 +- .../{ToolBox => tools}/SOS/CMakeLists.txt | 0 .../{ToolBox => tools}/SOS/DIALib/DIALib.il | 0 .../SOS/DIALib/DIALib.ilproj | 0 .../SOS/DacTableGen/DacTableGen.csproj | 0 .../SOS/DacTableGen/MapSymbolProvider.cs | 0 .../SOS/DacTableGen/cvconst.cs | 0 .../SOS/DacTableGen/diautil.cs | 0 .../SOS/DacTableGen/main.cs | 0 .../SOS/Directory.Build.props | 0 .../{ToolBox => tools}/SOS/SOS_README.md | 0 .../Compiler/Compilation.cs | 3 +- .../Compiler/CompilationBuilder.Aot.cs | 7 + .../Compiler/Dataflow/FlowAnnotations.cs | 68 +- .../Dataflow/ReflectionMethodBodyScanner.cs | 49 +- .../Dataflow/ReflectionPatternContext.cs | 2 + .../GenericCompositionNode.cs | 1 + .../DependencyAnalysis/ObjectWriter.cs | 9 + .../Compiler/FeatureSettings.cs | 52 + .../Compiler/FeatureSwitchManager.cs | 2 +- .../Compiler/LazyGenerics/ModuleCycleInfo.cs | 11 +- .../ManifestResourceBlockingPolicy.cs | 2 +- .../Compiler/ProcessLinkerXmlBase.cs | 661 +- .../Compiler/ProcessXmlBase.cs | 404 + .../ReferenceSource/BodySubstitutionParser.cs | 174 + .../ReferenceSource/DescriptorMarker.cs | 292 + .../ReferenceSource/FeatureSettings.cs | 50 + .../ReferenceSource/LinkAttributesParser.cs | 578 ++ .../ReferenceSource/ProcessLinkerXmlBase.cs | 662 ++ .../Compiler/ReferenceSource/README.md | 1 + .../Compiler/UsageBasedInteropStubManager.cs | 21 +- .../Compiler/UsageBasedMetadataManager.cs | 11 +- .../IL/Stubs/PInvokeILProvider.cs | 4 +- .../ILCompiler.Compiler.csproj | 2 + .../ILCompiler.Diagnostics.csproj | 1 + .../ILCompilerComWrappers.cs | 32 + .../ILCompiler.Diagnostics/ISymNGenWriter.cs | 75 +- .../aot/ILCompiler.Diagnostics/PdbWriter.cs | 37 +- .../SymNgenWriterWrapper.cs | 149 + .../ReadyToRun/CopiedFieldRvaNode.cs | 9 +- .../ReadyToRunCodegenCompilationBuilder.cs | 7 - .../Compiler/ReadyToRunHashCode.cs | 4 +- .../IL/Stubs/PInvokeILEmitter.cs | 7 + .../ILCompiler.ReadyToRun.csproj | 1 + .../Interop/IL/Marshaller.ReadyToRun.cs | 55 +- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 4 +- .../Compiler/RyuJitCompilation.cs | 16 +- .../Compiler/RyuJitCompilationBuilder.cs | 6 + .../JitInterface/CorInfoImpl.RyuJit.cs | 14 +- .../CastingTests.cs | 15 + .../CoreTestAssembly/Casting.cs | 4 + .../tools/aot/ILCompiler/ILCompiler.csproj | 8 +- src/coreclr/tools/aot/ILCompiler/Program.cs | 10 +- .../tools/aot/ILCompiler/repro/repro.csproj | 2 +- .../tools/aot/ILLink.Shared/DiagnosticId.cs | 165 +- .../aot/ILLink.Shared/DiagnosticString.cs | 10 +- .../ILLink.Shared/ILLink.LinkAttributes.xsd | 124 + .../aot/ILLink.Shared/ILLink.Shared.projitems | 8 +- .../aot/ILLink.Shared/MessageSubCategory.cs | 13 + src/coreclr/tools/aot/ILLink.Shared/README.md | 1 + .../aot/ILLink.Shared/SharedStrings.resx | 1019 +- src/coreclr/tools/aot/crossgen2/Program.cs | 2 +- .../dotnet-pgo/TraceTypeSystemContext.cs | 11 +- .../{ToolBox => tools}/superpmi/.clang-format | 0 .../superpmi/CMakeLists.txt | 0 .../superpmi/mcs/CMakeLists.txt | 2 +- .../superpmi/mcs/commandline.cpp | 0 .../superpmi/mcs/commandline.h | 0 .../{ToolBox => tools}/superpmi/mcs/mcs.cpp | 0 .../{ToolBox => tools}/superpmi/mcs/mcs.h | 0 .../superpmi/mcs/removedup.cpp | 0 .../superpmi/mcs/removedup.h | 0 .../superpmi/mcs/verbasmdump.cpp | 0 .../superpmi/mcs/verbasmdump.h | 0 .../superpmi/mcs/verbconcat.cpp | 0 .../superpmi/mcs/verbconcat.h | 0 .../superpmi/mcs/verbdump.cpp | 0 .../superpmi/mcs/verbdump.h | 0 .../superpmi/mcs/verbdumpmap.cpp | 0 .../superpmi/mcs/verbdumpmap.h | 0 .../superpmi/mcs/verbdumptoc.cpp | 0 .../superpmi/mcs/verbdumptoc.h | 0 .../superpmi/mcs/verbfracture.cpp | 0 .../superpmi/mcs/verbfracture.h | 0 .../superpmi/mcs/verbildump.cpp | 0 .../superpmi/mcs/verbildump.h | 0 .../superpmi/mcs/verbinteg.cpp | 0 .../superpmi/mcs/verbinteg.h | 0 .../superpmi/mcs/verbjitflags.cpp | 0 .../superpmi/mcs/verbjitflags.h | 0 .../superpmi/mcs/verbmerge.cpp | 0 .../superpmi/mcs/verbmerge.h | 0 .../superpmi/mcs/verbprintjiteeversion.cpp | 0 .../superpmi/mcs/verbprintjiteeversion.h | 0 .../superpmi/mcs/verbremovedup.cpp | 0 .../superpmi/mcs/verbremovedup.h | 0 .../superpmi/mcs/verbstat.cpp | 0 .../superpmi/mcs/verbstat.h | 0 .../superpmi/mcs/verbstrip.cpp | 0 .../superpmi/mcs/verbstrip.h | 0 .../superpmi/mcs/verbtoc.cpp | 0 .../{ToolBox => tools}/superpmi/mcs/verbtoc.h | 0 .../{ToolBox => tools}/superpmi/readme.md | 2 +- .../superpmi/superpmi-shared/agnostic.h | 0 .../superpmi/superpmi-shared/asmdumper.cpp | 0 .../superpmi/superpmi-shared/asmdumper.h | 0 .../superpmi/superpmi-shared/callutils.cpp | 0 .../superpmi/superpmi-shared/callutils.h | 0 .../superpmi-shared/compileresult.cpp | 0 .../superpmi/superpmi-shared/compileresult.h | 0 .../superpmi/superpmi-shared/crlwmlist.h | 0 .../superpmi-shared/errorhandling.cpp | 0 .../superpmi/superpmi-shared/errorhandling.h | 0 .../superpmi/superpmi-shared/hash.cpp | 0 .../superpmi/superpmi-shared/hash.h | 0 .../superpmi-shared/icorjitcompilerimpl.h | 0 .../superpmi-shared/icorjithostimpl.h | 0 .../superpmi-shared/icorjitinfoimpl.h | 0 .../superpmi/superpmi-shared/lightweightmap.h | 0 .../superpmi/superpmi-shared/logging.cpp | 0 .../superpmi/superpmi-shared/logging.h | 0 .../superpmi/superpmi-shared/lwmlist.h | 0 .../superpmi/superpmi-shared/mclist.cpp | 0 .../superpmi/superpmi-shared/mclist.h | 0 .../superpmi-shared/methodcontext.cpp | 0 .../superpmi/superpmi-shared/methodcontext.h | 0 .../superpmi-shared/methodcontextiterator.cpp | 0 .../superpmi-shared/methodcontextiterator.h | 0 .../superpmi-shared/methodcontextreader.cpp | 0 .../superpmi-shared/methodcontextreader.h | 0 .../superpmi/superpmi-shared/runtimedetails.h | 0 .../superpmi/superpmi-shared/simpletimer.cpp | 0 .../superpmi/superpmi-shared/simpletimer.h | 0 .../superpmi-shared/spmidumphelper.cpp | 0 .../superpmi/superpmi-shared/spmidumphelper.h | 0 .../superpmi-shared/spmirecordhelper.h | 0 .../superpmi/superpmi-shared/spmiutil.cpp | 0 .../superpmi/superpmi-shared/spmiutil.h | 0 .../superpmi/superpmi-shared/standardpch.h | 0 .../superpmi/superpmi-shared/tocfile.cpp | 0 .../superpmi/superpmi-shared/tocfile.h | 0 .../superpmi/superpmi-shared/typeutils.cpp | 0 .../superpmi/superpmi-shared/typeutils.h | 0 .../superpmi-shim-collector/CMakeLists.txt | 2 +- .../icorjitcompiler.cpp | 0 .../superpmi-shim-collector/icorjitcompiler.h | 0 .../superpmi-shim-collector/icorjitinfo.cpp | 0 .../superpmi-shim-collector/icorjitinfo.h | 0 .../superpmi-shim-collector/jithost.cpp | 0 .../superpmi-shim-collector/jithost.h | 0 .../superpmi-shim-collector.cpp | 0 .../superpmi-shim-collector.def | 0 .../superpmi-shim-collector.h | 0 .../superpmi-shim-counter/CMakeLists.txt | 2 +- .../superpmi-shim-counter/icorjitcompiler.cpp | 0 .../superpmi-shim-counter/icorjitcompiler.h | 0 .../superpmi-shim-counter/icorjitinfo.cpp | 0 .../superpmi-shim-counter/icorjitinfo.h | 0 .../superpmi-shim-counter/jithost.cpp | 0 .../superpmi/superpmi-shim-counter/jithost.h | 0 .../methodcallsummarizer.cpp | 0 .../methodcallsummarizer.h | 0 .../superpmi-shim-counter.cpp | 0 .../superpmi-shim-counter.def | 0 .../superpmi-shim-counter.h | 0 .../superpmi-shim-simple/CMakeLists.txt | 2 +- .../superpmi-shim-simple/icorjitcompiler.cpp | 0 .../superpmi-shim-simple/icorjitcompiler.h | 0 .../superpmi-shim-simple/icorjitinfo.cpp | 0 .../superpmi-shim-simple/icorjitinfo.h | 0 .../superpmi/superpmi-shim-simple/jithost.cpp | 0 .../superpmi/superpmi-shim-simple/jithost.h | 0 .../superpmi-shim-simple.cpp | 0 .../superpmi-shim-simple.def | 0 .../superpmi-shim-simple.h | 0 .../superpmi/superpmi/CMakeLists.txt | 2 +- .../superpmi/superpmi/commandline.cpp | 0 .../superpmi/superpmi/commandline.h | 0 .../superpmi/superpmi/cycletimer.cpp | 0 .../superpmi/superpmi/cycletimer.h | 0 .../superpmi/superpmi/icorjitinfo.cpp | 0 .../superpmi/superpmi/icorjitinfo.h | 0 .../superpmi/superpmi/jitdebugger.cpp | 0 .../superpmi/superpmi/jitdebugger.h | 0 .../superpmi/superpmi/jithost.cpp | 0 .../superpmi/superpmi/jithost.h | 0 .../superpmi/superpmi/jitinstance.cpp | 0 .../superpmi/superpmi/jitinstance.h | 0 .../superpmi/superpmi/methodstatsemitter.cpp | 0 .../superpmi/superpmi/methodstatsemitter.h | 0 .../superpmi/superpmi/metricssummary.cpp | 0 .../superpmi/superpmi/metricssummary.h | 0 .../superpmi/superpmi/neardiffer.cpp | 0 .../superpmi/superpmi/neardiffer.h | 0 .../superpmi/superpmi/parallelsuperpmi.cpp | 0 .../superpmi/superpmi/superpmi.cpp | 0 .../superpmi/superpmi/superpmi.h | 0 src/coreclr/utilcode/securitywrapper.cpp | 123 - src/coreclr/utilcode/sstring.cpp | 8 - src/coreclr/utilcode/stresslog.cpp | 15 +- src/coreclr/utilcode/util.cpp | 62 +- src/coreclr/utilcode/utilmessagebox.cpp | 78 +- src/coreclr/utilcode/winfix.cpp | 33 - src/coreclr/vm/.vscode/c_cpp_properties.json | 1 - src/coreclr/vm/CMakeLists.txt | 7 +- src/coreclr/vm/amd64/cgencpu.h | 2 - src/coreclr/vm/appdomain.cpp | 139 +- src/coreclr/vm/appdomain.hpp | 45 +- src/coreclr/vm/arm64/asmhelpers.S | 179 - src/coreclr/vm/assembly.cpp | 122 +- src/coreclr/vm/assembly.hpp | 144 +- src/coreclr/vm/assemblyname.cpp | 140 - src/coreclr/vm/assemblyname.hpp | 27 - src/coreclr/vm/assemblynative.cpp | 40 +- src/coreclr/vm/assemblyspec.cpp | 170 +- src/coreclr/vm/assemblyspec.hpp | 6 +- src/coreclr/vm/ceeload.cpp | 136 +- src/coreclr/vm/ceeload.h | 57 +- src/coreclr/vm/ceeload.inl | 10 +- src/coreclr/vm/class.h | 40 +- src/coreclr/vm/classhash.cpp | 2 +- src/coreclr/vm/classlayoutinfo.cpp | 100 +- src/coreclr/vm/classnames.h | 2 + src/coreclr/vm/clsload.cpp | 94 +- src/coreclr/vm/codeversion.cpp | 5 +- src/coreclr/vm/comdynamic.cpp | 8 +- src/coreclr/vm/commodule.cpp | 22 +- src/coreclr/vm/common.h | 3 - src/coreclr/vm/coreassemblyspec.cpp | 2 +- src/coreclr/vm/corelib.cpp | 1 - src/coreclr/vm/dacenumerablehash.inl | 4 +- src/coreclr/vm/dbginterface.h | 4 +- src/coreclr/vm/debugdebugger.cpp | 4 +- src/coreclr/vm/dllimport.cpp | 75 +- src/coreclr/vm/dllimport.h | 8 + src/coreclr/vm/dllimportcallback.cpp | 77 +- src/coreclr/vm/dllimportcallback.h | 16 +- .../vm/{domainfile.cpp => domainassembly.cpp} | 328 +- .../vm/{domainfile.h => domainassembly.h} | 415 +- src/coreclr/vm/domainfile.inl | 72 - src/coreclr/vm/dwbucketmanager.hpp | 4 +- src/coreclr/vm/dwreport.cpp | 54 +- src/coreclr/vm/dynamicmethod.cpp | 2 +- src/coreclr/vm/ecalllist.h | 9 - src/coreclr/vm/eventtrace.cpp | 126 +- src/coreclr/vm/excep.cpp | 8 +- src/coreclr/vm/field.cpp | 16 +- src/coreclr/vm/field.h | 2 + src/coreclr/vm/frames.cpp | 40 +- src/coreclr/vm/frames.h | 90 +- src/coreclr/vm/i386/asmhelpers.asm | 38 +- src/coreclr/vm/i386/cgenx86.cpp | 52 - src/coreclr/vm/i386/excepx86.cpp | 65 +- src/coreclr/vm/i386/stublinkerx86.cpp | 150 +- src/coreclr/vm/i386/stublinkerx86.h | 35 +- src/coreclr/vm/interoputil.cpp | 8 +- src/coreclr/vm/jithelpers.cpp | 26 +- src/coreclr/vm/jitinterface.cpp | 72 +- src/coreclr/vm/loaderallocator.cpp | 8 +- src/coreclr/vm/memberload.cpp | 2 +- src/coreclr/vm/methoditer.cpp | 16 +- src/coreclr/vm/methoditer.h | 13 +- src/coreclr/vm/methodtable.h | 2 + src/coreclr/vm/methodtable.inl | 7 + src/coreclr/vm/methodtablebuilder.cpp | 35 +- src/coreclr/vm/mlinfo.cpp | 137 +- src/coreclr/vm/multicorejit.cpp | 25 +- src/coreclr/vm/nativeimage.cpp | 2 +- src/coreclr/vm/nativelibrary.cpp | 12 +- src/coreclr/vm/object.inl | 34 - src/coreclr/vm/peassembly.cpp | 4 +- src/coreclr/vm/peassembly.h | 11 +- src/coreclr/vm/peimage.cpp | 28 - src/coreclr/vm/peimage.h | 2 - src/coreclr/vm/perfmap.cpp | 2 +- src/coreclr/vm/prestub.cpp | 14 +- src/coreclr/vm/profilingenumerators.cpp | 29 +- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 4 +- src/coreclr/vm/qcallentrypoints.cpp | 1 - src/coreclr/vm/reflectioninvocation.cpp | 10 +- src/coreclr/vm/rejit.cpp | 42 +- src/coreclr/vm/runtimehandles.cpp | 20 +- src/coreclr/vm/siginfo.cpp | 63 +- src/coreclr/vm/stubgen.cpp | 2 +- src/coreclr/vm/threads.cpp | 12 +- src/coreclr/vm/threads.h | 2 +- src/coreclr/vm/typeparse.cpp | 4 +- src/coreclr/vm/util.cpp | 16 - src/coreclr/vm/win32threadpool.cpp | 6 +- src/coreclr/vm/zapsig.cpp | 4 +- .../AppHost/HostWriter.cs | 2 +- .../Directory.Build.props | 10 + .../ILCompilerRIDs.props | 13 + .../Microsoft.DotNet.ILCompiler.pkgproj | 26 + .../pkg/projects/nativeaot-packages.proj | 14 + .../pkg/projects/netcoreappRIDs.props | 3 + .../AsymmetricAlgorithmHelpers.Der.cs | 4 - .../AsymmetricAlgorithmHelpers.Hash.cs | 23 +- .../Interop.Hmac.cs | 10 +- .../Unix/System.Native/Interop.IPAddress.cs | 16 +- .../Unix/System.Native/Interop.LChflags.cs | 6 + .../Interop.EvpPkey.cs | 22 +- .../Interop.OpenSsl.cs | 9 +- .../Interop.Ssl.cs | 45 +- .../Advapi32/Interop.CryptCreateHash.cs | 2 +- .../Windows/Advapi32/Interop.CryptDecrypt.cs | 2 +- .../Advapi32/Interop.CryptDeriveKey.cs | 2 +- .../Windows/Advapi32/Interop.CryptEncrypt.cs | 2 +- .../Advapi32/Interop.CryptExportKey.cs | 4 +- .../Windows/Advapi32/Interop.CryptGenKey.cs | 2 +- .../Advapi32/Interop.CryptGetKeyParam.cs | 2 +- .../Advapi32/Interop.CryptGetUserKey.cs | 2 +- .../Advapi32/Interop.CryptImportKey.cs | 4 +- .../Advapi32/Interop.CryptSetKeyParam.cs | 4 +- .../Windows/Advapi32/Interop.CryptSignHash.cs | 2 +- .../Interop/Windows/Advapi32/SafeKeyHandle.cs | 10 +- .../Windows/BCrypt/Interop.BCryptImportKey.cs | 2 +- .../Interop/Windows/NCrypt/Interop.Keys.cs | 3 + .../Windows/User32/Interop.Constants.cs | 1 + ...p.PeekMessage.cs => Interop.GetMessage.cs} | 2 +- .../Windows/User32/Interop.PostQuitMessage.cs | 14 + .../Win32/SafeHandles/SafeX509ChainHandle.cs | 2 +- .../Common/src/System/Net/CookieComparer.cs | 22 +- .../Http3/QPack/H3StaticTable.Http3.cs | 2 +- .../NetworkInformation/UnixCommandLinePing.cs | 6 +- .../Net/SocketProtocolSupportPal.Unix.cs | 4 +- .../Cryptography/Asn1Reader/AsnValueReader.cs | 12 + .../Cryptography/DSACng.ImportExport.cs | 701 +- .../Cryptography/DSACng.SignVerify.cs | 271 +- .../System/Security/Cryptography/DSACng.cs | 122 +- .../Security/Cryptography/DSAOpenSsl.cs | 623 +- .../Cryptography/DSASecurityTransforms.cs | 14 - .../ECDiffieHellmanAndroid.Derive.cs | 12 +- .../ECDiffieHellmanCng.ImportExport.cs | 395 +- .../Cryptography/ECDiffieHellmanCng.cs | 213 +- .../ECDiffieHellmanOpenSsl.Derive.cs | 313 +- .../Cryptography/ECDiffieHellmanOpenSsl.cs | 207 +- .../ECDiffieHellmanOpenSslPublicKey.cs | 161 +- .../ECDiffieHellmanSecurityTransforms.cs | 17 +- .../Cryptography/ECDsaCng.HashData.cs | 9 - .../Cryptography/ECDsaCng.ImportExport.cs | 437 +- .../Cryptography/ECDsaCng.SignVerify.cs | 28 +- .../System/Security/Cryptography/ECDsaCng.cs | 133 +- .../Security/Cryptography/ECDsaOpenSsl.cs | 567 +- .../Cryptography/ECDsaSecurityTransforms.cs | 359 +- .../Cryptography/EccSecurityTransforms.cs | 37 +- .../Security/Cryptography/RSAAndroid.cs | 32 +- .../Cryptography/RSACng.EncryptDecrypt.cs | 7 - .../Cryptography/RSACng.ImportExport.cs | 7 - .../Cryptography/RSACng.SignVerify.cs | 38 +- .../System/Security/Cryptography/RSACng.cs | 10 +- .../Security/Cryptography/RSAOpenSsl.cs | 59 +- .../Cryptography/RSASecurityTransforms.cs | 43 +- .../Common/tests/Resources/Strings.resx | 9 - .../System/IO/StreamConformanceTests.cs | 25 - .../CompressionStreamUnitTestBase.cs | 2 +- .../System/Net/Http/GenericLoopbackServer.cs | 14 + .../Net/Http/Http2LoopbackConnection.cs | 5 + .../Net/Http/Http3LoopbackConnection.cs | 6 + .../HttpClientHandlerTest.Cancellation.cs | 15 +- .../tests/System/Net/Http/LoopbackServer.cs | 5 + .../tests/System/Net/ManualChunkingStream.cs | 103 + .../Net/Prerequisites/LocalEchoServer.props | 4 - .../Handlers/RemoteLoopHandler.cs | 9 +- .../DSA/DsaFamilySignatureFormatTests.cs | 12 +- .../ECDiffieHellman/ECDhKeyFileTests.cs | 1 + .../ECDsa/ECDsaKeyFileTests.cs | 1 + .../ECDsa/ECDsaTests.cs | 15 +- .../ECDsa/ECDsaTests.netcoreapp.cs | 4 +- .../RSA/SignVerify.cs | 14 +- .../TestUtilities/System/AssertExtensions.cs | 2 +- .../System/IO/FileCleanupTestBase.cs | 33 + .../System/PlatformDetection.Unix.cs | 5 + .../TestUtilities/System/PlatformDetection.cs | 55 +- src/libraries/Directory.Build.props | 2 - .../tests/RuntimeBinderExceptionTests.cs | 2 +- .../src/Resources/Strings.resx | 3 - .../src/ConfigurationBinder.cs | 34 +- .../ConfigurationCollectionBindingTests.cs | 17 + ...Microsoft.Extensions.Configuration.Json.cs | 4 +- ...osoft.Extensions.Configuration.Json.csproj | 1 + .../src/JsonConfigurationExtensions.cs | 4 +- .../src/JsonConfigurationFileParser.cs | 6 +- ...osoft.Extensions.Configuration.Json.csproj | 1 + ...xtensions.Configuration.UserSecrets.csproj | 1 + ...xtensions.Configuration.UserSecrets.csproj | 1 + .../src/PathHelper.cs | 4 +- .../src/UserSecretsConfigurationExtensions.cs | 6 +- .../src/Resources/Strings.resx | 4 - ...icrosoft.Extensions.DependencyInjection.cs | 2 +- ...soft.Extensions.DependencyInjection.csproj | 1 + .../src/CallSiteJsonFormatter.cs | 16 +- .../src/DependencyInjectionEventSource.cs | 7 +- ...soft.Extensions.DependencyInjection.csproj | 4 +- .../src/ServiceLookup/CallSiteChain.cs | 8 +- .../src/ServiceLookup/CallSiteFactory.cs | 61 +- .../ServiceLookup/CallSiteRuntimeResolver.cs | 30 +- .../src/ServiceLookup/CallSiteValidator.cs | 32 +- .../CompiledServiceProviderEngine.cs | 2 +- .../src/ServiceLookup/ConstantCallSite.cs | 4 +- .../src/ServiceLookup/ConstructorCallSite.cs | 2 +- .../DynamicServiceProviderEngine.cs | 2 +- .../Expressions/ExpressionResolverBuilder.cs | 26 +- .../src/ServiceLookup/FactoryCallSite.cs | 2 +- .../ILEmit/ILEmitResolverBuilder.cs | 56 +- .../ILEmit/ILEmitResolverBuilderContext.cs | 7 +- .../ILEmit/ILEmitServiceProviderEngine.cs | 2 +- .../src/ServiceLookup/ResultCache.cs | 2 +- .../RuntimeServiceProviderEngine.cs | 2 +- .../src/ServiceLookup/ServiceCacheKey.cs | 17 +- .../src/ServiceLookup/ServiceCallSite.cs | 4 +- .../src/ServiceLookup/ServiceLookupHelpers.cs | 16 +- .../ServiceLookup/ServiceProviderEngine.cs | 2 +- .../ServiceProviderEngineScope.cs | 18 +- .../src/ServiceLookup/StackGuard.cs | 2 +- .../src/ServiceLookup/ThrowHelper.cs | 2 + .../src/ServiceProvider.cs | 26 +- .../UnitTests/ConsoleLifetimeExitTests.cs | 17 +- ...rosoft.Extensions.Logging.Abstractions.sln | 19 +- .../gen/LoggerMessageGenerator.Emitter.cs | 14 +- .../gen/LoggerMessageGenerator.Parser.cs | 6 +- ...crosoft.Extensions.Logging.Abstractions.cs | 2 +- .../src/EventId.cs | 3 +- ...oft.Extensions.Logging.Abstractions.csproj | 1 + .../Baselines/.editorconfig | 4 + .../TestWithDefaultValues.generated.txt | 4 +- .../TestWithDynamicLogLevel.generated.txt | 4 +- .../TestWithMoreThan6Params.generated.txt | 6 +- .../LoggerMessageGeneratedCodeTests.cs | 22 +- .../LoggerMessageGeneratorEmitterTests.cs | 5 +- .../LoggerMessageGeneratorParserTests.cs | 14 +- ...ExceptionTestExtensions.WithDiagnostics.cs | 15 + .../LevelTestExtensions.WithDiagnostics.cs | 18 + .../Microsoft.Extensions.Logging.Console.cs | 1 + ...icrosoft.Extensions.Logging.Console.csproj | 4 + .../src/ConsoleFormatterOptions.cs | 2 + ...icrosoft.Extensions.Logging.Console.csproj | 8 +- .../src/runtime.compatibility.json | 36 +- .../src/runtime.json | 24 +- .../src/runtimeGroups.props | 9 +- .../VisualBasic/FileIO/TextFieldParser.vb | 8 +- .../tests/FileSystemTests.cs | 3 +- .../src/Microsoft/Win32/Registry.cs | 2 +- .../src/Microsoft/Win32/RegistryKey.cs | 6 +- .../AccessControl/RegistrySecurity.Windows.cs | 2 +- .../src/Microsoft.Win32.SystemEvents.csproj | 6 +- .../src/Microsoft/Win32/SystemEvents.cs | 56 +- .../src/Resources/Strings.resx | 6 - .../Microsoft.Win32.SystemEvents.Tests.csproj | 1 + .../tests/ShutdownTest.cs | 33 + .../src/GenerateNupkgProps.targets | 6 +- .../src/GenerateThisAssemblyCs.targets | 4 +- .../ImmutableDictionary_2.HashBucket.cs | 2 + .../ImmutableHashSet_1.HashBucket.cs | 2 + .../tests/ReadOnlyCollectionBaseTests.cs | 2 +- .../ref/System.Collections.Specialized.cs | 5 +- .../Collections/Specialized/BitVector32.cs | 11 +- .../tests/BitVector32Tests.cs | 15 + .../ref/System.ComponentModel.Annotations.cs | 2 +- .../RegularExpressionAttribute.cs | 3 +- .../Registration/RegistrationBuilderTests.cs | 15 +- .../ref/System.ComponentModel.Composition.cs | 3 +- .../src/Resources/Strings.resx | 21 - .../ReflectionModel/LazyMemberInfo.cs | 25 +- .../Hosting/AssemblyCatalogTests.cs | 19 +- .../System.ComponentModel.TypeConverter.cs | 3 +- .../src/Resources/Strings.resx | 5 +- .../MemberRelationshipService.cs | 50 +- .../ComponentModel/InterlockedBitVector32.cs | 6 +- .../ComponentModel/MaskedTextProvider.cs | 5 +- .../src/System/Drawing/RectangleConverter.cs | 2 +- .../tests/ContainerTests.cs | 2 +- .../MemberRelationshipServiceTests.cs | 2 +- .../tests/Design/ServiceContainerTests.cs | 6 +- .../src/Resources/Strings.resx | 9 - .../src/Resources/Strings.resx | 5 +- .../src/System/IO/SyncTextReader.cs | 15 + .../tests/CancelKeyPress.Unix.cs | 5 +- .../ref/System.Data.Common.cs | 39 +- .../src/Resources/Strings.resx | 1 - .../src/System/Data/DataKey.cs | 4 +- .../src/System/Data/SQLTypes/SQLBinary.cs | 25 +- .../src/System/Data/SQLTypes/SQLBoolean.cs | 28 +- .../src/System/Data/SQLTypes/SQLByte.cs | 28 +- .../src/System/Data/SQLTypes/SQLDateTime.cs | 28 +- .../src/System/Data/SQLTypes/SQLDecimal.cs | 25 +- .../src/System/Data/SQLTypes/SQLDouble.cs | 28 +- .../src/System/Data/SQLTypes/SQLGuid.cs | 28 +- .../src/System/Data/SQLTypes/SQLInt16.cs | 28 +- .../src/System/Data/SQLTypes/SQLInt32.cs | 28 +- .../src/System/Data/SQLTypes/SQLInt64.cs | 28 +- .../src/System/Data/SQLTypes/SQLMoney.cs | 29 +- .../src/System/Data/SQLTypes/SQLSingle.cs | 28 +- .../src/System/Data/SQLTypes/SQLString.cs | 25 +- .../src/System/Data/Selection.cs | 14 +- .../Data/RestrictedTypeHandlingTests.cs | 3 +- .../System/Data/SqlTypes/SqlBinaryTest.cs | 3 + .../System/Data/SqlTypes/SqlBooleanTest.cs | 4 + .../tests/System/Data/SqlTypes/SqlByteTest.cs | 3 + .../System/Data/SqlTypes/SqlBytesTest.cs | 4 +- .../System/Data/SqlTypes/SqlCharsTest.cs | 4 +- .../System/Data/SqlTypes/SqlDateTimeTest.cs | 2 + .../System/Data/SqlTypes/SqlDecimalTest.cs | 2 + .../System/Data/SqlTypes/SqlDoubleTest.cs | 3 + .../tests/System/Data/SqlTypes/SqlGuidTest.cs | 3 + .../System/Data/SqlTypes/SqlInt16Test.cs | 3 + .../System/Data/SqlTypes/SqlInt32Test.cs | 164 +- .../System/Data/SqlTypes/SqlInt64Test.cs | 3 + .../System/Data/SqlTypes/SqlMoneyTest.cs | 2 + .../System/Data/SqlTypes/SqlSingleTest.cs | 3 + .../System/Data/SqlTypes/SqlStringTest.cs | 3 + .../src/Resources/Strings.resx | 6 - .../src/System.Data.Odbc.csproj | 1 - ...em.Diagnostics.DiagnosticSourceActivity.cs | 47 +- .../src/Resources/Strings.resx | 3 - ...System.Diagnostics.DiagnosticSource.csproj | 2 + .../src/System/Diagnostics/Metrics/Meter.cs | 54 + .../Metrics/ObservableUpDownCounter.cs | 61 + .../Diagnostics/Metrics/UpDownCounter.cs | 76 + .../tests/MetricsTests.cs | 435 +- .../src/Resources/Strings.resx | 6 - ...stem.Diagnostics.PerformanceCounter.csproj | 3 +- ...agnostics.PerformanceCounter.netcoreapp.cs | 12 + .../src/Resources/Strings.resx | 5 +- ...stem.Diagnostics.PerformanceCounter.csproj | 1 + .../src/System/Diagnostics/CounterSample.cs | 2 +- .../src/Resources/Strings.resx | 8 +- .../src/System/Diagnostics/ProcessManager.cs | 6 +- .../tests/ProcessTests.cs | 4 +- .../ref/System.Diagnostics.StackTrace.cs | 2 +- .../Diagnostics/SymbolStore/SymbolToken.cs | 2 +- .../src/Resources/Strings.resx | 8 +- .../Diagnostics/DelimitedListTraceListener.cs | 6 +- .../tests/CtorsDelimiterTests.cs | 4 +- .../src/Resources/Strings.resx | 8 +- .../src/System/Diagnostics/SwitchAttribute.cs | 5 +- .../src/System/Diagnostics/TraceSource.cs | 5 +- .../TestsManifestNegative.cs | 12 +- .../src/Resources/Strings.resx | 78 - ...DirectoryServices.AccountManagement.csproj | 3 + .../AD/ADStoreCtx_LoadStore.cs | 11 +- .../AccountManagement/Context.cs | 12 +- .../tests/AccountManagementTests.cs | 220 +- .../tests/ComputerPrincipalTest.cs | 83 - .../tests/ExtendedUserPrincipal.cs | 36 - .../tests/GroupPrincipalTest.cs | 68 - .../tests/PrincipalTest.cs | 143 - ...oryServices.AccountManagement.Tests.csproj | 8 +- .../tests/UserPrincipalTest.cs | 32 - .../src/Resources/Strings.resx | 69 - .../System.DirectoryServices.Protocols.csproj | 3 + .../src/Resources/Strings.resx | 9 - .../ref/System.Drawing.Common.netcoreapp.cs | 4 + .../src/Resources/Strings.resx | 41 +- .../src/System/Drawing/CharacterRange.cs | 30 +- .../src/System/Drawing/GdiplusNative.cs | 2 - .../Drawing/LocalAppContextSwitches.Unix.cs | 8 +- .../src/System/Drawing/Printing/TriState.cs | 78 +- .../src/System/Drawing/RectangleConverter.cs | 1 - .../tests/CharacterRangeTests.cs | 1 + .../tests/Drawing2D/MatrixTests.cs | 2 +- .../tests/FontFamilyTests.cs | 2 +- .../System.Drawing.Common/tests/FontTests.cs | 4 +- .../System.Drawing.Common/tests/ImageTests.cs | 28 +- .../tests/Printing/PrinterSettingsTests.cs | 24 +- .../tests/System.Drawing.Common.Tests.csproj | 2 +- .../tests/SystemPensTest.cs | 2 +- .../mono/System.Drawing/GraphicsTests.cs | 88 +- .../tests/mono/System.Imaging/MetafileTest.cs | 24 +- .../tests/runtimeconfig.template.json | 5 - .../src/System.Drawing.Primitives.csproj | 1 - .../Formats/Asn1/AsnWriter.GeneralizedTime.cs | 7 +- .../ref/System.Formats.Cbor.cs | 2 - .../ref/System.Formats.Cbor.csproj | 7 +- .../ref/System.Formats.Cbor.netcoreapp.cs | 17 + .../src/CompatibilitySuppressions.xml | 14 +- .../src/System.Formats.Cbor.csproj | 30 +- .../Formats/Cbor/CborHelpers.netcoreapp.cs | 63 + .../Formats/Cbor/CborHelpers.netstandard.cs | 255 + .../src/System/Formats/Cbor/HalfHelpers.cs | 50 - .../Formats/Cbor/HalfHelpers.netcoreapp.cs | 17 + .../Formats/Cbor/HalfHelpers.netstandard.cs | 203 + .../Formats/Cbor/Reader/CborReader.Simple.cs | 54 +- .../Reader/CborReader.Simple.netcoreapp.cs | 45 + .../Formats/Cbor/Reader/CborReader.String.cs | 12 +- .../Formats/Cbor/Reader/CborReader.Tag.cs | 4 +- .../Formats/Cbor/Writer/CborWriter.Simple.cs | 46 +- .../Writer/CborWriter.Simple.netcoreapp.cs | 36 + .../Writer/CborWriter.Simple.netstandard.cs | 36 + .../Formats/Cbor/Writer/CborWriter.String.cs | 4 +- .../Formats/Cbor/Writer/CborWriter.Tag.cs | 6 +- .../tests/CborTestHelpers.netcoreapp.cs | 10 + .../tests/CborTestHelpers.netstandard.cs | 11 + .../tests/CoseKeyHelpers.cs | 8 +- .../Reader/CborReaderTests.ByteString.cs | 2 +- .../tests/Reader/CborReaderTests.Map.cs | 2 +- .../tests/Reader/CborReaderTests.Simple.cs | 58 +- .../CborReaderTests.Simple.netcoreapp.cs | 69 + .../tests/Reader/CborReaderTests.Tag.cs | 2 +- .../Reader/CborReaderTests.TextString.cs | 27 +- .../tests/System.Formats.Cbor.Tests.csproj | 23 +- .../tests/Writer/CborWriterTests.Simple.cs | 20 - .../CborWriterTests.Simple.netcoreapp.cs | 31 + .../tests/Writer/CborWriterTests.Tag.cs | 2 +- .../Writer/CborWriterTests.TextString.cs | 2 +- .../NumberFormatInfo/NumberFormatInfoData.cs | 6 +- .../src/Resources/Strings.resx | 3 - ...pFileExtensions.ZipArchiveEntry.Extract.cs | 2 +- .../src/Resources/Strings.resx | 9 - .../DeflateManaged/DeflateManagedStream.cs | 12 +- .../DeflateManaged/InflaterManaged.cs | 2 - .../ref/System.IO.FileSystem.AccessControl.cs | 2 +- .../src/Resources/Strings.resx | 9 +- .../src/System/IO/FileSystemAclExtensions.cs | 115 +- .../tests/FileSystemAclExtensionsTests.cs | 422 +- .../tests/Base/FileGetSetAttributes.cs | 3 +- .../tests/Directory/CreateDirectory.cs | 5 +- .../tests/Directory/Exists.cs | 7 +- .../Directory/GetFileSystemEntries_str_str.cs | 7 +- .../tests/Directory/GetFiles.cs | 7 +- .../tests/Directory/SymbolicLinks.cs | 6 +- .../tests/DirectoryInfo/Exists.cs | 6 +- .../tests/DirectoryInfo/SymbolicLinks.cs | 6 +- .../System.IO.FileSystem/tests/File/Create.cs | 7 +- .../tests/File/EncryptDecrypt.cs | 2 - .../System.IO.FileSystem/tests/File/Exists.cs | 12 +- .../tests/File/ReadWriteAllBytes.cs | 2 +- .../tests/File/ReadWriteAllBytesAsync.cs | 2 +- .../tests/FileInfo/Exists.cs | 6 +- .../FileStreamConformanceTests.Windows.cs | 2 +- .../FileStream/FileStreamConformanceTests.cs | 2 +- .../tests/FileSystemTest.cs | 28 - .../tests/PortedCommon/IOInputs.cs | 2 +- .../tests/RandomAccess/NoBuffering.Windows.cs | 41 +- .../tests/RandomAccess/SetLength.cs | 65 + .../src/Resources/Strings.resx | 6 +- .../IO/IsolatedStorage/IsolatedStorage.cs | 2 +- .../IO/IsolatedStorage/IsolatedStorageFile.cs | 92 +- .../src/Resources/Strings.resx | 8 +- .../MemoryMappedFile.Unix.cs | 52 +- .../IO/MemoryMappedFiles/MemoryMappedFile.cs | 20 +- .../MemoryMappedViewAccessor.cs | 2 +- .../MemoryMappedViewStream.cs | 2 +- .../MemoryMappedFile.CreateFromFile.Tests.cs | 52 + .../tests/MemoryMappedFile.CreateNew.Tests.cs | 1 - .../MemoryMappedFile.CreateOrOpen.Tests.cs | 6 +- .../MemoryMappedFile.OpenExisting.Tests.cs | 2 +- .../tests/MemoryMappedFilesTestsBase.Unix.cs | 3 + .../MemoryMappedFilesTestsBase.Windows.cs | 7 +- .../tests/MemoryMappedViewAccessor.Tests.cs | 1 - .../tests/MemoryMappedViewStream.Tests.cs | 1 - .../MemoryMappedViewStreamConformanceTests.cs | 1 - .../src/Resources/Strings.resx | 4 +- .../src/System/IO/Packaging/PackUriHelper.cs | 2 + .../src/Resources/Strings.resx | 6 - .../System/IO/Pipes/NamedPipeClientStream.cs | 14 +- .../System/IO/Pipes/NamedPipeServerStream.cs | 9 +- .../NamedPipeTest.CreateClient.cs | 4 +- .../NamedPipeTest.CreateServer.cs | 12 +- .../src/Resources/Strings.resx | 21 - .../tests/UmsSafeBuffer.cs | 4 +- .../System.IO/tests/IndentedTextWriter.cs | 2 +- .../tests/Stream/Stream.NullTests.cs | 64 +- .../StreamReader.StringCtorTests.cs | 20 +- .../tests/StreamReader/StreamReaderTests.cs | 59 + .../StreamWriter.StringCtorTests.cs | 15 +- .../StringReader/StringReader.CtorTests.cs | 27 + .../tests/TextReader/TextReaderTests.cs | 21 + .../src/System/Dynamic/Utils/ContractUtils.cs | 2 +- .../Expressions/Interpreter/LocalVariables.cs | 23 +- .../ExceptionHandlingExpressions.cs | 2 +- .../Management/ManagementObjectTests.cs | 38 +- .../System.Memory/src/Resources/Strings.resx | 3 - .../tests/MemoryMarshal/AsReadOnlyRef.cs | 2 +- .../tests/MemoryMarshal/AsRef.cs | 2 +- .../tests/Span/IndexOfSequence.byte.cs | 101 + .../tests/Span/IndexOfSequence.char.cs | 101 + .../src/Resources/Strings.resx | 30 - .../BrowserHttpHandler/BrowserHttpHandler.cs | 97 +- .../System/Net/Http/Headers/HttpHeaders.cs | 574 +- .../Http/Headers/HttpHeadersNonValidated.cs | 37 +- ...ntHandler.AnyMobile.InvokeNativeHandler.cs | 12 +- .../AuthenticationHelper.Digest.cs | 25 +- .../SocketsHttpHandler/Http2Connection.cs | 11 +- .../SocketsHttpHandler/Http3RequestStream.cs | 9 +- .../Http/SocketsHttpHandler/HttpConnection.cs | 10 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 21 +- .../UnitTests/HPack/HPackRoundtripTests.cs | 2 +- .../UnitTests/Headers/HttpHeadersTest.cs | 162 + .../src/Resources/Strings.resx | 10 +- .../src/System.Net.Mail.csproj | 2 +- .../src/System/Net/Mail/Attachment.cs | 23 +- .../src/System/Net/Mail/MailAddress.cs | 13 +- .../System/Net/Mail/MailAddressCollection.cs | 9 +- .../src/System/Net/Mail/MailMessage.cs | 13 +- .../src/System/Net/Mail/MailPriority.cs | 13 +- .../src/System/Net/Mail/SmtpClient.cs | 10 +- .../src/System/Net/Mime/ContentDisposition.cs | 9 +- .../src/System/Net/Mime/ContentType.cs | 19 +- .../src/System/Net/Mime/HeaderCollection.cs | 69 +- .../Functional/ContentDispositionTest.cs | 2 +- .../tests/Functional/SmtpClientTest.cs | 4 +- .../src/System/Net/Dns.cs | 6 +- .../tests/PalTests/NameResolutionPalTests.cs | 33 +- .../NetworkAddressChange.Unix.cs | 53 +- .../SystemIPGlobalProperties.cs | 4 +- .../NetworkAddressChangedTests.cs | 29 + .../tests/FunctionalTests/ProcessUtil.cs | 72 + ...NetworkInformation.Functional.Tests.csproj | 2 + .../FunctionalTests/TestConfiguration.cs | 29 + .../src/Resources/Strings.resx | 3 - .../Net/NetworkInformation/Ping.RawSocket.cs | 15 +- .../Net/NetworkInformation/Ping.Unix.cs | 2 +- .../tests/FunctionalTests/TestSettings.cs | 4 +- .../src/System/Net/Cookie.cs | 2 +- .../src/System/Net/CookieCollection.cs | 4 +- .../src/System/Net/CredentialCache.cs | 30 +- .../src/System/Net/DnsEndPoint.cs | 10 +- .../tests/FunctionalTests/DnsEndPointTest.cs | 4 +- .../tests/UnitTests/CookieContainerTest.cs | 45 + .../src/Resources/Strings.resx | 6 - .../Interop/SafeMsQuicConfigurationHandle.cs | 6 +- .../src/Resources/Strings.resx | 3 - .../src/System.Net.Requests.csproj | 2 +- .../tests/FtpWebRequestTest.cs | 4 +- .../src/Resources/Strings.resx | 83 +- .../src/System.Net.Security.csproj | 1 + .../src/System/Net/Security/MD4.cs | 256 + .../Security/Pal.OSX/SafeDeleteSslContext.cs | 1 + .../src/System/Net/Security/SecureChannel.cs | 115 +- .../Net/Security/SslStream.Implementation.cs | 265 +- .../Net/Security/SslStreamPal.Android.cs | 9 +- .../System/Net/Security/SslStreamPal.OSX.cs | 41 +- .../System/Net/Security/SslStreamPal.Unix.cs | 66 +- .../Net/Security/SslStreamPal.Windows.cs | 26 +- .../ServiceNameCollection.cs | 5 +- .../ClientAsyncAuthenticateTest.cs | 14 - .../FunctionalTests/Resources/Strings.resx | 9 - .../ServerAsyncAuthenticateTest.cs | 9 +- .../ServiceNameCollectionTest.cs | 36 +- .../SslStreamMutualAuthenticationTest.cs | 95 + .../SslStreamNetworkStreamTest.cs | 130 +- .../System.Net.Security.Tests.csproj | 3 + .../tests/UnitTests/MD4Tests.cs | 158 + .../System.Net.Security.Unit.Tests.csproj | 6 +- .../src/System.Net.ServicePoint.csproj | 2 +- .../ref/System.Net.Sockets.cs | 3 +- .../src/Resources/Strings.resx | 3 - .../System/Net/Sockets/IPPacketInformation.cs | 48 +- .../Net/Sockets/SocketAsyncEventArgs.cs | 8 +- .../IPPacketInformationTest.cs | 7 + .../FunctionalTests/SocketDuplicationTests.cs | 1 - .../src/Resources/Strings.resx | 6 +- .../src/System/Net/WebHeaderCollection.cs | 9 +- .../ref/System.Net.WebProxy.cs | 8 +- .../ref/System.Net.WebProxy.csproj | 3 +- .../src/System/Net/WebProxy.cs | 8 +- .../src/Resources/Strings.resx | 15 - .../tests/AbortTest.cs | 1 + .../tests/ConnectTest.cs | 4 + .../System.Net.WebSockets.Client.Tests.csproj | 23 +- .../tests/WebSocketHelper.cs | 2 +- .../tests/package-lock.json | 44 + .../tests/package.json | 7 + .../tests/Vector2Tests.cs | 4 +- .../src/Internal/Console.Android.cs | 24 + .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 15 +- .../SafeHandles/SafeFileHandle.Windows.cs | 41 +- .../src/Resources/Strings.resx | 28 +- .../System.Private.CoreLib.Shared.projitems | 44 +- .../src/System/AppContext.cs | 10 +- .../src/System/AppDomain.cs | 9 +- .../src/System/ApplicationId.cs | 7 +- .../src/System/ArgumentException.cs | 21 + .../src/System/ArraySegment.cs | 10 +- .../src/System/Collections/Hashtable.cs | 2 +- .../src/System/DateOnly.cs | 6 +- .../src/System/DateTime.cs | 24 +- .../src/System/DateTimeOffset.cs | 24 +- .../SetsRequiredMembersAttribute.cs | 18 + .../CodeAnalysis/StringSyntaxAttribute.cs | 49 + .../Diagnostics/Tracing/EventDescriptor.cs | 2 +- .../System/Diagnostics/Tracing/EventSource.cs | 6 +- .../Diagnostics/UnreachableException.cs | 41 + .../src/System/Environment.cs | 13 +- .../src/System/Environment.iOS.cs | 13 + .../src/System/Globalization/CultureData.cs | 2 +- .../System/Globalization/DateTimeFormat.cs | 8 +- .../System/Globalization/NumberFormatInfo.cs | 39 +- .../src/System/HashCode.cs | 2 + .../src/System/IO/BufferedStream.cs | 33 +- .../src/System/IO/Directory.cs | 27 +- .../src/System/IO/DirectoryInfo.cs | 5 +- .../IO/Enumeration/FileSystemEntry.Unix.cs | 16 +- .../src/System/IO/File.cs | 50 +- .../src/System/IO/FileInfo.cs | 10 +- .../src/System/IO/FileStatus.SetTimes.OSX.cs | 26 +- .../IO/FileStatus.SetTimes.OtherUnix.cs | 14 +- .../src/System/IO/FileStatus.Unix.cs | 330 +- .../src/System/IO/FileStream.cs | 16 +- .../src/System/IO/FileSystem.Unix.cs | 263 +- .../src/System/IO/FileSystem.cs | 11 +- .../src/System/IO/FileSystemInfo.Unix.cs | 20 +- .../src/System/IO/FileSystemInfo.cs | 1 - .../src/System/IO/MemoryStream.cs | 9 +- .../src/System/IO/Path.Unix.cs | 6 +- .../src/System/IO/RandomAccess.Unix.cs | 8 +- .../src/System/IO/RandomAccess.Windows.cs | 39 +- .../src/System/IO/RandomAccess.cs | 25 +- .../Strategies/BufferedFileStreamStrategy.cs | 17 +- .../IO/Strategies/FileStreamHelpers.Unix.cs | 3 - .../Strategies/FileStreamHelpers.Windows.cs | 31 - .../System/IO/Strategies/FileStreamHelpers.cs | 9 +- .../IO/Strategies/OSFileStreamStrategy.cs | 39 +- .../src/System/IO/StreamReader.cs | 166 +- .../src/System/IO/StreamWriter.cs | 24 +- .../src/System/IO/StringReader.cs | 63 + .../src/System/IO/TextReader.cs | 74 +- .../src/System/IO/UnmanagedMemoryAccessor.cs | 4 +- .../src/System/IO/UnmanagedMemoryStream.cs | 7 +- .../src/System/ISpanFormattable.cs | 1 + .../src/System/IntPtr.cs | 2 + .../System.Private.CoreLib/src/System/Math.cs | 24 +- .../src/System/MemoryExtensions.cs | 25 +- .../src/System/Nullable.cs | 2 + .../src/System/Numerics/BitOperations.cs | 20 + .../src/System/Random.cs | 2 +- .../src/System/Reflection/AssemblyName.cs | 57 +- .../AssemblyNameHelpers.StrongName.cs | 3 +- .../System/Reflection/AssemblyNameParser.cs | 427 + .../CustomAttributeNamedArgument.cs | 17 +- .../CustomAttributeTypedArgument.cs | 11 +- .../Reflection/NullabilityInfoContext.cs | 316 +- .../DisableRuntimeMarshallingAttribute.cs | 27 + .../RequiredMemberAttribute.cs | 15 + .../CompilerServices/RuntimeFeature.cs | 6 + .../CompilerServices/RuntimeHelpers.cs | 10 + .../Runtime/InteropServices/Architecture.cs | 3 +- .../InteropServices/ArrayWithOffset.cs | 4 +- .../Runtime/InteropServices/GCHandle.cs | 9 +- .../System/Runtime/InteropServices/NFloat.cs | 700 +- .../Runtime/InteropServices/OSPlatform.cs | 4 +- .../RuntimeInformation.ProcessArchitecture.cs | 2 + .../System/Runtime/Intrinsics/Vector256.cs | 11 +- .../Runtime/Loader/AssemblyLoadContext.cs | 10 +- .../Runtime/Serialization/StreamingContext.cs | 2 + .../Runtime/Versioning/FrameworkName.cs | 26 +- .../src/System/Security/SecurityElement.cs | 36 +- .../src/System/SpanHelpers.Byte.cs | 310 +- .../src/System/SpanHelpers.Char.cs | 299 +- .../src/System/SpanHelpers.T.cs | 10 +- .../src/System/String.Comparison.cs | 21 +- .../src/System/String.Manipulation.cs | 19 +- .../System/Text/DecoderReplacementFallback.cs | 2 +- .../System/Text/EncoderReplacementFallback.cs | 2 +- .../src/System/Text/StringBuilder.cs | 428 +- .../src/System/Threading/CancellationToken.cs | 2 +- .../Threading/EventWaitHandle.Windows.cs | 5 +- .../System/Threading/LowLevelLifoSemaphore.cs | 9 +- .../src/System/Threading/Mutex.Unix.cs | 10 +- .../src/System/Threading/Mutex.Windows.cs | 10 +- .../PortableThreadPool.ThreadCounts.cs | 5 +- .../PortableThreadPool.WorkerTracking.cs | 11 +- .../src/System/Threading/Semaphore.Windows.cs | 5 +- .../Tasks/CachedCompletedInt32Task.cs | 36 + .../src/System/Threading/Tasks/Task.cs | 14 + .../src/System/ThrowHelper.cs | 12 +- .../src/System/TimeOnly.cs | 6 +- .../src/System/TimeZoneInfo.AdjustmentRule.cs | 6 + .../src/System/TimeZoneInfo.Unix.Android.cs | 92 +- .../src/System/UIntPtr.cs | 2 + .../src/Resources/Strings.resx | 9 - .../src/Resources/Strings.resx | 18 - .../JavaScript/JSObject.References.cs | 6 +- .../InteropServices/JavaScript/Runtime.cs | 206 +- .../tests/FunctionalTests/UriTests.cs | 4 +- .../src/Resources/Strings.resx | 6 +- .../src/System/Xml/Linq/XElement.cs | 3 +- .../src/System/Xml/Linq/XName.cs | 3 +- .../tests/SDMSample/SDMElement.cs | 2 +- .../tests/SDMSample/SDMXName.cs | 2 +- .../tests/Streaming/StreamingOutput.cs | 2 +- .../tests/axes/InvalidParamValidation.cs | 4 +- .../src/Resources/Strings.resx | 24 - .../System/Xml/BinaryXml/XmlBinaryReader.cs | 49 +- .../src/System/Xml/Core/XmlReader.cs | 11 +- .../src/System/Xml/Core/XmlReaderSettings.cs | 7 +- .../src/System/Xml/Core/XmlTextReaderImpl.cs | 10 +- .../src/System/Xml/XmlConvert.cs | 12 +- .../src/System/Xml/Xsl/Pair.cs | 43 +- .../src/System/Xml/Xsl/XmlQueryCardinality.cs | 2 +- .../src/System/Xml/Xsl/Xslt/QilGenerator.cs | 6 +- .../XmlSerializerTests.RuntimeOnly.cs | 52 +- .../Xslt/XslTransformApi/CXslTransform.cs | 2 +- .../src/Resources/Strings.resx | 3 - .../MethodBuilder/MethodBuilderByRefs.cs | 21 + .../ModuleBuilder/ModuleBuilderDefineEnum.cs | 4 +- .../ModuleBuilderDefineInitializedData.cs | 55 + .../tests/System.Reflection.Emit.Tests.csproj | 1 + .../TypeBuilderAddInterfaceImplementaion.cs | 7 - .../TypeBuilder/TypeBuilderDefineEvent.cs | 6 +- .../TypeBuilder/TypeBuilderDefineField.cs | 73 +- .../TypeBuilderDefineNestedType.cs | 8 +- .../tests/TypeBuilder/TypeBuilderSetParent.cs | 4 +- .../System.Reflection.Emit/tests/Utilities.cs | 11 +- .../tests/RuntimeReflectionExtensionTests.cs | 2 +- .../src/Resources/Strings.resx | 3 - .../Internal/Utilities/ExceptionUtilities.cs | 3 - .../Reflection/Metadata/Internal/BlobHeap.cs | 2 +- .../Metadata/MetadataReader.netstandard.cs | 53 +- .../PortableExecutable/ManagedTextSection.cs | 16 +- .../tests/Metadata/MetadataReaderTests.cs | 20 +- .../TypeSystem/AssemblyDefinitionTests.cs | 4 +- .../TypeSystem/AssemblyReferenceTests.cs | 4 +- .../PortableExecutable/PEBuilderTests.cs | 98 +- .../tests/Utilities/CompressedIntegerTests.cs | 2 +- .../tests/AssemblyNameTests.cs | 50 +- .../System.Reflection/tests/AssemblyTests.cs | 2 +- .../System.Reflection/tests/GetTypeTests.cs | 18 +- .../tests/ParameterInfoTests.cs | 6 +- .../tests/BinaryResourceWriterUnitTest.cs | 36 +- .../tests/runtimeconfig.template.json | 5 - .../src/Resources/Strings.resx | 3 - .../System/Runtime/Caching/CacheExpires.cs | 55 +- .../src/System/Runtime/Caching/CacheUsage.cs | 62 +- .../tests/System/EnvironmentTests.cs | 2 +- .../tests/System/IO/PathTests.cs | 2 +- .../tests/System/IO/PathTests_Unix.cs | 2 +- .../tests/System/IO/PathTests_Windows.cs | 2 +- .../tests/CheckArchitectureTests.cs | 4 + .../DllImportGenerator.csproj | 8 +- .../Marshalling/ArrayMarshaller.cs | 2 +- .../ref/System.Runtime.InteropServices.cs | 114 +- .../Runtime/InteropServices/GCHandleTests.cs | 1 + .../Runtime/InteropServices/NFloatTests.cs | 839 +- .../ObjectiveC/MessageSendTests.cs | 10 - .../ObjectiveC/PendingExceptionTests.cs | 5 - .../InteropServices/SafeBufferTests.cs | 4 +- .../tests/Vectors/Vector128Tests.cs | 2 + .../AddLambdaCapturingThis.cs | 22 +- .../AddLambdaCapturingThis_v1.cs | 28 +- .../AddNestedClass.cs | 20 + .../AddNestedClass_v1.cs | 29 + ...ata.ApplyUpdate.Test.AddNestedClass.csproj | 11 + .../deltascript.json | 6 + .../AddStaticField.cs | 22 + .../AddStaticField_v1.cs | 25 + ...ata.ApplyUpdate.Test.AddStaticField.csproj | 11 + .../deltascript.json | 6 + .../AddStaticLambda.cs | 18 + .../AddStaticLambda_v1.cs | 18 + ...ta.ApplyUpdate.Test.AddStaticLambda.csproj | 11 + .../deltascript.json | 6 + .../tests/ApplyUpdateTest.cs | 96 +- .../tests/ApplyUpdateUtil.cs | 2 +- .../DefaultContext/DefaultLoadContextTest.cs | 2 +- .../tests/System.Runtime.Loader.Tests.csproj | 3 + .../src/System/Numerics/BigNumber.cs | 4 +- .../tests/BigInteger/parse.cs | 16 +- .../src/Resources/Strings.resx | 3 - .../tests/BinaryFormatterTestData.cs | 6 +- .../tests/SerializationGuardTests.cs | 2 +- .../tests/runtimeconfig.template.json | 5 - .../tests/DataContractJsonSerializer.cs | 52 +- .../tests/DataContractSerializer.cs | 24 +- .../System.Runtime/ref/System.Runtime.cs | 122 +- .../tests/System.Runtime.Tests.csproj | 2 + .../tests/System/ArgumentExceptionTests.cs | 27 + .../System.Runtime/tests/System/ArrayTests.cs | 3 + .../tests/System/DateOnlyTests.cs | 10 + .../SetsRequiredMembersAttributeTests.cs | 16 + .../StringSyntaxAttributeTests.cs | 25 + .../Diagnostics/UnreachableExceptionTests.cs | 40 + .../tests/System/ExitCodeTests.Unix.cs | 1 + .../System/IO/EndOfStreamExceptionTests.cs | 4 +- .../System/NullReferenceExceptionTests.cs | 4 +- ...stomAttribute_Named_Typed_ArgumentTests.cs | 22 + .../Reflection/NullabilityInfoContextTests.cs | 214 +- .../CompilerServices/AttributesTests.cs | 6 + .../tests/System/Text/StringBuilderTests.cs | 2 - .../tests/System/TimeOnlyTests.cs | 11 + .../tests/System/TimeZoneInfoTests.cs | 15 + ...stem.Security.Cryptography.Cng.Forwards.cs | 35 + .../ref/System.Security.Cryptography.Cng.cs | 390 - .../System.Security.Cryptography.Cng.csproj | 5 +- .../src/Internal/Cryptography/Helpers.cs | 178 - .../Internal/Cryptography/KeyPropertyName.cs | 40 - .../SymmetricImportExportExtensions.cs | 67 - .../src/Resources/Strings.resx | 282 - .../System.Security.Cryptography.Cng.csproj | 374 +- .../System/Security/Cryptography/CngPkcs8.cs | 52 - .../System/Security/Cryptography/DSACng.cs | 42 - .../Cryptography/ECDiffieHellmanCng.Derive.cs | 146 - .../Cryptography/ECDiffieHellmanCng.Key.cs | 135 - .../Cryptography/ECDiffieHellmanCng.cs | 209 - .../ECDiffieHellmanCngPublicKey.cs | 153 - .../Security/Cryptography/ECDsaCng.Key.cs | 123 - .../System/Security/Cryptography/ECDsaCng.cs | 154 - .../System/Security/Cryptography/RSACng.cs | 42 - ...stem.Security.Cryptography.Csp.Forwards.cs | 27 + .../ref/System.Security.Cryptography.Csp.cs | 306 - .../System.Security.Cryptography.Csp.csproj | 2 +- .../src/Internal/Cryptography/Helpers.cs | 45 - .../src/Resources/Strings.resx | 227 - .../System.Security.Cryptography.Csp.csproj | 131 +- .../Security/Cryptography/CapiHelper.Unix.cs | 21 - ....Security.Cryptography.OpenSsl.Forwards.cs | 11 + .../System.Security.Cryptography.OpenSsl.cs | 94 - ...ystem.Security.Cryptography.OpenSsl.csproj | 3 +- .../src/Resources/Strings.resx | 242 - ...ystem.Security.Cryptography.OpenSsl.csproj | 167 +- .../src/Resources/Strings.resx | 24 - .../System.Security.Cryptography.Pkcs.csproj | 4 + .../Pkcs/Asn1/CertificateChoiceAsn.xml | 10 +- .../Pkcs/Asn1/CertificateChoiceAsn.xml.cs | 114 + .../Pkcs/Asn1/OtherCertificateFormat.xml | 17 + .../Pkcs/Asn1/OtherCertificateFormat.xml.cs | 98 + .../Security/Cryptography/Pkcs/SignedCms.cs | 12 +- .../tests/SignedCms/SignedCmsTests.cs | 9 + .../tests/SignedCms/SignedDocuments.cs | 154 + .../SignedCms/SignerInfoTests.netcoreapp.cs | 2 +- ....Cryptography.X509Certificates.Forwards.cs | 50 + ....Security.Cryptography.X509Certificates.cs | 684 -- ...urity.Cryptography.X509Certificates.csproj | 7 +- .../src/Internal/Cryptography/Helpers.cs | 350 - .../Pal.Android/CertificatePal.cs | 36 - .../Cryptography/Pal.OSX/CertificatePal.cs | 45 - .../Cryptography/Pal.Unix/CertificatePal.cs | 34 - .../Internal/Cryptography/Pal.Unix/FindPal.cs | 15 - .../Cryptography/Pal.Windows/X509Pal.cs | 30 - .../src/Resources/Strings.resx | 493 - ...urity.Cryptography.X509Certificates.csproj | 987 +- .../CertificateRequestApiTests.cs | 60 +- .../tests/Resources/Strings.resx | 78 - .../RevocationTests/DynamicRevocationTests.cs | 2 +- .../tests/DSAKeyValueTest.cs | 10 +- .../tests/XmlLicenseEncryptedRef.cs | 2 +- .../ref/System.Security.Cryptography.cs | 1727 +++ .../ref/System.Security.Cryptography.csproj | 4 + .../Win32/SafeHandles/NCryptSafeHandles.cs | 12 +- .../Win32/SafeHandles/SafePasswordHandle.cs | 0 .../src/Resources/Strings.resx | 327 +- .../src/System.Security.Cryptography.csproj | 1037 +- .../Security/Cryptography/AesCng.Windows.cs} | 7 +- .../Cryptography/AesCryptoServiceProvider.cs | 2 + .../Cryptography/BasicSymmetricCipherCsp.cs | 17 +- .../BasicSymmetricCipherNCrypt.cs | 15 +- .../Cryptography/CapiHelper.Browser.cs | 11 + .../Cryptography/CapiHelper.DSA.Shared.cs | 4 +- .../Cryptography/CapiHelper.DSA.Windows.cs | 6 +- .../Cryptography/CapiHelper.Shared.cs | 18 +- .../Cryptography/CapiHelper.SymmetricKey.cs | 2 +- .../Security/Cryptography/CapiHelper.Unix.cs} | 38 +- .../Cryptography/CapiHelper.Windows.cs | 122 +- .../Security/Cryptography/Cng.NotSupported.cs | 378 + .../Security/Cryptography/CngAlgorithm.cs | 6 +- .../Cryptography/CngAlgorithmCore.cs | 6 +- .../Cryptography/CngAlgorithmGroup.cs | 6 +- .../Cryptography/CngExportPolicies.cs | 0 .../Security/Cryptography/CngHelpers.cs | 242 + .../Security/Cryptography/CngKey.Create.cs | 6 +- .../Security/Cryptography/CngKey.Delete.cs | 0 .../System/Security/Cryptography/CngKey.EC.cs | 6 +- .../Security/Cryptography/CngKey.Exists.cs | 4 + .../Security/Cryptography/CngKey.Export.cs | 0 .../Security/Cryptography/CngKey.Import.cs | 3 + .../Security/Cryptography/CngKey.Open.cs | 4 + .../Cryptography/CngKey.OpenHandle.cs | 4 +- .../Cryptography/CngKey.Properties.cs | 2 +- .../Cryptography/CngKey.StandardProperties.cs | 0 .../System/Security/Cryptography/CngKey.cs | 35 +- .../Security/Cryptography/CngKeyBlobFormat.cs | 6 +- .../Cryptography/CngKeyCreationOptions.cs | 0 .../Cryptography/CngKeyCreationParameters.cs | 0 .../Cryptography/CngKeyHandleOpenOptions.cs | 0 .../Security/Cryptography/CngKeyLite.cs | 187 +- .../Cryptography/CngKeyOpenOptions.cs | 0 .../Security/Cryptography/CngKeyUsages.cs | 0 .../System/Security/Cryptography/CngPkcs8.cs | 27 +- .../Security/Cryptography/CngProperty.cs | 0 .../Cryptography/CngPropertyCollection.cs | 0 .../Cryptography/CngPropertyOptions.cs | 0 .../Security/Cryptography/CngProvider.cs | 6 +- .../Cryptography/CngSymmetricAlgorithmCore.cs | 26 +- .../Security/Cryptography/CngUIPolicy.cs | 0 .../Cryptography/CngUIProtectionLevels.cs | 0 .../Security/Cryptography/CryptoConfig.cs | 38 +- .../CspKeyContainerInfo.NotSupported.cs} | 0 .../CspKeyContainerInfo.Windows.cs | 22 +- .../Security/Cryptography/CspParameters.cs | 3 - .../Security/Cryptography/CspProviderFlags.cs | 0 .../DESCryptoServiceProvider.NotSupported.cs | 24 + .../DESCryptoServiceProvider.Unix.cs | 4 +- .../DESCryptoServiceProvider.Windows.cs | 1 - .../Cryptography/DSA.Create.OpenSsl.cs | 13 + .../DSA.Create.SecurityTransforms.cs | 13 + .../Cryptography/DSA.Create.Windows.cs | 13 + .../src/System/Security/Cryptography/DSA.cs | 90 +- .../Cryptography/DSACng.ImportExport.cs | 0 .../Security/Cryptography/DSACng.Key.cs | 0 .../System/Security/Cryptography/DSACng.cs | 163 +- .../DSACryptoServiceProvider.NotSupported.cs | 68 + .../DSACryptoServiceProvider.Unix.cs | 5 +- .../DSACryptoServiceProvider.Windows.cs | 25 +- .../Security/Cryptography/DSAOpenSsl.cs | 16 + .../Security/Cryptography/DSAWrapper.cs | 165 + .../Cryptography/ECCng.ImportExport.cs | 0 .../System/Security/Cryptography/ECCngKey.cs | 4 +- .../System/Security/Cryptography/ECCurve.cs | 4 +- .../ECDiffieHellman.Create.Cng.cs | 8 +- .../ECDiffieHellman.Create.OpenSsl.cs | 8 +- .../Cryptography/ECDiffieHellmanCng.Derive.cs | 161 +- .../Cryptography/ECDiffieHellmanCng.Key.cs | 134 +- .../Cryptography/ECDiffieHellmanCng.Xml.cs | 0 .../Cryptography/ECDiffieHellmanCng.cs | 247 +- .../ECDiffieHellmanCngPublicKey.cs | 173 +- .../ECDiffieHellmanKeyDerivationFunction.cs | 15 + .../Cryptography/ECDiffieHellmanOpenSsl.cs | 11 + .../Cryptography/ECDiffieHellmanWrapper.cs | 209 + .../Cryptography/ECDsa.Create.OpenSsl.cs | 19 +- .../ECDsa.Create.SecurityTransforms.cs | 42 + .../Cryptography/ECDsa.Create.Windows.cs | 41 + .../src/System/Security/Cryptography/ECDsa.cs | 87 +- .../Security/Cryptography/ECDsaCng.Key.cs | 119 +- .../System/Security/Cryptography/ECDsaCng.cs | 233 +- .../Security/Cryptography/ECDsaOpenSsl.cs | 11 + .../Security/Cryptography/ECDsaWrapper.cs | 190 + .../Security/Cryptography/ECKeyXmlFormat.cs | 0 .../System/Security/Cryptography/HMACMD5.cs | 172 + .../System/Security/Cryptography/HMACSHA1.cs | 173 +- .../Security/Cryptography/HMACSHA256.cs | 173 +- .../Security/Cryptography/HMACSHA384.cs | 176 +- .../Security/Cryptography/HMACSHA512.cs | 176 +- .../Cryptography/HashAlgorithmNames.Apple.cs | 19 + .../Cryptography/HashAlgorithmNames.cs | 2 +- .../HashProviderDispenser.Apple.cs | 209 +- .../HashProviderDispenser.OpenSsl.cs | 130 +- .../System/Security/Cryptography/Helpers.cs | 283 +- .../Cryptography/ICngSymmetricAlgorithm.cs | 3 +- .../Cryptography/ICspAsymmetricAlgorithm.cs | 0 .../Security/Cryptography/IncrementalHash.cs | 6 +- .../System/Security/Cryptography/KeyNumber.cs | 0 .../Security/Cryptography/LiteHash.Apple.cs | 215 + .../Security/Cryptography/LiteHash.Browser.cs | 57 + .../Security/Cryptography/LiteHash.Unix.cs | 174 + .../Security/Cryptography/LiteHash.Windows.cs | 173 + .../Security/Cryptography/LiteHashProvider.cs | 195 + .../src/System/Security/Cryptography/MD5.cs | 125 + .../Cryptography/MD5CryptoServiceProvider.cs | 4 + .../Cryptography/OpenSsl.NotSupported.cs | 270 + .../PasswordDeriveBytes.NotSupported.cs} | 0 .../PasswordDeriveBytes.Windows.cs | 1 - .../Cryptography/PasswordDeriveBytes.cs | 0 .../Security/Cryptography/PinAndClear.cs | 30 + .../Cryptography/ProviderPropertyName.cs | 5 +- .../RC2CryptoServiceProvider.NotSupported.cs | 31 + .../RC2CryptoServiceProvider.Unix.cs | 7 +- .../RC2CryptoServiceProvider.Windows.cs | 3 +- .../Cryptography/RNGCryptoServiceProvider.cs | 0 .../Cryptography/RSA.Create.OpenSsl.cs | 13 + .../RSA.Create.SecurityTransforms.cs | 13 + .../Cryptography/RSA.Create.Windows.cs | 13 + .../src/System/Security/Cryptography/RSA.cs | 65 +- .../Cryptography/RSACng.ImportExport.cs | 0 .../Security/Cryptography/RSACng.Key.cs | 0 .../System/Security/Cryptography/RSACng.cs | 167 +- .../RSACryptoServiceProvider.NotSupported.cs | 52 + .../RSACryptoServiceProvider.Unix.cs | 15 +- .../RSACryptoServiceProvider.Windows.cs | 51 +- .../Cryptography/RSAEncryptionPadding.cs | 5 +- .../Security/Cryptography/RSAOpenSsl.cs | 16 + .../Security/Cryptography/RSAWrapper.cs | 219 + .../Rfc2898DeriveBytes.OneShot.cs | 6 +- .../src/System/Security/Cryptography/SHA1.cs | 125 + .../Cryptography/SHA1CryptoServiceProvider.cs | 0 .../System/Security/Cryptography/SHA256.cs | 125 + .../SHA256CryptoServiceProvider.cs | 0 .../System/Security/Cryptography/SHA384.cs | 125 + .../SHA384CryptoServiceProvider.cs | 0 .../System/Security/Cryptography/SHA512.cs | 125 + .../SHA512CryptoServiceProvider.cs | 0 .../SafeEvpPKeyHandle.OpenSsl.cs} | 25 +- .../Cryptography/TripleDESCng.Windows.cs} | 7 +- ...leDESCryptoServiceProvider.NotSupported.cs | 24 + .../TripleDESCryptoServiceProvider.Wrap.cs} | 5 +- .../src/System/Security/Cryptography/Utils.cs | 0 .../AndroidCertificatePal.cs | 5 +- .../X509Certificates}/AndroidPkcs12Reader.cs | 5 +- .../AppleCertificateExporter.iOS.cs} | 6 +- .../AppleCertificatePal.ImportExport.iOS.cs} | 12 +- ...AppleCertificatePal.ImportExport.macOS.cs} | 7 +- .../AppleCertificatePal.Keys.iOS.cs} | 5 +- .../AppleCertificatePal.Keys.macOS.cs} | 51 +- .../AppleCertificatePal.Pem.iOS.cs} | 7 +- .../AppleCertificatePal.Pkcs12.iOS.cs} | 13 +- .../AppleCertificatePal.Pkcs12.macOS.cs} | 4 +- .../AppleCertificatePal.TempExportPal.cs | 4 +- .../X509Certificates}/AppleCertificatePal.cs | 9 +- .../ApplePkcs12CertLoader.iOS.cs} | 7 +- .../ApplePkcs12Reader.iOS.cs} | 6 +- .../ApplePkcs12Reader.macOS.cs} | 5 +- .../Asn1/AccessDescriptionAsn.xml | 0 .../Asn1/AccessDescriptionAsn.xml.cs | 0 .../Asn1/BasicConstraintsAsn.xml | 0 .../Asn1/BasicConstraintsAsn.xml.cs | 0 .../X509Certificates/Asn1/CertificateAsn.xml | 0 .../Asn1/CertificateAsn.xml.cs | 0 .../Asn1/CertificatePolicyMappingAsn.xml | 0 .../Asn1/CertificatePolicyMappingAsn.xml.cs | 0 .../Asn1/CertificateTemplateAsn.xml | 0 .../Asn1/CertificateTemplateAsn.xml.cs | 0 .../Asn1/CertificationRequestAsn.xml | 0 .../Asn1/CertificationRequestAsn.xml.cs | 0 .../Asn1/CertificationRequestInfoAsn.xml | 0 .../Asn1/CertificationRequestInfoAsn.xml.cs | 0 .../Asn1/DistributionPointAsn.xml | 0 .../Asn1/DistributionPointAsn.xml.cs | 0 .../Asn1/DistributionPointNameAsn.xml | 0 .../Asn1/DistributionPointNameAsn.xml.cs | 0 .../X509Certificates/Asn1/KeyUsageFlagsAsn.cs | 0 .../Asn1/PolicyConstraintsAsn.xml | 0 .../Asn1/PolicyConstraintsAsn.xml.cs | 0 .../Asn1/PolicyInformationAsn.xml | 0 .../Asn1/PolicyInformationAsn.xml.cs | 0 .../X509Certificates/Asn1/ReasonFlagsAsn.cs | 0 .../Asn1/TbsCertificateAsn.manual.cs | 0 .../Asn1/TbsCertificateAsn.xml | 0 .../Asn1/TbsCertificateAsn.xml.cs | 0 .../X509Certificates/Asn1/TimeAsn.manual.cs | 0 .../X509Certificates/Asn1/TimeAsn.xml | 0 .../X509Certificates/Asn1/TimeAsn.xml.cs | 0 .../Asn1/ValidityAsn.manual.cs | 0 .../X509Certificates/Asn1/ValidityAsn.xml | 0 .../X509Certificates/Asn1/ValidityAsn.xml.cs | 0 .../X509Certificates}/CertCollectionLoader.cs | 4 +- .../CertificateData.ManagedDecode.cs | 5 +- .../CertificateExtensionsCommon.cs | 6 +- .../CertificatePal.Android.cs | 36 + .../X509Certificates/CertificatePal.Apple.cs | 36 + .../CertificatePal.NotSupported.cs | 36 + .../CertificatePal.OpenSsl.cs | 33 + .../CertificatePal.Windows.Import.cs} | 16 +- .../CertificatePal.Windows.PrivateKey.cs} | 8 +- .../CertificatePal.Windows.cs} | 13 +- .../X509Certificates/CertificatePal.cs | 24 + .../X509Certificates}/CertificatePolicy.cs | 5 +- .../X509Certificates/CertificateRequest.cs | 55 +- .../X509Certificates/ChainPal.Android.cs} | 25 +- .../X509Certificates/ChainPal.Apple.cs} | 32 +- .../X509Certificates/ChainPal.NotSupported.cs | 35 + .../X509Certificates/ChainPal.OpenSsl.cs} | 17 +- .../ChainPal.Windows.BuildChain.cs} | 18 +- ...nPal.Windows.GetChainStatusInformation.cs} | 7 +- .../X509Certificates/ChainPal.Windows.cs} | 18 +- .../Cryptography/X509Certificates/ChainPal.cs | 26 + .../DSACertificateExtensions.cs | 1 - .../ECDsaCertificateExtensions.cs | 2 - .../ECDsaX509SignatureGenerator.cs | 0 .../X509Certificates}/ErrorCode.cs | 14 +- .../X509Certificates/FindPal.Android.cs} | 8 +- .../X509Certificates/FindPal.Apple.cs} | 8 +- .../X509Certificates/FindPal.NotSupported.cs | 13 + .../X509Certificates/FindPal.OpenSsl.cs | 21 + .../X509Certificates/FindPal.Windows.cs} | 13 +- .../Cryptography/X509Certificates}/FindPal.cs | 187 +- .../X509Certificates}/ICertificatePal.cs | 5 +- .../X509Certificates}/ICertificatePalCore.cs | 7 +- .../X509Certificates}/IChainPal.cs | 6 +- .../X509Certificates}/IExportPal.cs | 4 +- .../X509Certificates}/IFindPal.cs | 5 +- .../X509Certificates}/ILoaderPal.cs | 5 +- .../X509Certificates}/IStorePal.cs | 4 +- .../X509Certificates}/IX509Pal.cs | 6 +- .../ManagedCertificateFinder.cs | 6 +- .../ManagedX509ExtensionProcessor.cs | 5 +- .../X509Certificates/OpenFlags.cs | 0 .../OpenSslCachedDirectoryStoreProvider.cs} | 9 +- .../OpenSslCachedSystemStoreProvider.cs} | 16 +- .../OpenSslCertificateAssetDownloader.cs} | 7 +- .../OpenSslCertificateFinder.cs | 4 +- .../X509Certificates/OpenSslCrlCache.cs} | 9 +- .../OpenSslDirectoryBasedStoreProvider.cs} | 11 +- .../OpenSslExportProvider.cs} | 13 +- .../X509Certificates}/OpenSslPkcs12Reader.cs | 4 +- .../OpenSslPkcsFormatReader.cs} | 4 +- .../OpenSslSingleCertLoader.cs} | 7 +- .../OpenSslX509CertificateReader.cs | 17 +- .../OpenSslX509ChainProcessor.cs | 51 +- .../X509Certificates}/OpenSslX509Encoder.cs | 11 +- .../Pkcs10CertificationRequestInfo.cs | 2 +- .../X509Certificates/Pkcs9ExtensionRequest.cs | 0 .../X509Certificates/PublicKey.cs | 8 +- .../RSACertificateExtensions.cs | 1 - .../RSAPkcs1X509SignatureGenerator.cs | 0 .../RSAPssX509SignatureGenerator.cs | 0 .../X509Certificates/SafeLocalAllocHandle.cs} | 2 +- .../X509Certificates/StoreLocation.cs | 0 .../X509Certificates/StoreName.cs | 0 .../StorePal.Android.AndroidKeyStore.cs} | 5 +- .../StorePal.Android.ExportPal.cs} | 5 +- .../StorePal.Android.LoaderPal.cs} | 6 +- .../StorePal.Android.TrustedStore.cs} | 5 +- .../X509Certificates/StorePal.Android.cs} | 17 +- .../X509Certificates/StorePal.NotSupported.cs | 50 + .../X509Certificates/StorePal.OpenSsl.cs} | 43 +- .../StorePal.Windows.Export.cs} | 8 +- .../StorePal.Windows.Import.cs} | 20 +- .../X509Certificates/StorePal.Windows.cs} | 10 +- .../Cryptography/X509Certificates/StorePal.cs | 32 + .../StorePal.iOS.AppleKeychainStore.cs} | 7 +- .../X509Certificates/StorePal.iOS.cs} | 20 +- .../StorePal.macOS.AppleKeychainStore.cs} | 5 +- .../StorePal.macOS.AppleTrustStore.cs} | 5 +- .../StorePal.macOS.ExportPal.cs} | 8 +- .../StorePal.macOS.LoaderPal.cs} | 7 +- .../X509Certificates/StorePal.macOS.cs} | 17 +- .../SubjectAlternativeNameBuilder.cs | 0 .../X509Certificates/UnixChainVerifier.cs} | 8 +- .../X509Certificates}/UnixExportProvider.cs | 7 +- .../X509Certificates}/UnixPkcs12Reader.cs | 5 +- .../UnsupportedDisallowedStore.cs | 5 +- .../X509Certificates/WindowsHelpers.cs} | 5 +- .../WindowsInterop.crypt32.cs} | 2 +- .../X509Certificates/WindowsStructs.cs} | 3 +- .../X500DictionaryStringHelper.cs | 37 + .../X509Certificates/X500DistinguishedName.cs | 2 - .../X500DistinguishedNameFlags.cs | 0 .../X500NameEncoder.ManagedDecode.cs | 4 +- .../X509Certificates}/X500NameEncoder.cs | 5 +- .../X509Certificates/X501Attribute.cs | 0 .../X509BasicConstraintsExtension.cs | 12 +- .../X509Certificates/X509Certificate.cs | 26 +- .../X509Certificates/X509Certificate2.cs | 38 +- .../X509Certificate2Collection.cs | 5 +- .../X509Certificate2Enumerator.cs | 0 .../X509CertificateCollection.cs | 0 .../X509CertificateEnumerator.cs | 0 .../X509Certificates/X509Chain.cs | 11 +- .../X509Certificates/X509ChainElement.cs | 0 .../X509ChainElementCollection.cs | 0 .../X509ChainElementEnumerator.cs | 0 .../X509Certificates/X509ChainPolicy.cs | 0 .../X509Certificates/X509ChainStatus.cs | 0 .../X509Certificates/X509ChainStatusFlags.cs | 0 .../X509Certificates/X509ChainTrustMode.cs | 0 .../X509Certificates/X509ContentType.cs | 0 .../X509EnhancedKeyUsageExtension.cs | 10 - .../X509Certificates/X509Extension.cs | 0 .../X509ExtensionCollection.cs | 0 .../X509ExtensionEnumerator.cs | 0 .../X509Certificates/X509FindType.cs | 0 .../X509Certificates/X509IncludeOption.cs | 0 .../X509Certificates/X509KeyStorageFlags.cs | 0 .../X509Certificates/X509KeyUsageExtension.cs | 10 - .../X509Certificates/X509KeyUsageFlags.cs | 0 .../X509Certificates/X509NameType.cs | 0 .../X509Certificates/X509Pal.Android.cs} | 10 +- .../X509Certificates/X509Pal.Apple.ECKey.cs} | 12 +- .../X509Pal.Apple.X500Name.cs} | 8 +- .../X509Certificates/X509Pal.NotSupported.cs | 13 + .../X509Certificates/X509Pal.OpenSsl.cs} | 7 +- .../X509Pal.Windows.CustomExtensions.cs} | 11 +- .../X509Pal.Windows.GetCertContentType.cs} | 11 +- .../X509Pal.Windows.PublicKey.cs} | 8 +- .../X509Pal.Windows.X500DistinguishedName.cs} | 6 +- .../X509Certificates/X509Pal.Windows.cs | 13 + .../Cryptography/X509Certificates/X509Pal.cs | 12 + .../X509Certificates/X509Pal.iOS.cs} | 14 +- .../X509Certificates/X509Pal.macOS.cs} | 12 +- .../X509Certificates}/X509Persistence.cs | 2 +- .../X509Certificates/X509RevocationFlag.cs | 0 .../X509Certificates/X509RevocationMode.cs | 0 .../X509SignatureGenerator.cs | 0 .../X509Certificates/X509Store.cs | 2 - .../X509SubjectKeyIdentifierExtension.cs | 3 +- .../X509SubjectKeyIdentifierHashAlgorithm.cs | 0 .../X509Certificates/X509VerificationFlags.cs | 0 .../tests/AsnEncodedDataTests.cs | 5 +- .../tests/DSATests.cs | 12 +- .../tests/ECDsaTests.cs | 12 +- .../tests/HashAlgorithmTestDriver.cs | 223 +- .../tests/HmacMD5Tests.cs | 100 + .../tests/HmacSha1Tests.cs | 102 +- .../tests/HmacSha256Tests.cs | 102 +- .../tests/HmacSha384Tests.cs | 102 +- .../tests/HmacSha512Tests.cs | 102 +- .../tests/HmacTests.cs | 221 + .../tests/IncrementalHashTests.cs | 4 +- .../tests/MD5Tests.cs | 64 + .../tests/RSATests.cs | 6 +- .../tests/Rfc2898OneShotTests.cs | 12 +- .../tests/Sha1Tests.cs | 70 + .../tests/Sha256Tests.cs | 79 + .../tests/Sha384Tests.cs | 78 +- .../tests/Sha512Tests.cs | 85 + .../tests/StreamHelpers.cs | 147 + .../System.Security.Cryptography.Tests.csproj | 1 + .../src/Resources/Strings.resx | 5 +- .../System/Security/Principal/NTAccount.cs | 20 +- .../src/Resources/Strings.resx | 3 - ...iceProcess.ServiceController.netcoreapp.cs | 3 + ...em.ServiceProcess.ServiceController.csproj | 2 + .../SessionChangeDescription.cs | 39 +- .../src/Internal/Synthesis/EngineSiteSapi.cs | 38 +- .../DecoderReplacementFallbackTests.cs | 12 +- .../EncoderReplacementFallbackTests.cs | 12 +- .../ref/System.Text.Encodings.Web.cs | 1 + .../System.Text.Rune.netstandard20.cs | 2 +- .../Text/Unicode/UnicodeRanges.generated.cs | 9 + .../tests/UnicodeRangesTests.generated.cs | 1 + .../System.Text.Json/ref/System.Text.Json.cs | 26 +- .../ref/System.Text.Json.csproj | 4 + .../src/Resources/Strings.resx | 6 - .../src/System.Text.Json.csproj | 8 +- .../Text/Json/Document/JsonDocument.Parse.cs | 4 +- .../System/Text/Json/Nodes/JsonNode.Parse.cs | 3 +- .../src/System/Text/Json/Nodes/JsonNode.cs | 4 +- .../JsonSerializer.Read.String.cs | 16 +- .../Metadata/DefaultValueHolder.cs | 42 + .../Metadata/GenericMethodHolder.cs | 52 - .../Metadata/JsonParameterInfo.cs | 6 +- .../Metadata/JsonPropertyInfoOfT.cs | 2 +- .../Serialization/Metadata/JsonTypeInfo.cs | 13 +- .../src/System/Text/Json/ThrowHelper.cs | 6 + .../Writer/Utf8JsonWriter.WriteValues.Raw.cs | 5 +- .../System/Text/Json/Writer/Utf8JsonWriter.cs | 2 +- .../JsonSerializerContextTests.cs | 5 +- .../System.Text.Json.Tests/BitStackTests.cs | 2 +- .../JsonNode/JsonNodeOperatorTests.cs | 2 + .../gen/RegexGenerator.Emitter.cs | 597 +- .../gen/RegexGenerator.Parser.cs | 17 +- .../gen/Resources/Strings.resx | 9 - .../gen/Resources/xlf/Strings.cs.xlf | 15 - .../gen/Resources/xlf/Strings.de.xlf | 15 - .../gen/Resources/xlf/Strings.es.xlf | 15 - .../gen/Resources/xlf/Strings.fr.xlf | 15 - .../gen/Resources/xlf/Strings.it.xlf | 15 - .../gen/Resources/xlf/Strings.ja.xlf | 15 - .../gen/Resources/xlf/Strings.ko.xlf | 15 - .../gen/Resources/xlf/Strings.pl.xlf | 15 - .../gen/Resources/xlf/Strings.pt-BR.xlf | 15 - .../gen/Resources/xlf/Strings.ru.xlf | 15 - .../gen/Resources/xlf/Strings.tr.xlf | 15 - .../gen/Resources/xlf/Strings.zh-Hans.xlf | 15 - .../gen/Resources/xlf/Strings.zh-Hant.xlf | 15 - ...m.Text.RegularExpressions.Generator.csproj | 2 + .../ref/System.Text.RegularExpressions.cs | 52 +- .../src/Resources/Strings.resx | 6 - .../src/System.Text.RegularExpressions.csproj | 3 + .../System/Text/RegularExpressions/Match.cs | 48 +- .../Text/RegularExpressions/Regex.Count.cs | 64 + .../Text/RegularExpressions/Regex.Debug.cs | 12 +- .../Text/RegularExpressions/Regex.Match.cs | 20 +- .../Text/RegularExpressions/Regex.Replace.cs | 14 +- .../Text/RegularExpressions/Regex.Split.cs | 7 +- .../System/Text/RegularExpressions/Regex.cs | 28 +- .../Text/RegularExpressions/RegexCharClass.cs | 19 +- .../Text/RegularExpressions/RegexCode.cs | 497 +- .../RegexCompilationInfo.cs | 11 +- .../Text/RegularExpressions/RegexCompiler.cs | 536 +- .../RegexFindOptimizations.cs | 82 +- .../RegexGeneratorAttribute.cs | 7 +- .../RegularExpressions/RegexInterpreter.cs | 191 +- .../Text/RegularExpressions/RegexNode.cs | 1673 +-- .../Text/RegularExpressions/RegexNodeKind.cs | 180 + .../Text/RegularExpressions/RegexOpcode.cs | 162 + .../Text/RegularExpressions/RegexOptions.cs | 11 +- .../Text/RegularExpressions/RegexParser.cs | 154 +- .../RegularExpressions/RegexPrefixAnalyzer.cs | 452 +- .../RegularExpressions/RegexReplacement.cs | 10 +- .../Text/RegularExpressions/RegexRunner.cs | 160 +- .../Text/RegularExpressions/RegexTree.cs | 16 +- .../Text/RegularExpressions/RegexWriter.cs | 253 +- .../Symbolic/RegexNodeToSymbolicConverter.cs | 111 +- .../Symbolic/SymbolicMatch.cs | 12 +- .../Symbolic/SymbolicRegexInfo.cs | 6 +- .../tests/Regex.Count.Tests.cs | 120 + .../tests/Regex.Match.Tests.cs | 139 +- .../tests/RegexReductionTests.cs | 212 +- ...ystem.Text.RegularExpressions.Tests.csproj | 1 + .../RateLimiting/ConcurrencyLimiter.cs | 23 +- .../RateLimiting/TokenBucketRateLimiter.cs | 23 +- .../tests/BaseRateLimiterTests.cs | 14 +- .../tests/ConcurrencyLimiterTests.cs | 91 +- .../tests/TokenBucketRateLimiterTests.cs | 97 +- .../src/Resources/Strings.resx | 3 - .../Dataflow/DataflowBlockExtensionTests.cs | 2 +- .../tests/Task/TaskRtTests.cs | 18 + .../System.Threading/ref/System.Threading.cs | 2 +- .../src/System/Threading/LockCookie.cs | 37 +- .../ref/System.Transactions.Local.cs | 5 +- .../System/Transactions/TransactionOptions.cs | 7 +- .../src/System/Web/Util/UriUtil.cs | 6 +- .../src/System.Windows.Extensions.csproj | 3 + .../ref/System.Xml.ReaderWriter.cs | 12 +- src/libraries/externals.csproj | 7 +- src/libraries/illink-oob.targets | 93 +- src/libraries/illink-sharedframework.targets | 58 +- src/libraries/shims/ApiCompat.proj | 85 +- .../ApiCompatBaseline.PreviousNetCoreApp.txt | 6 +- ...patBaseline.netcoreapp.netfx461.ignore.txt | 2709 ----- .../ApiCompatBaseline.netcoreapp.netfx461.txt | 614 -- .../ApiCompatBaseline.netfx.netstandard.txt | 102 - ...piCompatBaseline.netfx.netstandardOnly.txt | 870 -- src/libraries/tests.proj | 20 +- src/mono/CMakeLists.txt | 31 +- .../System.Private.CoreLib.csproj | 7 +- .../src/ILLink/ILLink.Descriptors.xml | 4 +- .../src/Mono/HotReload.cs | 114 + .../src/Mono/RuntimeHandles.cs | 6 +- .../src/System/Array.Mono.cs | 6 +- .../src/System/Math.Mono.cs | 6 - .../src/System/ModuleHandle.cs | 2 +- .../src/System/Nullable.Mono.cs | 2 + .../src/System/Reflection/Assembly.Mono.cs | 3 - .../System/Reflection/AssemblyName.Mono.cs | 66 - .../Reflection/Emit/AssemblyBuilder.Mono.cs | 21 +- .../Reflection/Emit/FieldBuilder.Mono.cs | 9 + .../Reflection/Emit/ILGenerator.Mono.cs | 3 - .../Reflection/Emit/ModuleBuilder.Mono.cs | 12 +- .../Reflection/Emit/TypeBuilder.Mono.cs | 39 +- .../Reflection/Metadata/MetadataUpdater.cs | 3 +- .../src/System/Reflection/RuntimeAssembly.cs | 29 +- .../src/System/Reflection/RuntimeModule.cs | 5 +- src/mono/cmake/configure.cmake | 28 +- src/mono/mono.proj | 16 +- src/mono/mono/arch/amd64/amd64-codegen.h | 10 +- src/mono/mono/arch/arm/arm-codegen.h | 2 +- src/mono/mono/arch/arm/arm-wmmx.h | 2 +- src/mono/mono/arch/mips/test.c | 2 +- src/mono/mono/arch/ppc/ppc-codegen.h | 24 +- src/mono/mono/arch/s390x/s390x-codegen.h | 48 +- src/mono/mono/arch/s390x/tramp.c | 115 +- src/mono/mono/arch/sparc/sparc-codegen.h | 10 +- src/mono/mono/arch/sparc/test.c | 4 +- src/mono/mono/arch/x86/x86-codegen.h | 42 +- src/mono/mono/component/CMakeLists.txt | 1 + src/mono/mono/component/debugger-agent.c | 23 + src/mono/mono/component/debugger-agent.h | 16 +- src/mono/mono/component/debugger-engine.c | 8 +- src/mono/mono/component/debugger-engine.h | 8 +- .../mono/component/debugger-mono-compat.h | 2 +- src/mono/mono/component/debugger-protocol.c | 4 +- src/mono/mono/component/debugger-protocol.h | 7 +- .../mono/component/debugger-state-machine.h | 2 +- src/mono/mono/component/debugger-stub.c | 14 +- src/mono/mono/component/debugger.c | 4 +- .../mono/component/hot_reload-internals.h | 53 + src/mono/mono/component/hot_reload-stub.c | 65 +- src/mono/mono/component/hot_reload.c | 679 +- src/mono/mono/component/hot_reload.h | 9 +- src/mono/mono/component/mini-wasm-debugger.c | 16 +- src/mono/mono/eglib/garray.c | 14 +- src/mono/mono/eglib/gdir-unix.c | 10 +- src/mono/mono/eglib/gdir-win32.c | 2 +- src/mono/mono/eglib/gerror.c | 10 +- src/mono/mono/eglib/gfile-posix.c | 5 + src/mono/mono/eglib/gfile-unix.c | 3 + src/mono/mono/eglib/gfile-win32.c | 4 +- src/mono/mono/eglib/gfile.c | 18 +- src/mono/mono/eglib/glist.c | 10 +- src/mono/mono/eglib/gmarkup.c | 48 +- src/mono/mono/eglib/gmem.c | 18 +- src/mono/mono/eglib/gmisc-unix.c | 6 +- src/mono/mono/eglib/gmisc-win32.c | 10 +- src/mono/mono/eglib/gmodule-unix.c | 18 +- src/mono/mono/eglib/goutput.c | 4 +- src/mono/mono/eglib/gpath.c | 46 +- src/mono/mono/eglib/gpattern.c | 2 +- src/mono/mono/eglib/gptrarray.c | 12 +- src/mono/mono/eglib/gqsort.c | 40 +- src/mono/mono/eglib/gqueue.c | 14 +- src/mono/mono/eglib/gshell.c | 20 +- src/mono/mono/eglib/gslist.c | 20 +- src/mono/mono/eglib/gspawn.c | 18 +- src/mono/mono/eglib/gstr.c | 94 +- src/mono/mono/eglib/gstring.c | 22 +- src/mono/mono/eglib/gunicode-win32.c | 2 +- src/mono/mono/eglib/gutf8.c | 74 +- src/mono/mono/eglib/sort.frag.h | 4 +- src/mono/mono/eglib/test/array.c | 4 +- src/mono/mono/eglib/test/assertf.c | 2 +- src/mono/mono/eglib/test/endian.c | 6 +- src/mono/mono/eglib/test/fake.c | 2 +- src/mono/mono/eglib/test/hashtable.c | 12 +- src/mono/mono/eglib/test/list.c | 36 +- src/mono/mono/eglib/test/markup.c | 16 +- src/mono/mono/eglib/test/path.c | 22 +- src/mono/mono/eglib/test/ptrarray.c | 48 +- src/mono/mono/eglib/test/queue.c | 4 +- src/mono/mono/eglib/test/shell.c | 8 +- src/mono/mono/eglib/test/sizes.c | 8 +- src/mono/mono/eglib/test/slist.c | 22 +- src/mono/mono/eglib/test/string-util.c | 78 +- src/mono/mono/eglib/test/string.c | 32 +- src/mono/mono/eglib/test/test.c | 36 +- src/mono/mono/eglib/test/test.h | 6 +- src/mono/mono/eglib/test/tests.h | 6 +- src/mono/mono/eventpipe/ep-rt-mono.c | 14 +- .../eventpipe/test/ep-fastserializer-tests.c | 2 +- src/mono/mono/metadata/appdomain.c | 20 +- .../mono/metadata/assembly-load-context.c | 6 +- src/mono/mono/metadata/assembly.c | 29 +- src/mono/mono/metadata/assembly.h | 14 +- src/mono/mono/metadata/attrdefs.h | 6 +- src/mono/mono/metadata/boehm-gc.c | 24 +- src/mono/mono/metadata/cil-coff.h | 2 +- src/mono/mono/metadata/class-accessors.c | 76 +- src/mono/mono/metadata/class-getters.h | 5 +- src/mono/mono/metadata/class-init.c | 180 +- src/mono/mono/metadata/class-inlines.h | 14 + src/mono/mono/metadata/class-internals.h | 38 +- .../mono/metadata/class-private-definition.h | 19 +- src/mono/mono/metadata/class-setup-vtable.c | 76 +- src/mono/mono/metadata/class.c | 45 +- src/mono/mono/metadata/class.h | 4 +- src/mono/mono/metadata/cominterop.c | 117 +- src/mono/mono/metadata/cominterop.h | 12 +- src/mono/mono/metadata/coree.c | 2 +- src/mono/mono/metadata/custom-attrs.c | 19 +- src/mono/mono/metadata/debug-helpers.c | 16 +- src/mono/mono/metadata/debug-mono-ppdb.h | 4 +- src/mono/mono/metadata/debug-mono-symfile.c | 8 +- src/mono/mono/metadata/domain-internals.h | 4 +- src/mono/mono/metadata/dynamic-image.c | 18 +- src/mono/mono/metadata/dynamic-stream.c | 12 +- src/mono/mono/metadata/exception.c | 12 +- src/mono/mono/metadata/exception.h | 8 +- src/mono/mono/metadata/external-only.c | 6 +- src/mono/mono/metadata/gc-internals.h | 18 +- src/mono/mono/metadata/gc.c | 30 +- src/mono/mono/metadata/handle.c | 4 +- src/mono/mono/metadata/handle.h | 2 +- src/mono/mono/metadata/icall-decl.h | 3 - src/mono/mono/metadata/icall-def-netcore.h | 7 +- src/mono/mono/metadata/icall.c | 69 - src/mono/mono/metadata/image.c | 104 +- src/mono/mono/metadata/image.h | 4 +- src/mono/mono/metadata/jit-info.c | 2 +- src/mono/mono/metadata/jit-info.h | 4 +- src/mono/mono/metadata/loaded-images.c | 2 +- src/mono/mono/metadata/loader-internals.h | 12 + src/mono/mono/metadata/loader.c | 48 +- src/mono/mono/metadata/loader.h | 2 +- src/mono/mono/metadata/lock-tracer.c | 6 +- src/mono/mono/metadata/marshal-ilgen.c | 411 +- src/mono/mono/metadata/marshal-noilgen.c | 6 + src/mono/mono/metadata/marshal.c | 224 +- src/mono/mono/metadata/marshal.h | 32 +- src/mono/mono/metadata/mempool-internals.h | 4 +- src/mono/mono/metadata/mempool.c | 2 +- src/mono/mono/metadata/metadata-internals.h | 31 +- src/mono/mono/metadata/metadata-update.c | 35 + src/mono/mono/metadata/metadata-update.h | 16 + src/mono/mono/metadata/metadata.c | 30 +- src/mono/mono/metadata/method-builder-ilgen.c | 4 +- src/mono/mono/metadata/method-builder.c | 6 +- src/mono/mono/metadata/method-builder.h | 2 +- src/mono/mono/metadata/monitor.c | 28 +- src/mono/mono/metadata/mono-basic-block.c | 10 +- src/mono/mono/metadata/mono-conc-hash.c | 8 +- .../mono/metadata/mono-config-internals.h | 2 +- src/mono/mono/metadata/mono-config.c | 2 +- src/mono/mono/metadata/mono-debug.c | 6 +- src/mono/mono/metadata/mono-endian.c | 6 +- src/mono/mono/metadata/mono-hash-internals.h | 2 +- .../mono/metadata/mono-private-unstable.h | 2 +- src/mono/mono/metadata/native-library.c | 12 +- src/mono/mono/metadata/null-gc-handles.c | 14 +- src/mono/mono/metadata/null-gc.c | 2 +- src/mono/mono/metadata/object-internals.h | 37 +- src/mono/mono/metadata/object.c | 13 +- src/mono/mono/metadata/object.h | 8 +- src/mono/mono/metadata/property-bag.c | 2 +- src/mono/mono/metadata/reflection.c | 70 +- src/mono/mono/metadata/reflection.h | 2 +- src/mono/mono/metadata/row-indexes.h | 2 +- src/mono/mono/metadata/runtime.c | 2 +- src/mono/mono/metadata/seq-points-data.c | 2 +- src/mono/mono/metadata/seq-points-data.h | 4 +- src/mono/mono/metadata/sgen-bridge.h | 4 +- src/mono/mono/metadata/sgen-client-mono.h | 2 +- src/mono/mono/metadata/sgen-mono-ilgen.c | 4 +- src/mono/mono/metadata/sgen-old-bridge.c | 6 +- src/mono/mono/metadata/sgen-tarjan-bridge.c | 2 +- src/mono/mono/metadata/sgen-toggleref.h | 2 +- src/mono/mono/metadata/sre-encode.c | 12 +- src/mono/mono/metadata/sre-internals.h | 2 +- src/mono/mono/metadata/sre.c | 109 +- src/mono/mono/metadata/sysmath.c | 50 +- src/mono/mono/metadata/tabledefs.h | 6 +- src/mono/mono/metadata/threads.c | 3 + src/mono/mono/metadata/tokentype.h | 4 +- src/mono/mono/metadata/verify.h | 2 +- src/mono/mono/metadata/w32file-unix.c | 56 +- src/mono/mono/metadata/w32handle.h | 2 +- src/mono/mono/mini/CMakeLists.txt | 2 +- src/mono/mono/mini/abcremoval.c | 94 +- src/mono/mono/mini/abcremoval.h | 4 +- src/mono/mono/mini/alias-analysis.c | 10 +- src/mono/mono/mini/aot-compiler.c | 5 + src/mono/mono/mini/aot-runtime.c | 106 +- src/mono/mono/mini/aot-runtime.h | 2 +- src/mono/mono/mini/arch-stubs.c | 2 +- src/mono/mono/mini/branch-opts.c | 122 +- src/mono/mono/mini/calls.c | 22 +- src/mono/mono/mini/cfold.c | 18 +- src/mono/mono/mini/debug-mini.c | 20 +- src/mono/mono/mini/debugger-agent-external.c | 2 +- src/mono/mono/mini/decompose.c | 42 +- src/mono/mono/mini/dominators.c | 34 +- src/mono/mono/mini/exceptions-arm.c | 54 +- src/mono/mono/mini/exceptions-arm64.c | 16 +- src/mono/mono/mini/exceptions-mips.c | 48 +- src/mono/mono/mini/exceptions-ppc.c | 124 +- src/mono/mono/mini/exceptions-s390x.c | 50 +- src/mono/mono/mini/exceptions-sparc.c | 34 +- src/mono/mono/mini/exceptions-wasm.c | 4 +- src/mono/mono/mini/exceptions-x86.c | 58 +- src/mono/mono/mini/graph.c | 24 +- src/mono/mono/mini/helpers.c | 18 +- src/mono/mono/mini/interp/interp-internals.h | 9 +- src/mono/mono/mini/interp/interp.c | 409 +- src/mono/mono/mini/interp/mintops.def | 2 - src/mono/mono/mini/interp/transform.c | 74 +- src/mono/mono/mini/intrinsics.c | 63 +- src/mono/mono/mini/ir-emit.h | 20 +- src/mono/mono/mini/jit.h | 10 +- src/mono/mono/mini/liveness.c | 76 +- src/mono/mono/mini/llvm-runtime.h | 2 +- src/mono/mono/mini/llvmonly-runtime.c | 4 +- src/mono/mono/mini/local-propagation.c | 38 +- src/mono/mono/mini/main-core.c | 8 +- src/mono/mono/mini/main.c | 10 +- src/mono/mono/mini/memory-access.c | 4 +- src/mono/mono/mini/method-to-ir.c | 304 +- src/mono/mono/mini/mini-amd64-gsharedvt.c | 4 +- src/mono/mono/mini/mini-amd64.c | 210 +- src/mono/mono/mini/mini-arch.h | 2 +- src/mono/mono/mini/mini-arm.c | 162 +- src/mono/mono/mini/mini-arm.h | 4 +- src/mono/mono/mini/mini-arm64.c | 26 +- src/mono/mono/mini/mini-arm64.h | 2 +- src/mono/mono/mini/mini-codegen.c | 122 +- src/mono/mono/mini/mini-cross-helpers.c | 2 +- src/mono/mono/mini/mini-exceptions.c | 52 +- src/mono/mono/mini/mini-gc.c | 42 +- src/mono/mono/mini/mini-generic-sharing.c | 2 +- src/mono/mono/mini/mini-llvm-cpp.h | 12 +- src/mono/mono/mini/mini-llvm.c | 7 +- src/mono/mono/mini/mini-mips.c | 110 +- src/mono/mono/mini/mini-mips.h | 4 +- src/mono/mono/mini/mini-native-types.c | 8 + src/mono/mono/mini/mini-ops.h | 6 +- src/mono/mono/mini/mini-posix.c | 12 +- src/mono/mono/mini/mini-ppc.c | 176 +- src/mono/mono/mini/mini-ppc.h | 6 +- src/mono/mono/mini/mini-profiler.c | 2 +- src/mono/mono/mini/mini-runtime.c | 26 +- src/mono/mono/mini/mini-runtime.h | 4 +- src/mono/mono/mini/mini-s390x.c | 852 +- src/mono/mono/mini/mini-s390x.h | 6 +- src/mono/mono/mini/mini-sparc.c | 176 +- src/mono/mono/mini/mini-sparc.h | 4 +- src/mono/mono/mini/mini-trampolines.c | 28 +- src/mono/mono/mini/mini-unwind.h | 6 +- src/mono/mono/mini/mini-wasm.c | 30 +- src/mono/mono/mini/mini-wasm.h | 4 +- src/mono/mono/mini/mini-x86-gsharedvt.c | 2 +- src/mono/mono/mini/mini-x86.c | 236 +- src/mono/mono/mini/mini.c | 94 +- src/mono/mono/mini/mini.h | 78 +- src/mono/mono/mini/mono-private-unstable.h | 4 +- src/mono/mono/mini/monovm.c | 8 +- src/mono/mono/mini/regalloc.h | 4 +- src/mono/mono/mini/seq-points.c | 6 +- src/mono/mono/mini/seq-points.h | 2 +- src/mono/mono/mini/ssa.c | 60 +- src/mono/mono/mini/trace.h | 4 +- src/mono/mono/mini/tramp-amd64-gsharedvt.c | 4 +- src/mono/mono/mini/tramp-amd64.c | 12 +- src/mono/mono/mini/tramp-arm.c | 16 +- src/mono/mono/mini/tramp-arm64.c | 4 +- src/mono/mono/mini/tramp-mips.c | 12 +- src/mono/mono/mini/tramp-ppc.c | 18 +- src/mono/mono/mini/tramp-s390x.c | 164 +- src/mono/mono/mini/tramp-sparc.c | 8 +- src/mono/mono/mini/tramp-x86-gsharedvt.c | 2 +- src/mono/mono/mini/tramp-x86.c | 4 +- src/mono/mono/mini/type-checking.c | 16 +- src/mono/mono/mini/unwind.c | 16 +- src/mono/mono/profiler/CMakeLists.txt | 8 +- src/mono/mono/sgen/sgen-alloc.c | 12 +- src/mono/mono/sgen/sgen-cardtable.c | 4 +- src/mono/mono/sgen/sgen-conf.h | 2 +- src/mono/mono/sgen/sgen-descriptor.c | 4 +- src/mono/mono/sgen/sgen-descriptor.h | 2 +- src/mono/mono/sgen/sgen-fin-weak-hash.c | 6 +- src/mono/mono/sgen/sgen-gc.c | 14 +- src/mono/mono/sgen/sgen-gc.h | 6 +- src/mono/mono/sgen/sgen-gray.h | 10 +- src/mono/mono/sgen/sgen-hash-table.c | 4 +- .../sgen/sgen-marksweep-drain-gray-stack.h | 2 +- src/mono/mono/sgen/sgen-marksweep.c | 4 +- src/mono/mono/sgen/sgen-memory-governor.c | 2 +- src/mono/mono/sgen/sgen-minor-copy-object.h | 6 +- src/mono/mono/sgen/sgen-nursery-allocator.c | 10 +- src/mono/mono/sgen/sgen-pinning-stats.c | 2 +- src/mono/mono/sgen/sgen-pinning.c | 2 +- src/mono/mono/sgen/sgen-simple-nursery.c | 4 +- src/mono/mono/sgen/sgen-split-nursery.c | 2 +- src/mono/mono/tests/bug-gh-9507.cs | 3 +- .../tests/metadata-verifier/gen-md-tests.c | 38 +- src/mono/mono/utils/atomic.c | 118 +- src/mono/mono/utils/dlmalloc.c | 14 +- src/mono/mono/utils/dlmalloc.h | 6 +- src/mono/mono/utils/dtrace.h | 4 +- src/mono/mono/utils/freebsd-elf_common.h | 4 +- src/mono/mono/utils/gc_wrapper.h | 4 +- src/mono/mono/utils/lock-free-alloc.h | 4 +- src/mono/mono/utils/lock-free-queue.c | 4 +- src/mono/mono/utils/lock-free-queue.h | 4 +- src/mono/mono/utils/mach-support-arm.c | 2 +- src/mono/mono/utils/mach-support-x86.c | 2 +- src/mono/mono/utils/memcheck.h | 20 +- src/mono/mono/utils/memfuncs.c | 2 +- src/mono/mono/utils/mono-codeman.c | 20 +- src/mono/mono/utils/mono-conc-hashtable.c | 2 +- src/mono/mono/utils/mono-context.h | 12 +- src/mono/mono/utils/mono-counters.c | 6 +- src/mono/mono/utils/mono-counters.h | 4 +- src/mono/mono/utils/mono-dl-wasm.c | 7 + src/mono/mono/utils/mono-embed.c | 12 +- src/mono/mono/utils/mono-embed.h | 4 +- src/mono/mono/utils/mono-error-internals.h | 5 +- src/mono/mono/utils/mono-error.c | 12 +- src/mono/mono/utils/mono-error.h | 2 +- src/mono/mono/utils/mono-filemap.c | 4 +- src/mono/mono/utils/mono-flight-recorder.c | 4 +- src/mono/mono/utils/mono-hwcap-arm.c | 12 +- src/mono/mono/utils/mono-jemalloc.c | 2 +- src/mono/mono/utils/mono-jemalloc.h | 4 +- src/mono/mono/utils/mono-linked-list-set.c | 2 +- src/mono/mono/utils/mono-log-android.c | 2 +- src/mono/mono/utils/mono-log-common.c | 4 +- .../mono/utils/mono-log-flight-recorder.c | 8 +- src/mono/mono/utils/mono-log-posix.c | 8 +- src/mono/mono/utils/mono-log-windows.c | 4 +- src/mono/mono/utils/mono-logger-internals.h | 8 +- src/mono/mono/utils/mono-logger.c | 28 +- src/mono/mono/utils/mono-logger.h | 4 +- src/mono/mono/utils/mono-md5.c | 98 +- src/mono/mono/utils/mono-memory-model.h | 10 +- src/mono/mono/utils/mono-mmap-wasm.c | 7 + src/mono/mono/utils/mono-networkinterfaces.c | 6 +- src/mono/mono/utils/mono-path.c | 10 +- src/mono/mono/utils/mono-poll.c | 2 +- src/mono/mono/utils/mono-private-unstable.h | 2 +- src/mono/mono/utils/mono-property-hash.c | 4 +- src/mono/mono/utils/mono-publib.h | 2 +- src/mono/mono/utils/mono-rand.c | 4 +- src/mono/mono/utils/mono-sha1.c | 26 +- src/mono/mono/utils/mono-stack-unwinding.h | 6 +- src/mono/mono/utils/mono-stdlib.c | 2 +- src/mono/mono/utils/mono-stdlib.h | 4 + src/mono/mono/utils/mono-threads-aix.c | 2 +- src/mono/mono/utils/mono-threads-coop.c | 2 +- .../mono/utils/mono-threads-mach-helper.c | 4 +- .../mono/utils/mono-threads-state-machine.c | 4 +- src/mono/mono/utils/mono-threads-wasm.c | 19 +- src/mono/mono/utils/mono-threads.c | 5 + src/mono/mono/utils/mono-threads.h | 6 +- src/mono/mono/utils/mono-uri.c | 2 +- src/mono/mono/utils/mono-utility-thread.c | 4 +- src/mono/mono/utils/mono-value-hash.c | 16 +- src/mono/mono/utils/mono-value-hash.h | 4 +- src/mono/mono/utils/monobitset.c | 20 +- src/mono/mono/utils/monobitset.h | 2 +- src/mono/mono/utils/networking-fallback.c | 4 +- src/mono/mono/utils/networking-missing.c | 10 +- src/mono/mono/utils/networking-posix.c | 13 +- src/mono/mono/utils/strenc.c | 36 +- src/mono/mono/utils/valgrind.h | 54 +- src/mono/sample/wasm/wasm.mk | 15 +- src/mono/wasi/Makefile | 29 + src/mono/wasi/Makefile.variable | 8 + src/mono/wasi/README.md | 52 + src/mono/wasi/include/pthread.h | 230 + src/mono/wasi/include/setjmp.h | 2 + src/mono/wasi/mono-wasi-driver/driver.c | 624 ++ src/mono/wasi/mono-wasi-driver/driver.h | 25 + src/mono/wasi/mono-wasi-driver/stubs.c | 22 + .../wasi/mono-wasi-driver/synthetic-pthread.c | 62 + src/mono/wasi/sample/.gitignore | 1 + src/mono/wasi/sample/Directory.Build.props | 8 + src/mono/wasi/sample/SampleMakefile.variable | 18 + src/mono/wasi/sample/console/Makefile | 20 + .../sample/console/WasiConsoleApp/Program.cs | 16 + .../WasiConsoleApp/WasiConsoleApp.csproj | 9 + src/mono/wasi/sample/console/main.c | 21 + src/mono/wasm/build/README.md | 10 + .../debugger/BrowserDebugProxy/DebugStore.cs | 52 +- .../BrowserDebugProxy/DevToolsHelper.cs | 14 +- .../debugger/BrowserDebugProxy/MonoProxy.cs | 110 +- .../BrowserDebugProxy/MonoSDBHelper.cs | 56 +- .../DebuggerTestSuite/BreakpointTests.cs | 418 +- .../DebuggerTestSuite/DebuggerTestBase.cs | 77 +- .../debugger/DebuggerTestSuite/MiscTests.cs | 2 +- .../DebuggerTestSuite/SteppingTests.cs | 58 +- .../MethodBody1.cs | 13 +- .../MethodBody1_v1.cs | 9 +- .../MethodBody1_v2.cs | 14 +- .../tests/debugger-test/debugger-test.cs | 163 +- src/mono/wasm/runtime/cs-to-js.ts | 45 +- src/mono/wasm/runtime/cwraps.ts | 2 +- src/mono/wasm/runtime/debug.ts | 2 +- src/mono/wasm/runtime/dotnet.d.ts | 10 +- src/mono/wasm/runtime/driver.c | 25 +- src/mono/wasm/runtime/memory.ts | 46 +- src/mono/wasm/runtime/method-binding.ts | 4 +- src/mono/wasm/runtime/roots.ts | 96 +- src/mono/wasm/runtime/types.ts | 44 + src/mono/wasm/test-main.js | 21 + src/native/corehost/fxr/host_context.cpp | 4 +- .../corehost/fxr/standalone/CMakeLists.txt | 4 + src/native/corehost/hostmisc/utils.cpp | 2 + .../corehost/test/nativehost/CMakeLists.txt | 4 + src/native/eventpipe/ep-event-source.c | 2 + src/native/libs/Common/pal_utilities.h | 4 + src/native/libs/System.Native/entrypoints.c | 2 + src/native/libs/System.Native/pal_io.c | 17 +- src/native/libs/System.Native/pal_io.h | 7 + .../libs/System.Native/pal_networkchange.c | 15 + .../System.Native/pal_runtimeinformation.h | 3 +- src/native/libs/System.Native/pal_time.c | 15 + src/native/libs/System.Native/pal_time.h | 7 + .../opensslshim.h | 2 + .../pal_evp_pkey.c | 45 +- .../pal_evp_pkey.h | 8 +- .../WasmAppBuilder/PInvokeTableGenerator.cs | 2 + .../XUnitWrapperGenerator/OptionsHelper.cs | 2 +- .../XUnitWrapperGenerator.cs | 10 +- src/tests/Common/testenvironment.proj | 2 + src/tests/Common/tests.targets | 16 +- .../WebAssembly.Browser.HotReload.Test.csproj | 3 + ...Assembly.Browser.RuntimeConfig.Test.csproj | 3 + src/tests/GC/API/Frozen/Frozen.cs | 188 + src/tests/GC/API/Frozen/Frozen.csproj | 16 + src/tests/Interop/CMakeLists.txt | 1 + .../Interop/COM/ComWrappers/API/Program.cs | 5 +- .../DisabledRuntimeMarshalling/AutoLayout.cs | 54 + .../DisabledRuntimeMarshalling/CMakeLists.txt | 10 + .../DisabledRuntimeMarshallingNative.cpp | 64 + ...ing_Disabled_NativeAssemblyDisabled.csproj | 13 + ...ling_Disabled_NativeAssemblyEnabled.csproj | 13 + ...lling_Disabled_NativeTypeInAssembly.csproj | 11 + ...ng_Disabled_NativeTypeInAssembly_ro.csproj | 14 + ...eMarshalling_NativeAssemblyDisabled.csproj | 14 + .../FunctionPointers.cs | 29 + .../DisabledRuntimeMarshallingNative.cs | 153 + ...ledRuntimeMarshallingNative_Default.csproj | 10 + .../DisabledRuntimeMarshallingNative.cs | 190 + ...rshallingNative_DisabledMarshalling.csproj | 11 + .../Delegates.cs | 34 + .../PInvokes.cs | 151 + .../UnmanagedCallersOnly.cs | 23 + .../Delegates.cs | 35 + .../PInvokes.cs | 96 + .../UnmanagedCallersOnly.cs | 27 + .../RuntimeMarshallingDisabledAttribute.cs | 5 + .../ObjectiveCMarshalAPI/Program.cs | 3 +- src/tests/Interop/common/xplatform.h | 14 +- .../General/Shared/VectorDotTest.template | 10 +- .../General/Vector128/Dot.Byte.cs | 10 +- .../General/Vector128/Dot.Double.cs | 10 +- .../General/Vector128/Dot.Int16.cs | 10 +- .../General/Vector128/Dot.Int32.cs | 10 +- .../General/Vector128/Dot.Int64.cs | 10 +- .../General/Vector128/Dot.SByte.cs | 10 +- .../General/Vector128/Dot.Single.cs | 10 +- .../General/Vector128/Dot.UInt16.cs | 10 +- .../General/Vector128/Dot.UInt32.cs | 10 +- .../General/Vector128/Dot.UInt64.cs | 10 +- .../General/Vector256/Dot.Byte.cs | 10 +- .../General/Vector256/Dot.Double.cs | 10 +- .../General/Vector256/Dot.Int16.cs | 10 +- .../General/Vector256/Dot.Int32.cs | 10 +- .../General/Vector256/Dot.Int64.cs | 10 +- .../General/Vector256/Dot.SByte.cs | 10 +- .../General/Vector256/Dot.Single.cs | 10 +- .../General/Vector256/Dot.UInt16.cs | 10 +- .../General/Vector256/Dot.UInt32.cs | 10 +- .../General/Vector256/Dot.UInt64.cs | 10 +- .../General/Vector64/Dot.Byte.cs | 10 +- .../General/Vector64/Dot.Double.cs | 10 +- .../General/Vector64/Dot.Int16.cs | 10 +- .../General/Vector64/Dot.Int32.cs | 10 +- .../General/Vector64/Dot.Int64.cs | 10 +- .../General/Vector64/Dot.SByte.cs | 10 +- .../General/Vector64/Dot.Single.cs | 10 +- .../General/Vector64/Dot.UInt16.cs | 10 +- .../General/Vector64/Dot.UInt32.cs | 10 +- .../General/Vector64/Dot.UInt64.cs | 10 +- src/tests/JIT/Intrinsics/CreateSpan_il.il | 2 +- .../JIT/Methodical/eh/basics/emptyfinally.il | 2 +- .../eh/basics/tryfinallywith2endfinally.il | 2 +- .../tryfinallywith2reachableendfinally.il | 2 +- .../Methodical/eh/deadcode/deadcodeincatch.il | 2 +- .../eh/deadcode/deadoponerrorinfunclet.il | 2 +- .../eh/finallyexec/catchrettoinnertry.il | 2 +- .../nonlocalexittonestedsibling.il | 2 +- .../Methodical/eh/leaves/2branchesoutoftry.il | 2 +- .../eh/leaves/backwardleaveincatch.il | 2 +- .../eh/leaves/branchbackwardswithcatch.il | 2 +- .../eh/leaves/branchbackwardswithfinally.il | 2 +- .../eh/leaves/branchoutofnestedtryfinally.il | 2 +- .../eh/leaves/branchoutoftryfinally.il | 2 +- .../eh/leaves/forwardleaveincatch.il | 2 +- .../Methodical/eh/leaves/leaveinsameregion.il | 2 +- .../Methodical/eh/leaves/leaveintotrybody.il | 2 +- .../tryfinallyintrycatchwithleaveintotry.il | 2 +- .../eh/mixedhandler/catchfiltercatch.il | 2 +- .../eh/mixedhandler/filterfiltercatchcatch.il | 2 +- .../eh/rethrow/rethrowinfinallyinsidecatch.il | 2 +- .../flowgraph/bug619534/twoEndFinallys.il | 5 +- .../inlining/dev10_bug719093/variancesmall.il | 2 +- .../JIT/Methodical/nonvirtualcall/classic.il | 2 +- .../JIT/Methodical/nonvirtualcall/delegate.il | 2 +- .../JIT/Methodical/nonvirtualcall/generics.il | 2 +- .../Methodical/nonvirtualcall/generics2.il | 2 +- .../JIT/Methodical/nonvirtualcall/tailcall.il | 2 +- .../Methodical/nonvirtualcall/valuetype.il | 2 +- .../JIT/Methodical/xxblk/dynblk_order.il | 114 + .../Methodical/xxblk/dynblk_order_d.ilproj | 12 + .../Methodical/xxblk/dynblk_order_ro.ilproj | 13 + .../Regression/Dev11/dev11_4421/Dev11_4421.cs | 7 +- .../Dev11/dev11_4421/Dev11_4421.csproj | 1 - .../JitBlue/Runtime_33972/Runtime_33972.cs | 559 + .../Runtime_33972/Runtime_33972.csproj | 13 + .../JitBlue/Runtime_34587/Runtime_34587.cs | 2 +- .../JitBlue/Runtime_63942/Runtime_63942.cs | 13 + .../Runtime_63942/Runtime_63942.csproj | 21 + .../JitBlue/Runtime_64125/Runtime_64125.cs | 9215 +++++++++++++++++ .../Runtime_64125/Runtime_64125.csproj | 11 + .../JitBlue/Runtime_64125/Runtime_64125.tt | 113 + .../JitBlue/Runtime_64208/Runtime_64208.cs | 33 + .../Runtime_64208/Runtime_64208.csproj | 17 + .../DynBlkNullAssertions.cs | 42 + .../DynBlkNullAssertions.csproj | 13 + .../JIT/opt/IsKnownConstant/StringEquals.cs | 99 + .../opt/IsKnownConstant/StringEquals.csproj | 9 + .../JIT/opt/ValueNumbering/ExceptionSets.cs | 37 + .../opt/ValueNumbering/ExceptionSets.csproj | 13 + .../ExceptionSetsPropagation_Hwi.cs | 40 + .../ExceptionSetsPropagation_Hwi.csproj | 13 + .../ExceptionSetsPropagation_LclHeap.il | 75 + .../ExceptionSetsPropagation_LclHeap.ilproj | 13 + .../classloader/RefFields/InvalidCSharp.il | 137 + .../RefFields/InvalidCSharp.ilproj | 8 + .../Loader/classloader/RefFields/Validate.cs | 97 + .../classloader/RefFields/Validate.csproj | 12 + .../Regressions/empty/explicitStruct_empty.cs | 60 + .../empty/explicitStruct_empty.csproj | 5 + .../coreclr/GitHub_61104/test61104.cs | 12 + .../coreclr/GitHub_61104/test61104.csproj | 17 + .../coreclr/GitHub_62058/test62058.cs | 60 + .../coreclr/GitHub_62058/test62058.csproj | 9 + src/tests/ilverify/ILTests/ValueTypeTests.il | 13 + src/tests/issues.targets | 31 +- .../Preinitialization/Preinitialization.cs | 35 + .../profiler/native/gcprofiler/gcprofiler.cpp | 18 + .../profiler/native/gcprofiler/gcprofiler.h | 3 + 2436 files changed, 67334 insertions(+), 42999 deletions(-) create mode 100644 docs/pr-builds.md create mode 100644 docs/workflow/debugging/libraries/debugging-corelib.md mode change 100644 => 100755 eng/common/cross/arm/tizen-build-rootfs.sh mode change 100644 => 100755 eng/common/cross/arm/tizen-fetch.sh create mode 100644 eng/common/internal/NuGet.config delete mode 100644 eng/common/templates/post-build/channels/generic-internal-channel.yml delete mode 100644 eng/common/templates/post-build/channels/generic-public-channel.yml mode change 100644 => 100755 eng/formatting/format.sh rename eng/pipelines/{runtime-manual.yml => runtime-extra-platforms.yml} (59%) create mode 100644 eng/testing/default.rd.xml delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs delete mode 100644 src/coreclr/ToolBox/CMakeLists.txt delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs create mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs delete mode 100644 src/coreclr/pal/src/cruntime/path.cpp delete mode 100644 src/coreclr/pal/src/cruntime/wchartls.cpp delete mode 100644 src/coreclr/pal/src/include/pal/modulename.h delete mode 100644 src/coreclr/pal/src/loader/modulename.cpp delete mode 100644 src/coreclr/pal/src/memory/local.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp rename src/coreclr/{ToolBox => tools}/SOS/CMakeLists.txt (100%) rename src/coreclr/{ToolBox => tools}/SOS/DIALib/DIALib.il (100%) rename src/coreclr/{ToolBox => tools}/SOS/DIALib/DIALib.ilproj (100%) rename src/coreclr/{ToolBox => tools}/SOS/DacTableGen/DacTableGen.csproj (100%) rename src/coreclr/{ToolBox => tools}/SOS/DacTableGen/MapSymbolProvider.cs (100%) rename src/coreclr/{ToolBox => tools}/SOS/DacTableGen/cvconst.cs (100%) rename src/coreclr/{ToolBox => tools}/SOS/DacTableGen/diautil.cs (100%) rename src/coreclr/{ToolBox => tools}/SOS/DacTableGen/main.cs (100%) rename src/coreclr/{ToolBox => tools}/SOS/Directory.Build.props (100%) rename src/coreclr/{ToolBox => tools}/SOS/SOS_README.md (100%) create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md create mode 100644 src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs create mode 100644 src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd create mode 100644 src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs create mode 100644 src/coreclr/tools/aot/ILLink.Shared/README.md rename src/coreclr/{ToolBox => tools}/superpmi/.clang-format (100%) rename src/coreclr/{ToolBox => tools}/superpmi/CMakeLists.txt (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/CMakeLists.txt (96%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/commandline.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/commandline.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/mcs.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/mcs.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/removedup.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/removedup.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbasmdump.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbasmdump.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbconcat.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbconcat.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdump.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdump.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdumpmap.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdumpmap.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdumptoc.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbdumptoc.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbfracture.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbfracture.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbildump.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbildump.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbinteg.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbinteg.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbjitflags.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbjitflags.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbmerge.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbmerge.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbprintjiteeversion.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbprintjiteeversion.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbremovedup.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbremovedup.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbstat.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbstat.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbstrip.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbstrip.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbtoc.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/mcs/verbtoc.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/readme.md (99%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/agnostic.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/asmdumper.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/asmdumper.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/callutils.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/callutils.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/compileresult.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/compileresult.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/crlwmlist.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/errorhandling.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/errorhandling.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/hash.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/hash.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/icorjitcompilerimpl.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/icorjithostimpl.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/icorjitinfoimpl.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/lightweightmap.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/logging.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/logging.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/lwmlist.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/mclist.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/mclist.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontext.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontext.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontextiterator.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontextiterator.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontextreader.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/methodcontextreader.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/runtimedetails.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/simpletimer.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/simpletimer.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/spmidumphelper.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/spmidumphelper.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/spmirecordhelper.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/spmiutil.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/spmiutil.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/standardpch.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/tocfile.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/tocfile.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/typeutils.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shared/typeutils.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/CMakeLists.txt (95%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/icorjitcompiler.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/icorjitcompiler.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/icorjitinfo.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/icorjitinfo.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/jithost.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/jithost.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/superpmi-shim-collector.def (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-collector/superpmi-shim-collector.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/CMakeLists.txt (96%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/icorjitcompiler.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/icorjitcompiler.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/icorjitinfo.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/icorjitinfo.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/jithost.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/jithost.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/methodcallsummarizer.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/superpmi-shim-counter.def (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-counter/superpmi-shim-counter.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/CMakeLists.txt (96%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/icorjitcompiler.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/icorjitcompiler.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/icorjitinfo.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/icorjitinfo.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/jithost.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/jithost.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/superpmi-shim-simple.def (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi-shim-simple/superpmi-shim-simple.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/CMakeLists.txt (96%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/commandline.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/commandline.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/cycletimer.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/cycletimer.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/icorjitinfo.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/icorjitinfo.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jitdebugger.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jitdebugger.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jithost.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jithost.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jitinstance.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/jitinstance.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/methodstatsemitter.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/methodstatsemitter.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/metricssummary.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/metricssummary.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/neardiffer.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/neardiffer.h (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/parallelsuperpmi.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/superpmi.cpp (100%) rename src/coreclr/{ToolBox => tools}/superpmi/superpmi/superpmi.h (100%) delete mode 100644 src/coreclr/vm/assemblyname.cpp delete mode 100644 src/coreclr/vm/assemblyname.hpp rename src/coreclr/vm/{domainfile.cpp => domainassembly.cpp} (80%) rename src/coreclr/vm/{domainfile.h => domainassembly.h} (59%) delete mode 100644 src/coreclr/vm/domainfile.inl create mode 100644 src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props create mode 100644 src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props create mode 100644 src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj create mode 100644 src/installer/pkg/projects/nativeaot-packages.proj rename src/libraries/Common/src/Interop/Windows/User32/{Interop.PeekMessage.cs => Interop.GetMessage.cs} (77%) create mode 100644 src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs create mode 100644 src/libraries/Common/tests/System/Net/ManualChunkingStream.cs create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/.editorconfig create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs create mode 100644 src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs create mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs create mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs create mode 100644 src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs delete mode 100644 src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs delete mode 100644 src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs delete mode 100644 src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs delete mode 100644 src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs delete mode 100644 src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs delete mode 100644 src/libraries/System.Drawing.Common/tests/runtimeconfig.template.json create mode 100644 src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs delete mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs create mode 100644 src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netstandard.cs create mode 100644 src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.netcoreapp.cs create mode 100644 src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.netcoreapp.cs create mode 100644 src/libraries/System.IO.FileSystem/tests/RandomAccess/SetLength.cs create mode 100644 src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs create mode 100644 src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs create mode 100644 src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs create mode 100644 src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs create mode 100644 src/libraries/System.Net.Security/tests/UnitTests/MD4Tests.cs create mode 100644 src/libraries/System.Net.WebSockets.Client/tests/package-lock.json create mode 100644 src/libraries/System.Net.WebSockets.Client/tests/package.json create mode 100644 src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs rename src/{coreclr/nativeaot => libraries}/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs (98%) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DisableRuntimeMarshallingAttribute.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/CachedCompletedInt32Task.cs create mode 100644 src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderByRefs.cs delete mode 100644 src/libraries/System.Resources.Extensions/tests/runtimeconfig.template.json create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass_v1.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/deltascript.json create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField_v1.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/deltascript.json create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda_v1.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/deltascript.json delete mode 100644 src/libraries/System.Runtime.Serialization.Formatters/tests/runtimeconfig.template.json create mode 100644 src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttributeTests.cs create mode 100644 src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs create mode 100644 src/libraries/System.Runtime/tests/System/Diagnostics/UnreachableExceptionTests.cs create mode 100644 src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.Forwards.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/Helpers.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/KeyPropertyName.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/SymmetricImportExportExtensions.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/Resources/Strings.resx delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPkcs8.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.Key.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.cs delete mode 100644 src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.cs create mode 100644 src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.Forwards.cs delete mode 100644 src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs delete mode 100644 src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Helpers.cs delete mode 100644 src/libraries/System.Security.Cryptography.Csp/src/Resources/Strings.resx delete mode 100644 src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Unix.cs create mode 100644 src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.Forwards.cs delete mode 100644 src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.cs delete mode 100644 src/libraries/System.Security.Cryptography.OpenSsl/src/Resources/Strings.resx create mode 100644 src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml create mode 100644 src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.Forwards.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Helpers.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/CertificatePal.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/CertificatePal.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePal.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/FindPal.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.cs delete mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng/src/System/Security/Cryptography/AesCng.cs => System.Security.Cryptography/src/System/Security/Cryptography/AesCng.Windows.cs} (97%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/AesCryptoServiceProvider.cs (97%) rename src/libraries/{System.Security.Cryptography.Csp/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/BasicSymmetricCipherCsp.cs (90%) rename src/libraries/{System.Security.Cryptography.Cng/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/BasicSymmetricCipherNCrypt.cs (85%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Browser.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs (99%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs (94%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CapiHelper.Shared.cs (95%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs (97%) rename src/libraries/{System.Security.Cryptography.Csp/src/Internal/Cryptography/Unix/HashAlgorithmNames.cs => System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs} (76%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CapiHelper.Windows.cs (94%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Cng.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngAlgorithm.cs (95%) rename src/libraries/{System.Security.Cryptography.Cng/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/CngAlgorithmCore.cs (97%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngAlgorithmGroup.cs (93%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngExportPolicies.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngHelpers.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Create.cs (96%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Delete.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.EC.cs (98%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Exists.cs (92%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Export.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Import.cs (97%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Open.cs (91%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.OpenHandle.cs (97%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.Properties.cs (96%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.StandardProperties.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKey.cs (59%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyBlobFormat.cs (95%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyCreationOptions.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyCreationParameters.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyHandleOpenOptions.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyOpenOptions.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngKeyUsages.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngProperty.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngPropertyCollection.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngPropertyOptions.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngProvider.cs (93%) rename src/libraries/{System.Security.Cryptography.Cng/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/CngSymmetricAlgorithmCore.cs (91%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngUIPolicy.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/CngUIProtectionLevels.cs (100%) rename src/libraries/{System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Unix.cs => System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.NotSupported.cs} (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs (87%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CspParameters.cs (97%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/CspProviderFlags.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs (94%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs (99%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.OpenSsl.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.SecurityTransforms.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.Windows.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/DSACng.ImportExport.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/DSACng.Key.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs (98%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs (96%) rename src/libraries/{System.Security.Cryptography.OpenSsl => System.Security.Cryptography}/src/System/Security/Cryptography/DSAOpenSsl.cs (86%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAWrapper.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/ECCng.ImportExport.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/ECDiffieHellmanCng.Xml.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanKeyDerivationFunction.cs rename src/libraries/{System.Security.Cryptography.OpenSsl => System.Security.Cryptography}/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs (90%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanWrapper.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.SecurityTransforms.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.Windows.cs rename src/libraries/{System.Security.Cryptography.OpenSsl => System.Security.Cryptography}/src/System/Security/Cryptography/ECDsaOpenSsl.cs (90%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaWrapper.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/ECKeyXmlFormat.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.Apple.cs rename src/libraries/{System.Security.Cryptography.Cng/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/ICngSymmetricAlgorithm.cs (95%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/ICspAsymmetricAlgorithm.cs (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/KeyNumber.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHashProvider.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs (91%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSsl.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Unix.cs => System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.NotSupported.cs} (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs (98%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/PasswordDeriveBytes.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PinAndClear.cs rename src/libraries/{System.Security.Cryptography.Cng/src/Internal => System.Security.Cryptography/src/System/Security}/Cryptography/ProviderPropertyName.cs (83%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs (93%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs (98%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/RNGCryptoServiceProvider.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.OpenSsl.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.SecurityTransforms.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.Windows.cs rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/RSACng.ImportExport.cs (100%) rename src/libraries/{System.Security.Cryptography.Cng => System.Security.Cryptography}/src/System/Security/Cryptography/RSACng.Key.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs (95%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs (94%) rename src/libraries/{System.Security.Cryptography.OpenSsl => System.Security.Cryptography}/src/System/Security/Cryptography/RSAOpenSsl.cs (84%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAWrapper.cs rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs (100%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs (100%) rename src/libraries/{Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs => System.Security.Cryptography/src/System/Security/Cryptography/SafeEvpPKeyHandle.OpenSsl.cs} (77%) rename src/libraries/{System.Security.Cryptography.Cng/src/System/Security/Cryptography/TripleDESCng.cs => System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCng.Windows.cs} (97%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.NotSupported.cs rename src/libraries/{System.Security.Cryptography.Csp/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.cs => System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.Wrap.cs} (93%) rename src/libraries/{System.Security.Cryptography.Csp => System.Security.Cryptography}/src/System/Security/Cryptography/Utils.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/AndroidCertificatePal.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/AndroidPkcs12Reader.cs (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificateExporter.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificateExporter.iOS.cs} (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.ImportExport.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs} (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.ImportExport.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Keys.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.iOS.cs} (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Keys.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.macOS.cs} (80%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pem.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pem.iOS.cs} (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pkcs12.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs} (82%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Pkcs12.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.macOS.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/AppleCertificatePal.TempExportPal.cs (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/AppleCertificatePal.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12CertLoader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12CertLoader.iOS.cs} (84%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12Reader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.iOS.cs} (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ApplePkcs12Reader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.macOS.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/KeyUsageFlagsAsn.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/ReasonFlagsAsn.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.manual.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.manual.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.manual.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/CertCollectionLoader.cs (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/CertificateData.ManagedDecode.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/CertificateExtensionsCommon.cs (95%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Android.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Apple.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.NotSupported.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.OpenSsl.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.Import.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.PrivateKey.cs} (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs} (98%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/CertificatePolicy.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ChainPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs} (96%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.NotSupported.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs} (91%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.BuildChain.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.BuildChain.cs} (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.GetChainStatusInformation.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.GetChainStatusInformation.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.cs} (92%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.cs rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/ECDsaX509SignatureGenerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ErrorCode.cs (83%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/FindPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Android.cs} (79%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Apple.cs} (81%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.NotSupported.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.OpenSsl.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/FindPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Windows.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/FindPal.cs (60%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ICertificatePal.cs (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ICertificatePalCore.cs (83%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/IChainPal.cs (80%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/IExportPal.cs (75%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/IFindPal.cs (89%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ILoaderPal.cs (71%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/IStorePal.cs (80%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/IX509Pal.cs (93%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ManagedCertificateFinder.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/ManagedX509ExtensionProcessor.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/OpenFlags.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedDirectoryStoreProvider.cs} (91%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs} (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/OpenSslCertificateFinder.cs (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CrlCache.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslDirectoryBasedStoreProvider.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ExportProvider.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslExportProvider.cs} (90%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/OpenSslPkcs12Reader.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/PkcsFormatReader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs} (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/SingleCertLoader.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslSingleCertLoader.cs} (79%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/OpenSslX509CertificateReader.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/OpenSslX509ChainProcessor.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/OpenSslX509Encoder.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/Pkcs9ExtensionRequest.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/PublicKey.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/RSAPkcs1X509SignatureGenerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SafeLocalAllocHandle.cs} (93%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/StoreLocation.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/StoreName.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.AndroidKeyStore.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.AndroidKeyStore.cs} (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.ExportPal.cs} (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.LoaderPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.LoaderPal.cs} (91%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.TrustedStore.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.TrustedStore.cs} (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs} (86%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.NotSupported.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs} (75%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Export.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Export.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Import.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs} (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.cs} (94%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.AppleKeychainStore.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.AppleKeychainStore.cs} (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs} (86%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleKeychainStore.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleKeychainStore.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleTrustStore.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleTrustStore.cs} (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.ExportPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.ExportPal.cs} (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.LoaderPal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.LoaderPal.cs} (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs} (90%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainVerifier.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixChainVerifier.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/UnixExportProvider.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/UnixPkcs12Reader.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/UnsupportedDisallowedStore.cs (92%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Helpers.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsHelpers.cs} (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsInterop.crypt32.cs} (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Primitives.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsStructs.cs} (99%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DictionaryStringHelper.cs rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X500DistinguishedNameFlags.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/X500NameEncoder.ManagedDecode.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/X500NameEncoder.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X501Attribute.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs (91%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Chain.cs (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainElementCollection.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainElementEnumerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainPolicy.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainStatus.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainStatusFlags.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ChainTrustMode.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ContentType.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs (90%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Extension.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ExtensionCollection.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509ExtensionEnumerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509FindType.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509IncludeOption.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509KeyStorageFlags.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs (86%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509KeyUsageFlags.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509NameType.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/X509Pal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs} (96%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.ECKey.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.ECKey.cs} (88%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.X500Name.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.X500Name.cs} (86%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.NotSupported.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Pal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.OpenSsl.cs} (57%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.CustomExtensions.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.CustomExtensions.cs} (97%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.GetCertContentType.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.GetCertContentType.cs} (94%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.PublicKey.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs} (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.X500DistinguishedName.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.X500DistinguishedName.cs} (98%) create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.cs rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/X509Pal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs} (90%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs} (95%) rename src/libraries/{System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix => System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates}/X509Persistence.cs (89%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509RevocationFlag.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509RevocationMode.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509Store.cs (99%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs (98%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierHashAlgorithm.cs (100%) rename src/libraries/{System.Security.Cryptography.X509Certificates => System.Security.Cryptography}/src/System/Security/Cryptography/X509Certificates/X509VerificationFlags.cs (100%) create mode 100644 src/libraries/System.Security.Cryptography/tests/StreamHelpers.cs create mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultValueHolder.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs create mode 100644 src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Count.cs create mode 100644 src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNodeKind.cs create mode 100644 src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOpcode.cs create mode 100644 src/libraries/System.Text.RegularExpressions/tests/Regex.Count.Tests.cs delete mode 100644 src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.ignore.txt delete mode 100644 src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.txt delete mode 100644 src/libraries/shims/ApiCompatBaseline.netfx.netstandard.txt delete mode 100644 src/libraries/shims/ApiCompatBaseline.netfx.netstandardOnly.txt create mode 100644 src/mono/System.Private.CoreLib/src/Mono/HotReload.cs create mode 100644 src/mono/mono/component/hot_reload-internals.h create mode 100644 src/mono/wasi/Makefile create mode 100644 src/mono/wasi/Makefile.variable create mode 100644 src/mono/wasi/README.md create mode 100644 src/mono/wasi/include/pthread.h create mode 100644 src/mono/wasi/include/setjmp.h create mode 100644 src/mono/wasi/mono-wasi-driver/driver.c create mode 100644 src/mono/wasi/mono-wasi-driver/driver.h create mode 100644 src/mono/wasi/mono-wasi-driver/stubs.c create mode 100644 src/mono/wasi/mono-wasi-driver/synthetic-pthread.c create mode 100644 src/mono/wasi/sample/.gitignore create mode 100644 src/mono/wasi/sample/Directory.Build.props create mode 100644 src/mono/wasi/sample/SampleMakefile.variable create mode 100644 src/mono/wasi/sample/console/Makefile create mode 100644 src/mono/wasi/sample/console/WasiConsoleApp/Program.cs create mode 100644 src/mono/wasi/sample/console/WasiConsoleApp/WasiConsoleApp.csproj create mode 100644 src/mono/wasi/sample/console/main.c create mode 100644 src/tests/GC/API/Frozen/Frozen.cs create mode 100644 src/tests/GC/API/Frozen/Frozen.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/AutoLayout.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/CMakeLists.txt create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshallingNative.cpp create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyDisabled.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyEnabled.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly_ro.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_NativeAssemblyDisabled.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/FunctionPointers.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative_Default.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/Delegates.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/UnmanagedCallersOnly.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/Delegates.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/PInvokes.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/UnmanagedCallersOnly.cs create mode 100644 src/tests/Interop/DisabledRuntimeMarshalling/RuntimeMarshallingDisabledAttribute.cs create mode 100644 src/tests/JIT/Methodical/xxblk/dynblk_order.il create mode 100644 src/tests/JIT/Methodical/xxblk/dynblk_order_d.ilproj create mode 100644 src/tests/JIT/Methodical/xxblk/dynblk_order_ro.ilproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.csproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.csproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.tt create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.csproj create mode 100644 src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.cs create mode 100644 src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.csproj create mode 100644 src/tests/JIT/opt/IsKnownConstant/StringEquals.cs create mode 100644 src/tests/JIT/opt/IsKnownConstant/StringEquals.csproj create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSets.cs create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSets.csproj create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.cs create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.csproj create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.il create mode 100644 src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.ilproj create mode 100644 src/tests/Loader/classloader/RefFields/InvalidCSharp.il create mode 100644 src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj create mode 100644 src/tests/Loader/classloader/RefFields/Validate.cs create mode 100644 src/tests/Loader/classloader/RefFields/Validate.csproj create mode 100644 src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.cs create mode 100644 src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.csproj create mode 100644 src/tests/Regressions/coreclr/GitHub_61104/test61104.cs create mode 100644 src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj create mode 100644 src/tests/Regressions/coreclr/GitHub_62058/test62058.cs create mode 100644 src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 015825df43d7a..f6ec0a4e1da7e 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.22062.1", + "version": "1.0.0-prerelease.22074.1", "commands": [ "xharness" ] diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 31ff731b02911..2634a9528f1ee 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,3 +10,12 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ build-essential python curl git lldb-6.0 liblldb-6.0-dev \ libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev \ libssl-dev libnuma-dev libkrb5-dev zlib1g-dev ninja-build + +# Install V8 Engine +SHELL ["/bin/bash", "-c"] + +RUN curl -sSL "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/linux/chromium-v8/v8-linux64-rel-8.5.183.zip" -o ./v8.zip \ + && unzip ./v8.zip -d /usr/local/v8 \ + && echo $'#!/usr/bin/env bash\n\ +"/usr/local/v8/d8" --snapshot_blob="/usr/local/v8/snapshot_blob.bin" "$@"\n' > /usr/local/bin/v8 \ + && chmod +x /usr/local/bin/v8 \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 41e9c94c00dee..d7b5a8b0efb57 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "name": "C# (.NET)", "build": { "dockerfile": "Dockerfile", - "args": { + "args": { // Update 'VARIANT' to pick a .NET Core version: 2.1, 3.1, 5.0 "VARIANT": "5.0", } @@ -32,11 +32,22 @@ // Add the locally installed dotnet to the path to ensure that it is activated // This allows developers to just use 'dotnet build' on the command-line, and the local dotnet version will be used. + // Add the global tools dir to the PATH so that globally installed tools will work "remoteEnv": { - "PATH": "${containerWorkspaceFolder}/.dotnet:${containerEnv:PATH}", - "DOTNET_MULTILEVEL_LOOKUP": "0" + "PATH": "${containerWorkspaceFolder}/.dotnet:${containerWorkspaceFolder}/.dotnet-tools-global:${containerEnv:PATH}", + "DOTNET_MULTILEVEL_LOOKUP": "0", + // Path to provisioned Emscripten SDK, for rebuilding the wasm runtime + "EMSDK_PATH": "${containerWorkspaceFolder}/src/mono/wasm/emsdk", }, // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" + "remoteUser": "vscode", + + // Forward mono samples port + "forwardPorts": [8000], + "portsAttributes": { + "8000": { + "label": "mono wasm samples (8000)", + } + } } diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index faf7cb08d1afa..48850f5f00b71 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -7,5 +7,13 @@ set -e # restore libs tests so that the project is ready to be loaded by OmniSharp ./build.sh libs.tests -restore +# prebuild for WASM, so it is ready for wasm development +make -C src/mono/wasm provision-wasm +export EMSDK_PATH=$PWD/src/mono/wasm/emsdk +./build.sh mono+libs -os Browser -c release + +# install dotnet-serve for running wasm samples +./dotnet.sh tool install dotnet-serve --tool-path ./.dotnet-tools-global + # save the commit hash of the currently built assemblies, so developers know which version was built git rev-parse HEAD > ./artifacts/prebuild.sha diff --git a/.github/fabricbot.json b/.github/fabricbot.json index 72acfd8440a06..accae195f26ee 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -13,8 +13,7 @@ ], "mentionees": [ "dotnet/area-system-security", - "vcsjones", - "krwq" + "vcsjones" ] }, { @@ -33,8 +32,7 @@ "area-System.Linq.Parallel" ], "mentionees": [ - "dotnet/area-system-linq-parallel", - "tarekgh" + "dotnet/area-system-linq-parallel" ] }, { @@ -42,8 +40,7 @@ "area-System.Text.Encoding" ], "mentionees": [ - "dotnet/area-system-text-encoding", - "tarekgh" + "dotnet/area-system-text-encoding" ] }, { @@ -51,8 +48,7 @@ "area-System.Text.Encodings.Web" ], "mentionees": [ - "dotnet/area-system-text-encodings-web", - "tarekgh" + "dotnet/area-system-text-encodings-web" ] }, { @@ -175,8 +171,7 @@ "area-System.Buffers" ], "mentionees": [ - "dotnet/area-system-buffers", - "GrabYourPitchforks" + "dotnet/area-system-buffers" ] }, { @@ -377,8 +372,7 @@ "area-Extensions-FileSystem" ], "mentionees": [ - "dotnet/area-extensions-filesystem", - "maryamariyan" + "dotnet/area-extensions-filesystem" ] }, { @@ -776,8 +770,7 @@ "area-System.Resources" ], "mentionees": [ - "dotnet/area-system-resources", - "tarekgh" + "dotnet/area-system-resources" ] }, { @@ -996,7 +989,7 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "Replace `needs more info` label with `needs further triage` label when the author comments on an issue", + "taskName": "Replace `needs-author-action` label with `needs-further-triage` label when the author comments on an issue", "conditions": { "operator": "and", "operands": [ @@ -1017,7 +1010,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } }, { @@ -1030,13 +1023,13 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { "name": "removeLabel", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } } ], @@ -1052,7 +1045,7 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "Remove `no recent activity` label from issues when issue is modified", + "taskName": "Remove `no-recent-activity` label from issues when issue is modified", "conditions": { "operator": "and", "operands": [ @@ -1070,7 +1063,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1079,7 +1072,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1090,7 +1083,7 @@ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1107,14 +1100,14 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "Remove `no recent activity` label when an issue is commented on", + "taskName": "Remove `no-recent-activity` label when an issue is commented on", "conditions": { "operator": "and", "operands": [ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1123,7 +1116,7 @@ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1149,7 +1142,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1158,7 +1151,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1171,12 +1164,12 @@ "issues", "project_card" ], - "taskName": "Remove `no recent activity` label from PRs when modified", + "taskName": "Remove `no-recent-activity` label from PRs when modified", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1194,7 +1187,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1207,12 +1200,12 @@ "eventNames": [ "issue_comment" ], - "taskName": "Remove `no recent activity` label from PRs when commented on", + "taskName": "Remove `no-recent-activity` label from PRs when commented on", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1230,7 +1223,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1243,12 +1236,12 @@ "eventNames": [ "pull_request_review" ], - "taskName": "Remove `no recent activity` label from PRs when new review is added", + "taskName": "Remove `no-recent-activity` label from PRs when new review is added", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1345,7 +1338,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1359,7 +1352,7 @@ { "name": "addReply", "parameters": { - "comment": "This issue will now be closed since it had been marked `no recent activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days." + "comment": "This issue will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days." } }, { @@ -1375,7 +1368,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Close PRs with no recent activity", + "taskName": "Close PRs with no-recent-activity", "frequency": [ { "weekDay": 0, @@ -1460,7 +1453,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1474,7 +1467,7 @@ { "name": "addReply", "parameters": { - "comment": "This pull request will now be closed since it had been marked `no recent activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days." + "comment": "This pull request will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days." } }, { @@ -1490,7 +1483,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Add no recent activity label to issues", + "taskName": "Add no-recent-activity label to issues", "frequency": [ { "weekDay": 0, @@ -1575,7 +1568,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } }, { @@ -1587,7 +1580,7 @@ { "name": "noLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1595,13 +1588,13 @@ { "name": "addLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { "name": "addReply", "parameters": { - "comment": "This issue has been automatically marked `no recent activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no recent activity`." + "comment": "This issue has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`." } } ] @@ -1614,7 +1607,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Add no recent activity label to PRs", + "taskName": "Add no-recent-activity label to PRs", "frequency": [ { "weekDay": 0, @@ -1711,7 +1704,7 @@ { "name": "noLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1719,13 +1712,13 @@ { "name": "addLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { "name": "addReply", "parameters": { - "comment": "This pull request has been automatically marked `no recent activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no recent activity`." + "comment": "This pull request has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`." } } ] @@ -1742,7 +1735,7 @@ "inPrLabelText": "Status: In PR", "fixedLabelText": "Status: Fixed", "fixedLabelEnabled": false, - "label_inPr": "in pr" + "label_inPr": "in-pr" } }, { @@ -2239,7 +2232,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2267,7 +2260,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2280,7 +2273,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2502,7 +2495,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2524,7 +2517,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2543,7 +2536,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2625,7 +2618,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2928,7 +2921,7 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3006,7 +2999,7 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3130,7 +3123,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3152,7 +3145,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3171,7 +3164,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3258,7 +3251,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3280,7 +3273,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3299,7 +3292,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3369,7 +3362,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3398,7 +3391,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3837,7 +3830,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3989,7 +3982,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4018,7 +4011,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4029,7 +4022,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -4210,7 +4203,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -4317,7 +4310,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4350,7 +4343,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4369,7 +4362,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -5159,7 +5152,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5187,7 +5180,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5215,7 +5208,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5287,7 +5280,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5315,7 +5308,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5328,7 +5321,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -5383,7 +5376,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -5416,7 +5409,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } } ] @@ -5426,12 +5419,12 @@ "issues", "project_card" ], - "taskName": "Needs more info notification", + "taskName": "Needs-author-action notification", "actions": [ { "name": "addReply", "parameters": { - "comment": "This issue has been marked `needs more info` since it may be missing important information. Please refer to our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md#writing-a-good-bug-report) for tips on how to report issues effectively." + "comment": "This issue has been marked `needs-author-action` since it may be missing important information. Please refer to our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md#writing-a-good-bug-report) for tips on how to report issues effectively." } } ] @@ -5951,7 +5944,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } }, { @@ -6003,25 +5996,7 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.Collections" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Linq" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Text.Json" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Xml" + "label": "area-Meta" } } ] @@ -6032,7 +6007,7 @@ { "name": "isInProject", "parameters": { - "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs", + "projectName": "Area Pod: Eric / Jeff - PRs", "isOrgProject": true } } @@ -6046,12 +6021,12 @@ "issues", "project_card" ], - "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Add new PR to Board", + "taskName": "[Area Pod: Eric / Jeff - PRs] Add new PR to Board", "actions": [ { "name": "addToProject", "parameters": { - "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs", + "projectName": "Area Pod: Eric / Jeff - PRs", "columnName": "Needs Champion", "isOrgProject": true } @@ -6686,7 +6661,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } }, { @@ -6723,6 +6698,119 @@ ] } }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.CodeDom" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Configuration" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Emit" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Metadata" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Resources" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Runtime.CompilerServices" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Threading.Channels" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Threading.Tasks" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.DirectoryServices" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Jose / Steve - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Buyaa / Jose / Steve - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Jose / Steve - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, { "taskType": "trigger", "capabilityId": "IssueResponder", @@ -7257,7 +7345,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs more info" + "label": "needs-author-action" } }, { @@ -7294,6 +7382,77 @@ ] } }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Collections" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.Json" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Xml" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, { "taskType": "trigger", "capabilityId": "IssueResponder", @@ -7379,5 +7538,2436 @@ } ] } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Configuration" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Logging" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Options" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Primitives" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-DependencyModel" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Configuration" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Logging" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Options" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Primitives" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Add new issue to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Configuration" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Logging" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Options" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Primitives" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isCloseAndComment", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "write" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Needs Further Triage", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Configuration" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Logging" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Options" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Primitives" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Remove relabeled issues", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs more info" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Move to Triaged Column", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Configuration" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Logging" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Options" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Primitives" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Configuration" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Logging" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Options" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Primitives" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Activity" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Globalization" + } + } + ] + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Eric / Maryam / Tarek - PRs] Remove relabeled PRs", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Eric / Maryam / Tarek - PRs", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Add new issue to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isCloseAndComment", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "write" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Needs Further Triage", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Remove relabeled issues", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Move to Triaged Column", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - PRs] Remove relabeled PRs", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Add new issue to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isCloseAndComment", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "write" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Needs Further Triage", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Remove relabeled issues", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Move to Triaged Column", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - PRs] Remove relabeled PRs", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + } } ] \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6627d2c2d0a75..a4848da2e9ca5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ syntax: glob # instead of directories), git will still ignore them. .dotnet .dotnet-mono +.dotnet-tools-global .packages .tools diff --git a/Directory.Build.props b/Directory.Build.props index e9e6fc4e36234..d862ee091fe81 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -29,6 +29,7 @@ <_hostArch>$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant) $(_hostArch) arm + armv6 armel arm64 loongarch64 diff --git a/NuGet.config b/NuGet.config index f74e0c4a70248..01da668976261 100644 --- a/NuGet.config +++ b/NuGet.config @@ -15,6 +15,7 @@ + diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index e38f6ef907d43..55329a8b02294 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -697,6 +697,35 @@ License for fastmod (https://github.com/lemire/fastmod) and ibm-fpgen (https://g See the License for the specific language governing permissions and limitations under the License. +License for sse4-strstr (https://github.com/WojciechMula/sse4-strstr) +-------------------------------------- + + Copyright (c) 2008-2016, Wojciech Muła + 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. + + 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. + License notice for The C++ REST SDK ----------------------------------- diff --git a/docs/coding-guidelines/libraries-packaging.md b/docs/coding-guidelines/libraries-packaging.md index 9e07a0683fd8d..66909e4df855c 100644 --- a/docs/coding-guidelines/libraries-packaging.md +++ b/docs/coding-guidelines/libraries-packaging.md @@ -86,5 +86,12 @@ In the analyzer project make sure to do the following. Ensure it only targets `n ``` +In order to mitigate design-time/build-time performance issues with source generators, we generate build logic to allow the end user to disable the source generator from the package. By default, the MSBuild property an end user can set is named `Disable{PackageId}SourceGenerator`. If a package needs a custom property name, this can be overriden by setting the following property in the project that produces the package +```xml + + CustomPropertyName + +``` + ### .NETFramework RID specific assets When targeting .NETFramework, RID specific assets are automatically added to the package if the project contains other compatible RID specific assets, mainly `netstandard2.0-windows`. diff --git a/docs/design/features/standalone-gc-loading.md b/docs/design/features/standalone-gc-loading.md index 3373bf5559f55..ed7440002e8da 100644 --- a/docs/design/features/standalone-gc-loading.md +++ b/docs/design/features/standalone-gc-loading.md @@ -47,7 +47,7 @@ Worth noting is that the JIT (both RyuJIT and the legacy JIT(s) before it) can b and have realized these same benefits. The existence of an interface and an implementation loadable from shared libraries has enabled RyuJIT in particular to be used as the code generator for both the CoreRT compiler and crossgen, while still being flexible enough to be tested using tools that implement -very non-standard execution engines such as [SuperPMI](https://github.com/dotnet/runtime/blob/main/src/coreclr/ToolBox/superpmi/readme.txt). +very non-standard execution engines such as [SuperPMI](https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/superpmi/readme.md). The below loading protocol is inspired directly by the JIT loader and many aspects of the GC loader are identical to what the JIT does when loading dynamic shared libraries. diff --git a/docs/design/libraries/DllImportGenerator/StructMarshalling.md b/docs/design/libraries/DllImportGenerator/StructMarshalling.md index ab332616b7413..63781d6d77dbb 100644 --- a/docs/design/libraries/DllImportGenerator/StructMarshalling.md +++ b/docs/design/libraries/DllImportGenerator/StructMarshalling.md @@ -6,10 +6,11 @@ These types pose an interesting problem for a number of reasons listed below. Wi ## Problems -- Unmanaged vs Blittable - - The C# language (and Roslyn) do not have a concept of "blittable types". It only has the concept of "unmanaged types", which is similar to blittable, but differs for `bool`s and `char`s. `bool` and `char` types are "unmanaged", but are never (in the case of `bool`), or only sometimes (in the case of `char`) blittable. As a result, we cannot use the "is this type unmanaged" check in Roslyn for structures. +- What types require marshalling and what types can be passed as-is to native code? + - Unmanaged vs Blittable + - The C# language (and Roslyn) do not have a concept of "blittable types". It only has the concept of "unmanaged types", which is similar to blittable, but differs for `bool`s and `char`s. `bool` and `char` types are "unmanaged", but are never (in the case of `bool`), or only sometimes (in the case of `char`) blittable. As a result, we cannot use the "is this type unmanaged" check in Roslyn for structures without an additional mechanism provided by the runtime. - Limited type information in ref assemblies. - - In the ref assemblies generated by dotnet/runtime, we save space and prevent users from relying on private implementation details of structures by emitting limited information about their fields. Structures that have at least one non-object field are given a private `int` field, and structures that have at least one field that transitively contains an object are given one private `object`-typed field. As a result, we do not have full type information at code-generation time for any structures defined in the BCL when compiling a library that uses the ref assemblies. + - In the ref assemblies generated by dotnet/arcade's GenAPI (used in dotnet/runtime), we save space and prevent users from relying on private implementation details of structures by emitting limited information about their fields. Structures that have at least one non-object field are given a private `int` field, and structures that have at least one field that transitively contains an object are given one private `object`-typed field. As a result, we do not have full type information at code-generation time for any structures defined in the BCL when compiling a library that uses the ref assemblies. - Private reflection - Even when we do have information about all of the fields, we can't emit code that references them if they are private, so we would have to emit unsafe code and calculate offsets manually to support marshaling them. @@ -19,16 +20,13 @@ We've been working around another problem for a while in the runtime-integrated I propose an opt-in design where the owner of a struct has to explicitly opt-in to usage for interop. This enables our team to add special support as desired for various types such as `Span` while also avoiding the private reflection and limited type information issues mentioned above. -This design would use these attributes: +All design options would use these attributes: ```csharp [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] public class GeneratedMarshallingAttribute : Attribute {} -[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] -public class BlittableTypeAttribute : Attribute {} - [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] public class NativeMarshallingAttribute : Attribute { @@ -42,7 +40,7 @@ public class MarshalUsingAttribute : Attribute } ``` -The `NativeMarshallingAttribute` and `MarshalUsingAttribute` attributes would require that the provided native type `TNative` is a blittable `struct` and has a subset of three methods with the following names and shapes (with the managed type named TManaged): +The `NativeMarshallingAttribute` and `MarshalUsingAttribute` attributes would require that the provided native type `TNative` is a `struct` that does not require any marshalling and has a subset of three methods with the following names and shapes (with the managed type named TManaged): ```csharp partial struct TNative @@ -59,7 +57,7 @@ The analyzer will report an error if neither the constructor nor the `ToManaged` > :question: Does this API surface and shape work for all marshalling scenarios we plan on supporting? It may have issues with the current "layout class" by-value `[Out]` parameter marshalling where the runtime updates a `class` typed object in place. We already recommend against using classes for interop for performance reasons and a struct value passed via `ref` or `out` with the same members would cover this scenario. -If the native type `TNative` also has a public `Value` property, then the value of the `Value` property will be passed to native code instead of the `TNative` value itself. As a result, the type `TNative` will be allowed to be non-blittable and the type of the `Value` property will be required to be blittable. If the `Value` property is settable, then when marshalling in the native-to-managed direction, a default value of `TNative` will have its `Value` property set to the native value. If `Value` does not have a setter, then marshalling from native to managed is not supported. +If the native type `TNative` also has a public `Value` property, then the value of the `Value` property will be passed to native code instead of the `TNative` value itself. As a result, the type `TNative` will be allowed to require marshalling and the type of the `Value` property will be required be passable to native code without any additional marshalling. If the `Value` property is settable, then when marshalling in the native-to-managed direction, a default value of `TNative` will have its `Value` property set to the native value. If `Value` does not have a setter, then marshalling from native to managed is not supported. If a `Value` property is provided, the developer may also provide a ref-returning or readonly-ref-returning `GetPinnableReference` method. The `GetPinnableReference` method will be called before the `Value` property getter is called. The ref returned by `GetPinnableReference` will be pinned with a `fixed` statement, but the pinned value will not be used (it acts exclusively as a side-effect). @@ -90,7 +88,7 @@ public struct TMarshaler #### Pinning -Since C# 7.3 added a feature to enable custom pinning logic for user types, we should also add support for custom pinning logic. If the user provides a `GetPinnableReference` method on the managed type that matches the requirements to be used in a `fixed` statement and the pointed-to type is blittable, then we will support using pinning to marshal the managed value when possible. The analyzer should issue a warning when the pointed-to type would not match the final native type, accounting for the `Value` property on the native type. Since `MarshalUsingAttribute` is applied at usage time instead of at type authoring time, we will not enable the pinning feature since the implementation of `GetPinnableReference` is likely designed to match the default marshalling rules provided by the type author, not the rules provided by the marshaller provided by the `MarshalUsingAttribute`. +Since C# 7.3 added a feature to enable custom pinning logic for user types, we should also add support for custom pinning logic. If the user provides a `GetPinnableReference` method on the managed type that matches the requirements to be used in a `fixed` statement and the pointed-to type would not require any additional marshalling, then we will support using pinning to marshal the managed value when possible. The analyzer should issue a warning when the pointed-to type would not match the final native type, accounting for the `Value` property on the native type. Since `MarshalUsingAttribute` is applied at usage time instead of at type authoring time, we will not enable the pinning feature since the implementation of `GetPinnableReference` is likely designed to match the default marshalling rules provided by the type author, not the rules provided by the marshaller provided by the `MarshalUsingAttribute`. #### Caller-allocated memory @@ -111,27 +109,18 @@ When these members are present, the source generator will call the two-parameter Type authors can pass down the `buffer` pointer to native code by defining a `Value` property that returns a pointer to the first element, generally through code using `MemoryMarshal.GetReference()` and `Unsafe.AsPointer`. If `RequiresStackBuffer` is not provided or set to `false`, 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. -### Usage - -There are 2 usage mechanisms of these attributes. - -#### Usage 1, Source-generated interop - -The user can apply the `GeneratedMarshallingAttribute` to their structure `S`. The source generator will determine if the type is blittable. If it is blittable, the source generator will generate a partial definition and apply the `BlittableTypeAttribute` to the struct type `S`. Otherwise, it will generate a blittable representation of the struct with the aformentioned required shape and apply the `NativeMarshallingAttribute` and point it to the blittable representation. The blittable representation can either be generated as a separate top-level type or as a nested type on `S`. +### Determining if a type is doesn't need marshalling -#### Usage 2, Manual interop - -The user may want to manually mark their types as marshalable in this system due to specific restrictions in their code base around marshaling specific types that the source generator does not account for. We could also use this internally to support custom types in source instead of in the code generator. In this scenario, the user would apply either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` attribute to their struct type. An analyzer would validate that the struct is blittable if the `BlittableTypeAttribute` is applied or validate that the native struct type is blittable and has marshalling methods of the required shape when the `NativeMarshallingAttribute` is applied. - -The P/Invoke source generator (as well as the struct source generator when nested struct types are used) would use the `BlittableTypeAttribute` and `NativeMarshallingAttribute` to determine how to marshal a value type parameter or field instead of looking at the fields of the struct directly. +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. -If a structure type does not have either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` applied at the type definition, the user can supply a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a native type matching the same requirements as `NativeMarshallingAttribute`'s native type. - -All generated stubs will be marked with [`SkipLocalsInitAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute) on supported frameworks. This does require attention when performing custom marshalling as the state of stub allocated memory will be in an undefined state. +#### Design 1: Introducing `BlittableTypeAttribute` -### Why do we need `BlittableTypeAttribute`? +Traditionally, the concept of "does not require marshalling" is referred to as "blittable". The built-in runtime marshalling system has an issue as mentioned above that the concept of `unmanaged` is not the same as the concept of `blittable`. Additionally, due to the ref assembly issue above, we cannot rely on ref assemblies to have accurate information in terms of fields of a type. To solve these issues in combination with the desire to enable manual interop, we need to provide a way for users to signal that a given type should be blittable and that the source generator should not generate marshalling code. We'll introduce a new attribute, the `BlittableTypeAttribute`: -Based on the design above, it seems that we wouldn't need `BlittableTypeAttribute`. However, due to the ref assembly issue above in combination with the desire to enable manual interop, we need to provide a way for users to signal that a given type should be blittable and that the source generator should not generate marshalling code. +```csharp +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +public class BlittableTypeAttribute : Attribute {} +``` I'll give a specific example for where we need the `BlittableTypeAttribute` below. Let's take a scenario where we don't have `BlittableTypeAttribute`. @@ -210,7 +199,7 @@ When the source generator (either Struct, P/Invoke, Reverse P/Invoke, etc.) enco If someone actively disables the analyzer or writes their types in IL, then they have stepped out of the supported scenarios and marshalling code generated for their types may be inaccurate. -#### Exception: Generics +##### Exception: Generics Because the Roslyn compiler needs to be able to validate that there are not recursive struct definitions, reference assemblies have to contain a field of a type parameter type in the reference assembly if they do in the runtime assembly. As a result, we can inspect private generic fields reliably. @@ -221,6 +210,32 @@ To enable blittable generics support in this struct marshalling model, we extend Since all fields typed with non-parameterized types are validated to be blittable at type definition time, we know that they are all blittable at type usage time. So, we only need to validate that the generic fields are instantiated with blittable types. +#### Design 2: [`DisableRuntimeMarshallingAttribute`](https://github.com/dotnet/runtime/issues/60639) + +As an alternative design, we can use a different definition of "does not require marshalling". This design proposes changing the definition from "the runtime's definition of blittable" to "types considered `unmanaged` in C#". The `DisableRuntimeMarshallingAttribute` attribute helps us solve this problem. When applied to an assembly, this attribute causes the runtime to not do any marshalling for any types that are `unmanaged` types and do not have any auto-layout fields for all P/Invokes in the assembly; this includes when the types do not fit the runtime's definition of "blittable". This definition of "does not require marshalling" will work for all of our scenarios, with one issue listed below. + +For the auto-layout clause, we have one small issue; today, our ref-assemblies do not expose if a value type is marked as `[StructLayout(LayoutKind.Auto)]`, so we'd still have some cases where we might have runtime failures. However, we can update the tooling used in dotnet/runtime, GenAPI, to expose this information if we so desire. Once that case is handled, we have a mechanism that we can safely use to determine, at compile time, which types will not require marshalling. If we decide to not cover this case (as cases where users mark types as `LayoutKind.Auto` manually are exceptionally rare), we still have a solid design as Roslyn will automatically determine for us if a type is `unmanaged`, so we don't need to do any additional work. + +As `unmanaged` is a C# language concept, we can use Roslyn's APIs to determine if a type is `unmanaged` to determine if it does not require marshalling without needing to define any new attributes and reshape the ecosystem. However, to enable this work, the DllImportGenerator, as well as any other source generators that generate calls to native code using the interop team's infrastructure, will need to require that the user applies the `DisableRuntimeMarshallingAttribute` to their assembly when custom user-defined types are used. As we believe that users should be able to move over their assemblies to the new source-generated interop world as a whole assembly, we do not believe that this will cause any serious issues in adoption. To help support users in this case, the interop team will provide a code-fix that will generate the `DisableRuntimeMarshallingAttribute` for users when they use the source generator. + +### Usage + +There are 2 usage mechanisms of these attributes. + +#### Usage 1, Source-generated interop + +The user can apply the `GeneratedMarshallingAttribute` to their structure `S`. The source generator will determine if the type requires marshalling. If it does, it will generate a representation of the struct that does not require marshalling with the aformentioned required shape and apply the `NativeMarshallingAttribute` and point it to that new type. This generated representation can either be generated as a separate top-level type or as a nested type on `S`. + +#### Usage 2, Manual interop + +The user may want to manually mark their types as marshalable with custom marshalling rules in this system due to specific restrictions in their code base around marshaling specific types that the source generator does not account for. We could also use this internally to support custom types in source instead of in the code generator. In this scenario, the user would apply either the `NativeMarshallingAttribute` attribute to their struct type. An analyzer would validate that the native struct type does not require marshalling and has marshalling methods of the required shape when the `NativeMarshallingAttribute` is applied. + +The P/Invoke source generator (as well as the struct source generator when nested struct types are used) would use the `NativeMarshallingAttribute` to determine how to marshal a parameter or field with an unknown type. + +If a structure type does not meet the requirements to not require marshalling or does not have the `NativeMarshallingAttribute` applied at the type definition, the user can supply a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a native type matching the same requirements as `NativeMarshallingAttribute`'s native type. + +All generated stubs will be marked with [`SkipLocalsInitAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute) on supported frameworks. This does require attention when performing custom marshalling as the state of stub allocated memory will be in an undefined state. + ### Special case: Transparent Structures There has been discussion about Transparent Structures, structure types that are treated as their underlying types when passed to native code. The support for a `Value` property on a generated marshalling type supports the transparent struct support. For example, we could support strongly typed `HRESULT` returns with this model as shown below: @@ -250,7 +265,7 @@ struct HRESULT In this case, the underlying native type would actually be an `int`, but the user could use the strongly-typed `HResult` type as the public surface area. -> :question: Should we support transparent structures on manually annotated blittable types? If we do, we should do so in an opt-in manner to make it possible to have a `Value` property on the blittable type. +> :question: Should we support transparent structures on manually annotated types that wouldn't need marshalling otherwise? If we do, we should do so in an opt-in manner to make it possible to have a `Value` property on the type without assuming that it is for interop in all cases. #### Example: ComWrappers marshalling with Transparent Structures diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 1c52fedd4d84c..6e1900c1dc6bd 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -13,6 +13,7 @@ This is a list of additions and edits to be made in ECMA-335 specifications. It - [Static Interface Methods](#static-interface-methods) - [Covariant Return Types](#covariant-return-types) - [Unsigned data conversion with overflow detection](#unsigned-data-conversion-with-overflow-detection) +- [Rules for IL rewriters](#rules-for-il-rewriters) ## Signatures @@ -948,3 +949,12 @@ Conversions from floating-point numbers to integral values truncate the number t on the top of the stack is reinterpreted as an unsigned value before the conversion. Note that integer values of less than 4 bytes are extended to int32 (not native int) on the evaluation stack. + +## Rules for IL Rewriters + +There are apis such as `System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan(...)` which require that the PE file have a particular structure. In particular, that api requires that the associated RVA of a FieldDef which is used to create a span must be naturally aligned over the data type that `CreateSpan` is instantiated over. There are 2 major concerns. + +1. That the RVA be aligned when the PE file is constructed. This may be achieved by whatever means is most convenient for the compiler. +2. That in the presence of IL rewriters that the RVA remains aligned. This section descibes metadata which will be processed by IL rewriters in order to maintain the required alignment. + +In order to maintain alignment, if the field needs alignment to be preserved, the field must be of a type locally defined within the module which has a Pack (§II.10.7) value of the desired alignment. Unlike other uses of the .pack directive, in this circumstance the .pack specifies a minimum alignment. diff --git a/docs/design/specs/PortablePdb-Metadata.md b/docs/design/specs/PortablePdb-Metadata.md index 811af00510bea..c1d8e3c442066 100644 --- a/docs/design/specs/PortablePdb-Metadata.md +++ b/docs/design/specs/PortablePdb-Metadata.md @@ -64,6 +64,8 @@ There shall be no duplicate rows in the _Document_ table, based upon document na _Name_ shall not be nil. It can however encode an empty name string. +_Hash_ is the file content hashed using the specified _HashAlgorithm_. It is used to validate that a source file matches the one used by the compiler when compiling the source code. + The values for which field _Language_ has a defined meaning are listed in the following tables along with the corresponding interpretation: | _Language_ field value | language | diff --git a/docs/pr-builds.md b/docs/pr-builds.md new file mode 100644 index 0000000000000..f5f7555ae7e67 --- /dev/null +++ b/docs/pr-builds.md @@ -0,0 +1,94 @@ +## PR Builds +When submitting a PR to the `dotnet/runtime` repository various builds will run validation in many areas to ensure we keep productivity and quality high. + +The `dotnet/runtime` validation system can become overwhelming as we need to cover a lot of build scenarios and test in all the platforms that we support. In order to try to make this more reliable and spend the least amount of time testing what the PR changes need we have various pipelines, required and optional that are covered in this document. + +Most of the repository pipelines use a custom mechanism to evaluate paths based on the changes contained in the PR to try and build/test the least that we can without compromising quality. This is the initial step on every pipeline that depends on this infrastructure, called "Evalute Paths". In this step you can see the result of the evaluation for each subset of the repository. For more details on which subsets we have based on paths see [here](https://github.com/dotnet/runtime/blob/513fe2863ad5ec6dc453d223d4b60f787a0ffa78/eng/pipelines/common/evaluate-default-paths.yml). Also to understand how this mechanism works you can read this [comment](https://github.com/dotnet/runtime/blob/513fe2863ad5ec6dc453d223d4b60f787a0ffa78/eng/pipelines/evaluate-changed-paths.sh#L3-L12). + +### Runtime pipeline +This is the "main" pipeline for the runtime product. In this pipeline we include the most critical tests and platforms where we have enough test resources in order to deliver test results in a reasonable amount of time. The tests executed in this pipeline for runtime and libraries are considered innerloop, are the tests that are executed locally when one runs tests locally. + +For mobile platforms and wasm we run some smoke tests that aim to protect the quality of these platforms. We had to move to a smoke test approach given the hardware and time limitations that we encountered and contributors were affected by this with unstability and long wait times for their PRs to finish validation. + +### Runtime-dev-innerloop pipeline +This pipeline is also required, and its intent is to cover a developer innerloop scenarios that could be affected by any change, like running a specific build command or running tests inside Visual Studio, etc. + +### Dotnet-linker-tests +This is also a required pipeline. The purpose of this pipeline is to test that the libraries code is linker friendly. Meaning that when we trim our libraries using the ILLink, we don't have any trimming bugs, like a required method on a specific scenario is trimmed away by accident. + +### Runtime-staging +This pipeline runs on every change, however it behaves a little different than the other pipelines. This pipeline, will not fail if there are test failures, however it will fail if there is a timeout or a build failure. The reason why we fail on build failures is because we want to protect the developer innerloop (building the repository) for this platform. + +The tests will not fail because the intent of this platform is to stage new platforms where the test infrastructure is new and we need to test if we have enough capacity to include that new platform on the "main" runtime pipeline without causing flakiness. Once we analyze data and a platform is stable when running on PRs in this pipeline for at least a weak it can be promoted either to the `runtime-extra-platforms` pipeline or to the `runtime` pipeline. + +### Runtime-extra-platforms +This pipeline does not run by default as it is not required for a PR, but it runs twice a day, and it can also be invoked in specific PRs by commenting `/azp run runtime-extra-platforms`. However, this pipeline is still an important part of our testing. + +This pipeline runs innerloop tests on platforms where we don't have enough hardware capacity to run tests (mobile, browser) or on platforms where we believe tests should organically pass based on the coverage we have in the "main" runtime pipeline. For example, in the "main" pipeline we run tests on Ubuntu 21.10 but since we also support Ubuntu 18.04 which is an LTS release, we run tests on Ubuntu 18.04 of this pipeline just to make sure we have healthy tests on those platforms which we are releasing a product for. + +Another concrete scenario would be windows arm64 for libraries tests. Where we don't have enough hardware, but the JIT is the most important piece to test as that is what generates the native code to run on that platform, so we run JIT tests on arm64 in the "main" pipeline, but our libraries tests are only run on the `runtime-extra-platforms` pipeline. + +### Outerloop pipelines +We have various pipelines that their names contain `Outerloop` on them. These pipelines will not run by default on every PR, they can also be invoked using the `/azp run` comment and will run on a daily basis to analyze test results. + +These pipelines will run tests that take very long, that are not very stable (i.e some networking tests), or that modify machine state. Such tests are called `Outerloop` tests rather than `innerloop`. + +## Rerunning Validation + +Validation may fail for several reasons: + +### Option 1: You have a defect in your PR + +* Simply push the fix to your PR branch, and validation will start over. + +### Option 2: There is a flaky test that is not related to your PR + +* Your assumption should be that a failed test indicates a problem in your PR. (If we don't operate this way, chaos ensues.) If the test fails when run again, it is almost surely a failure caused by your PR. However, there are occasions where unrelated failures occur. Here's some ways to know: + * Perhaps you see the same failure in CI results for unrelated active PR's. + * It's a known issue listed in our [big tracking issue](https://github.com/dotnet/runtime/issues/702) or tagged `blocking-clean-ci` [(query here)](https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Ablocking-clean-ci+) + * It's otherwise beyond any reasonable doubt that your code changes could not have caused this. + * If the tests pass on rerun, that may suggest it's not related. +* In this situation, you want to re-run but not necessarily rebase on main. + * To rerun just the failed leg(s): + * Click on any leg. Navigate through the Azure DevOps UI, find the "..." button and choose "Retry failed legs" + * Or, on the GitHub Checks tab choose "re-run failed checks". This will not rebase your change. + * To rerun all validation: + * Add a comment `/azp run runtime` + * Or, click on "re-run all checks" in the GitHub Checks tab + * Or, simply close and reopen the PR. +* If you have established that it is an unrelated failure, please ensure we have an active issue for it. See the [unrelated failure](#what-to-do-if-you-determine-the-failure-is-unrelated) section below. +* Whoever merges the PR should be satisfied that the failure is unrelated, is not introduced by the change, and that we are appropriately tracking it. + +### Option 3: The state of the main branch HEAD is bad. + +* This is the very rare case where there was a build break in main, and you got unlucky. Hopefully the break has been fixed, and you want CI to rebase your change and rerun validation. +* To rebase and rerun all validation: + * Add a comment `/azp run runtime` + * Or, click on "re-run all checks" in the GitHub Checks tab + * Or, simply close and reopen the PR. + * Or, ammend your commit with `--amend --no-edit` and force push to your branch. + +### Additional information: + * You can list the available pipelines by adding a comment like `/azp list` or get the available commands by adding a comment like `azp help`. + * In the rare case the license/cla check fails to register a response, it can be rerun by issuing a GET request to `https://cla.dotnetfoundation.org/check/dotnet/runtime?pullRequest={pr_number}`. A successful response may be a redirect to `https://github.com`. + * Reach out to the infrastructure team for assistance on [Teams channel](https://teams.microsoft.com/l/channel/19%3ab27b36ecd10a46398da76b02f0411de7%40thread.skype/Infrastructure?groupId=014ca51d-be57-47fa-9628-a15efcc3c376&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) (for corpnet users) or on [Gitter](https://gitter.im/dotnet/community) in other cases. + +## What to do if you determine the failure is unrelated + +If you have determined the failure is definitely not caused by changes in your PR, please do this: + +* Search for an [existing issue](https://github.com/dotnet/runtime/issues). Usually the test method name or (if a crash/hang) the test assembly name are good search parameters. + * If there's an existing issue, add a comment with + * a) the link to the build + * b) the affected configuration (ie `net6.0-windows-Release-x64-Windows.81.Amd64.Open`) + * c) all console output including the error message and stack trace from the Azure DevOps tab (This is necessary as retention policies are in place that recycle old builds.) + * d) if there's a dump file (see Attachments tab in Azure DevOps) include that + * If the issue is already closed, reopen it and update the labels to reflect the current failure state. + * If there's no existing issue, create an issue with the same information listed above. + * Update the original pull request with a comment linking to the new or existing issue. +* In a follow-up Pull Request, disable the failing test(s) with the corresponding issue link tracking the disable. + * Update the tracking issue with the label `disabled-test`. + * For libraries tests add a [`[ActiveIssue(link)]`](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/Attributes/ActiveIssueAttribute.cs) attribute on the test method. You can narrow the disabling down to runtime variant, flavor, and platform. For an example see [File_AppendAllLinesAsync_Encoded](https://github.com/dotnet/runtime/blob/cf49643711ad8aa4685a8054286c1348cef6e1d8/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs#L74) + * For runtime tests found under `src/tests`, please edit [`issues.targets`](https://github.com/dotnet/runtime/blob/main/src/tests/issues.targets). There are several groups for different types of disable (mono vs. coreclr, different platforms, different scenarios). Add the folder containing the test and issue mimicking any of the samples in the file. + +There are plenty of possible bugs, e.g. race conditions, where a failure might highlight a real problem and it won't manifest again on a retry. Therefore these steps should be followed for every iteration of the PR build, e.g. before retrying/rebuilding. \ No newline at end of file diff --git a/docs/pr-guide.md b/docs/pr-guide.md index b250efd6e12dd..eb7dea7a01ba7 100644 --- a/docs/pr-guide.md +++ b/docs/pr-guide.md @@ -24,71 +24,10 @@ Anyone with write access can merge a pull request manually or by setting the [au * The PR has been approved by at least one reviewer and any other objections are addressed. * You can request another review from the original reviewer. -* The PR successfully builds and passes all tests in the Continuous Integration (CI) system. - * Depending on your change, you may need to re-run validation. See [rerunning validation](#rerunning-validation) below. +* The PR successfully builds and passes all tests in the Continuous Integration (CI) system. For more information please read to our [PR Builds](pr-builds.md) doc. Typically, PRs are merged as one commit. It creates a simpler history than a Merge Commit. "Special circumstances" are rare, and typically mean that there are a series of cleanly separated changes that will be too hard to understand if squashed together, or for some reason we want to preserve the ability to bisect them. -## Rerunning Validation - -Validation may fail for several reasons: - -### Option 1: You have a defect in your PR - -* Simply push the fix to your PR branch, and validation will start over. - -### Option 2: There is a flaky test that is not related to your PR - -* Your assumption should be that a failed test indicates a problem in your PR. (If we don't operate this way, chaos ensues.) If the test fails when run again, it is almost surely a failure caused by your PR. However, there are occasions where unrelated failures occur. Here's some ways to know: - * Perhaps you see the same failure in CI results for unrelated active PR's. - * It's a known issue listed in our [big tracking issue](https://github.com/dotnet/runtime/issues/702) or tagged `blocking-clean-ci` [(query here)](https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Ablocking-clean-ci+) - * Its otherwise beyond any reasonable doubt that your code changes could not have caused this. - * If the tests pass on rerun, that may suggest it's not related. -* In this situation, you want to re-run but not necessarily rebase on main. - * To rerun just the failed leg(s): - * Click on any leg. Navigate through the Azure DevOps UI, find the "..." button and choose "Retry failed legs" - * Or, on the GitHub Checks tab choose "re-run failed checks". This will not rebase your change. - * To rerun all validation: - * Add a comment `/azp run runtime` - * Or, click on "re-run all checks" in the GitHub Checks tab - * Or, simply close and reopen the PR. -* If you have established that it is an unrelated failure, please ensure we have an active issue for it. See the [unrelated failure](#what-to-do-if-you-determine-the-failure-is-unrelated) section below. -* Whoever merges the PR should be satisfied that the failure is unrelated, is not introduced by the change, and that we are appropriately tracking it. - -### Option 3: The state of the main branch HEAD is bad. - -* This is the very rare case where there was a build break in main, and you got unlucky. Hopefully the break has been fixed, and you want CI to rebase your change and rerun validation. -* To rebase and rerun all validation: - * Add a comment `/azp run runtime` - * Or, click on "re-run all checks" in the GitHub Checks tab - * Or, simply close and reopen the PR. - * Or, ammend your commit with `--amend --no-edit` and force push to your branch. - -### Additional information: - * You can list the available pipelines by adding a comment like `/azp list` or get the available commands by adding a comment like `azp help`. - * In the rare case the license/cla check fails to register a response, it can be rerun by issuing a GET request to `https://cla.dotnetfoundation.org/check/dotnet/runtime?pullRequest={pr_number}`. A successful response may be a redirect to `https://github.com`. - * Reach out to the infrastructure team for assistance on [Teams channel](https://teams.microsoft.com/l/channel/19%3ab27b36ecd10a46398da76b02f0411de7%40thread.skype/Infrastructure?groupId=014ca51d-be57-47fa-9628-a15efcc3c376&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) (for corpnet users) or on [Gitter](https://gitter.im/dotnet/community) in other cases. - -## What to do if you determine the failure is unrelated - -If you have determined the failure is definitely not caused by changes in your PR, please do this: - -* Search for an [existing issue](https://github.com/dotnet/runtime/issues). Usually the test method name or (if a crash/hang) the test assembly name are good search parameters. - * If there's an existing issue, add a comment with - * a) the link to the build - * b) the affected configuration (ie `net6.0-windows-Release-x64-Windows.81.Amd64.Open`) - * c) all console output including the error message and stack trace from the Azure DevOps tab (This is necessary as retention policies are in place that recycle old builds.) - * d) if there's a dump file (see Attachments tab in Azure DevOps) include that - * If the issue is already closed, reopen it and update the labels to reflect the current failure state. - * If there's no existing issue, create an issue with the same information listed above. - * Update the original pull request with a comment linking to the new or existing issue. -* In a follow-up Pull Request, disable the failing test(s) with the corresponding issue link tracking the disable. - * Update the tracking issue with the label `disabled-test`. - * For libraries tests add a [`[ActiveIssue(link)]`](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/Attributes/ActiveIssueAttribute.cs) attribute on the test method. You can narrow the disabling down to runtime variant, flavor, and platform. For an example see [File_AppendAllLinesAsync_Encoded](https://github.com/dotnet/runtime/blob/a259ec2e967d502f82163beba6b84da5319c5e08/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs#L899) - * For runtime tests found under `src/tests`, please edit [`issues.targets`](https://github.com/dotnet/runtime/blob/main/src/tests/issues.targets). There are several groups for different types of disable (mono vs. coreclr, different platforms, different scenarios). Add the folder containing the test and issue mimicking any of the samples in the file. - -There are plenty of possible bugs, e.g. race conditions, where a failure might highlight a real problem and it won't manifest again on a retry. Therefore these steps should be followed for every iteration of the PR build, e.g. before retrying/rebuilding. - ## Blocking Pull Request Merging If for whatever reason you would like to move your pull request back to an in-progress status to avoid merging it in the current form, you can do that by adding [WIP] prefix to the pull request title. diff --git a/docs/project/glossary.md b/docs/project/glossary.md index cb7e0b21538b8..28fed9e8e160d 100644 --- a/docs/project/glossary.md +++ b/docs/project/glossary.md @@ -43,7 +43,7 @@ terminology. | SDK | Software Development Kit. The [.NET SDK](https://docs.microsoft.com/dotnet/core/sdk) contains the .NET CLI, .NET libraries and runtime, and the dotnet driver. | | SEH | [Structured Exception Handling](https://docs.microsoft.com/windows/win32/debug/structured-exception-handling). Unified mechanism for handling hardware and software exceptions on Windows. | | SOS | [Son of Strike](https://docs.microsoft.com/archive/blogs/jasonz/sos-debugging-of-the-clr-part-1). The debugging extension for DbgEng based debuggers. Uses the DAC as an abstraction layer for its operation. | -| SuperPMI | JIT component test framework (super fast JIT testing - it mocks/replays EE in EE-JIT interface) - see [SuperPMI details](https://github.com/dotnet/runtime/blob/main/src/coreclr/ToolBox/superpmi/readme.txt). | +| SuperPMI | JIT component test framework (super fast JIT testing - it mocks/replays EE in EE-JIT interface) - see [SuperPMI details](https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/superpmi/readme.md). | | SVR | The CLR used to be built as two variants, with one called "mscorsvr.dll", to mean the "server" version. In particular, it contained the server GC implementation, which was intended for multi-threaded apps capable of taking advantage of multiple processors. In the .NET Framework 2 release, the two variants were merged into "mscorwks.dll". The WKS version was the default, however the SVR version remained available. | | TFM | [Target Framework Moniker](https://docs.microsoft.com/dotnet/standard/frameworks) such as `net6.0` or `netstandard2.0`. | | TPA | Trusted Platform Assemblies used to be a special set of assemblies that comprised the platform assemblies, when it was originally designed. As of today, it is simply the set of assemblies known to constitute the application. | @@ -187,8 +187,7 @@ by Mono runtime in environments that allow fallback to JIT or need IL interprete [Native AOT](https://github.com/dotnet/designs/blob/main/accepted/2020/form-factors.md#native-aot-form-factors) is a .NET runtime form factor with key performance characteristics (startup time, binary size and steady state throughput and predictability) -competitive with statically compiled languages. A .NET runtime flavor based on CoreCLR with these characteristics is being developed as -experimental project in [dotnet/runtimelab](https://github.com/dotnet/runtimelab/tree/feature/NativeAOT) repo. +competitive with statically compiled languages. ## Frameworks diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md index 968bb5fa89243..3206fc7349c20 100644 --- a/docs/workflow/building/coreclr/nativeaot.md +++ b/docs/workflow/building/coreclr/nativeaot.md @@ -21,7 +21,7 @@ The executable looks like a native executable, in the sense that it can be debug ## Building - [Install pre-requisites](../../README.md#build-requirements) -- Run `build[.cmd|.sh] clr+libs -rc [Debug|Release] -lc Release` from the repo root. This will restore nuget packages required for building and build the parts of the repo required for general CoreCLR development. Alternatively, instead of specifying `clr+libs`, you can specify `clr.jit+clr.tools+clr.nativeaotlibs+libs` which is more targeted and builds faster. Replace `clr.jit` with `clr.alljits` if you need to crosscompile. +- Run `build[.cmd|.sh] clr+libs -rc [Debug|Release] -lc Release` from the repo root. This will restore nuget packages required for building and build the parts of the repo required for general CoreCLR development. Alternatively, instead of specifying `clr+libs`, you can specify `clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs` which is more targeted and builds faster. Replace `clr.jit` with `clr.alljits` if you need to crosscompile. - [NOT PORTED OVER YET] The build will place the toolchain packages at `artifacts\packages\[Debug|Release]\Shipping`. To publish your project using these packages: - [NOT PORTED OVER YET] Add the package directory to your `nuget.config` file. For example, replace `dotnet-experimental` line in `samples\HelloWorld\nuget.config` with `` - [NOT PORTED OVER YET] Run `dotnet publish --packages pkg -r [win-x64|linux-x64|osx-64] -c [Debug|Release]` to publish your project. `--packages pkg` option restores the package into a local directory that is easy to cleanup once you are done. It avoids polluting the global nuget cache with your locally built dev package. diff --git a/docs/workflow/building/coreclr/osx-instructions.md b/docs/workflow/building/coreclr/osx-instructions.md index d8bf4fe604fcb..41e8d87de1a7e 100644 --- a/docs/workflow/building/coreclr/osx-instructions.md +++ b/docs/workflow/building/coreclr/osx-instructions.md @@ -1,49 +1,12 @@ -Build CoreCLR on OS X +Build CoreCLR on macOS ===================== -This guide will walk you through building CoreCLR on OS X. We'll start by showing how to set up your environment from scratch. +This guide will walk you through building CoreCLR on macOS. We'll start by showing how to set up your environment from scratch. Environment =========== -These instructions were validated on macOS 10.12. Sierra. On older versions coreFX will fail to build properly because of SSL API changes. - -If your machine has Command Line Tools for XCode 6.3 installed, you'll need to update them to the 6.3.1 version or higher in order to successfully build. There was an issue with the headers that shipped with version 6.3 that was subsequently fixed in 6.3.1. - -Git Setup ---------- - -Clone the CoreCLR and CoreFX repositories (either upstream or a fork). - -```sh -git clone https://github.com/dotnet/runtime -# Cloning into 'runtime'... -``` - -CMake ------ - -CoreCLR has a dependency on CMake for the build. You can install it with [Homebrew](https://brew.sh/). - -```sh -brew install cmake -``` - -ICU ---- -ICU (International Components for Unicode) is also required to build and run. It can be obtained via [Homebrew](https://brew.sh/). - -```sh -brew install icu4c -``` - -pkg-config ----------- -pkg-config is also required to build. It can be obtained via [Homebrew](https://brew.sh/). - -```sh -brew install pkg-config -``` +Ensure you have all of the prerequisites installed from the [macOS Requirements](/docs/workflow/requirements/macos-requirements.md). Build the Runtime and System.Private.CoreLib ============================================ diff --git a/docs/workflow/debugging/libraries/debugging-corelib.md b/docs/workflow/debugging/libraries/debugging-corelib.md new file mode 100644 index 0000000000000..9dd817d5bf7ff --- /dev/null +++ b/docs/workflow/debugging/libraries/debugging-corelib.md @@ -0,0 +1,7 @@ +Debugging System.Private.CoreLib +========================== + +`System.Console.Write`/`System.Console.WriteLine` cannot be used in `System.Private.CoreLib`. Instead, use `Internal.Console.Write` to add temporary logging for printf-style debugging. + +### Android +The logs can be found through the generated Android Debug Bridge log or viewed directly through ADB logcat. diff --git a/docs/workflow/debugging/mono/wasm-debugging.md b/docs/workflow/debugging/mono/wasm-debugging.md index cfc98c1be2dbd..4e7945ce515b6 100644 --- a/docs/workflow/debugging/mono/wasm-debugging.md +++ b/docs/workflow/debugging/mono/wasm-debugging.md @@ -2,7 +2,7 @@ WASM runtime debugging ====================== -- Disable symbol stripping by setting the `WasmNativeStrip` msbuild property to `false`. +- Disable symbol stripping by setting the `WasmNativeStrip` msbuild property to `false`. See also, [collecting stack traces with symbols in Blazor](#collecting-stack-traces-with-symbols-in-blazor) - Emscripten generates dwarf debug info and Chrome 80 and later can use it. @@ -133,3 +133,131 @@ These kinds of faults usually happen because the mono runtime has some helper fu never meant to be reached, i.e. `no_gsharedvt_in_wrapper` or `no_llvmonly_interp_method_pointer`. These functions are used as placeholders for function pointers with different signatures, so if they do end up being called due to a bug, a signature mismatch error happens. + +# Collecting stack traces with symbols in Blazor + +When debugging a native crash in a .NET 6 Blazor app or another WebAssembly +framework that uses our default `dotnet.wasm`, the native stack frames will not +have C symbol names, but will instead look like `$func1234`. + +For example this Razor page will crash when a user clicks on the `Crash` button + +```csharp + + +@code { + private void Crash () + { + IntPtr p = (IntPtr)0x01; + Console.WriteLine ("About to crash"); + System.Runtime.InteropServices.Marshal.FreeHGlobal(p); + } +} +``` + +Clicking on the `Crash` button will produce the following output in the console (the function indices may be different): + +```console +dotnet.wasm:0x1d8355 Uncaught (in promise) RuntimeError: memory access out of bounds + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm +$free @ dotnet.wasm:0x1d8355 +$func4027 @ dotnet.wasm:0xead6a +$func219 @ dotnet.wasm:0x1a03a +$func167 @ dotnet.wasm:0xcaf7 +$func166 @ dotnet.wasm:0xba0a +$func2810 @ dotnet.wasm:0xabacf +$func1615 @ dotnet.wasm:0x6f8eb +$func1613 @ dotnet.wasm:0x6f85d +$func966 @ dotnet.wasm:0x502dc +$func219 @ dotnet.wasm:0x1a0e2 +$func167 @ dotnet.wasm:0xcaf7 +$func166 @ dotnet.wasm:0xba0a +$func2810 @ dotnet.wasm:0xabacf +$func1615 @ dotnet.wasm:0x6f8eb +$func1619 @ dotnet.wasm:0x6ff58 +$mono_wasm_invoke_method @ dotnet.wasm:0x96c9 +Module._mono_wasm_invoke_method @ dotnet.6.0.1.hopd7ipo8x.js:1 +managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19 +beginInvokeDotNetFromJS @ blazor.webassembly.js:1 +b @ blazor.webassembly.js:1 +invokeMethodAsync @ blazor.webassembly.js:1 +(anonymous) @ blazor.webassembly.js:1 +invokeWhenHeapUnlocked @ blazor.webassembly.js:1 +S @ blazor.webassembly.js:1 +C @ blazor.webassembly.js:1 +dispatchGlobalEventToAllElements @ blazor.webassembly.js:1 +onGlobalEvent @ blazor.webassembly.js:1 +``` + +In order to get symbols, the user should: + +1. Install the `wasm-tools` workload using `dotnet workload install wasm-tools` +2. Set these additional properties in their `.csproj` file: + + ```xml + + + true + false + + ``` + +3. Delete the `bin` and `obj` folders, re-build the project and run it again. + +Now clicking on the `Crash` button will produce a stack trace with symbols: + +```console +dotnet.wasm:0x224878 Uncaught (in promise) RuntimeError: memory access out of bounds + at dlfree (dotnet.wasm:0x224878) + at SystemNative_Free (dotnet.wasm:0x20f0e2) + at do_icall (dotnet.wasm:0x190f9) + at do_icall_wrapper (dotnet.wasm:0x18429) + at interp_exec_method (dotnet.wasm:0xa56c) + at interp_runtime_invoke (dotnet.wasm:0x943a) + at mono_jit_runtime_invoke (dotnet.wasm:0x1dec32) + at do_runtime_invoke (dotnet.wasm:0x95fca) + at mono_runtime_invoke_checked (dotnet.wasm:0x95f57) + at mono_runtime_try_invoke_array (dotnet.wasm:0x9a87e) +$dlfree @ dotnet.wasm:0x224878 +$SystemNative_Free @ dotnet.wasm:0x20f0e2 +$do_icall @ dotnet.wasm:0x190f9 +$do_icall_wrapper @ dotnet.wasm:0x18429 +$interp_exec_method @ dotnet.wasm:0xa56c +$interp_runtime_invoke @ dotnet.wasm:0x943a +$mono_jit_runtime_invoke @ dotnet.wasm:0x1dec32 +$do_runtime_invoke @ dotnet.wasm:0x95fca +$mono_runtime_invoke_checked @ dotnet.wasm:0x95f57 +$mono_runtime_try_invoke_array @ dotnet.wasm:0x9a87e +$mono_runtime_invoke_array_checked @ dotnet.wasm:0x9af17 +$ves_icall_InternalInvoke @ dotnet.wasm:0x702ed +$ves_icall_InternalInvoke_raw @ dotnet.wasm:0x7777f +$do_icall @ dotnet.wasm:0x191c5 +$do_icall_wrapper @ dotnet.wasm:0x18429 +$interp_exec_method @ dotnet.wasm:0xa56c +$interp_runtime_invoke @ dotnet.wasm:0x943a +$mono_jit_runtime_invoke @ dotnet.wasm:0x1dec32 +$do_runtime_invoke @ dotnet.wasm:0x95fca +$mono_runtime_try_invoke @ dotnet.wasm:0x966fe +$mono_runtime_invoke @ dotnet.wasm:0x98982 +$mono_wasm_invoke_method @ dotnet.wasm:0x227de2 +Module._mono_wasm_invoke_method @ dotnet..y6ggkhlo8e.js:9927 +managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19 +beginInvokeDotNetFromJS @ blazor.webassembly.js:1 +b @ blazor.webassembly.js:1 +invokeMethodAsync @ blazor.webassembly.js:1 +(anonymous) @ blazor.webassembly.js:1 +invokeWhenHeapUnlocked @ blazor.webassembly.js:1 +S @ blazor.webassembly.js:1 +C @ blazor.webassembly.js:1 +dispatchGlobalEventToAllElements @ blazor.webassembly.js:1 +onGlobalEvent @ blazor.webassembly.js:1 +``` diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index 0fc9bf8e5a7ee..e5ae41903b5a7 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -152,10 +152,10 @@ dotnet_diagnostic.CA1064.severity = none dotnet_diagnostic.CA1065.severity = none # CA1066: Implement IEquatable when overriding Object.Equals -dotnet_diagnostic.CA1066.severity = none +dotnet_diagnostic.CA1066.severity = warning # CA1067: Override Object.Equals(object) when implementing IEquatable -dotnet_diagnostic.CA1067.severity = none +dotnet_diagnostic.CA1067.severity = warning # CA1068: CancellationToken parameters must come last dotnet_diagnostic.CA1068.severity = none diff --git a/eng/CodeAnalysis.test.globalconfig b/eng/CodeAnalysis.test.globalconfig index 572310d3b86d0..f56a38cfa707c 100644 --- a/eng/CodeAnalysis.test.globalconfig +++ b/eng/CodeAnalysis.test.globalconfig @@ -1681,7 +1681,7 @@ dotnet_diagnostic.xUnit2012.severity = warning dotnet_diagnostic.xUnit2013.severity = none # xUnit2014: Do not use throws check to check for asynchronously thrown exception -dotnet_diagnostic.xUnit2014.severity = warning +dotnet_diagnostic.xUnit2014.severity = none # xUnit2015: Do not use typeof expression to check the exception type dotnet_diagnostic.xUnit2015.severity = warning diff --git a/eng/Subsets.props b/eng/Subsets.props index 772fbfcb99532..5ea1ff48e23f4 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 @@ -58,7 +58,7 @@ - clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs + clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.spmi clr.iltools+clr.packages @@ -106,12 +106,14 @@ - + + + @@ -202,10 +204,14 @@ $(ClrRuntimeBuildSubsets);ClrILToolsSubset=true - + $(ClrRuntimeBuildSubsets);ClrNativeAotSubset=true + + $(ClrRuntimeBuildSubsets);ClrSpmiSubset=true + + @@ -358,6 +364,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a2cfe2c769fe8..3da43d2ed21e2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,258 +1,258 @@ - + https://github.com/dotnet/icu - aae7d341a8ee7841ed0cb1cf298ab17fe04c187b + 80a658fa6aa6601d67bfe5a294e0d1b7e1184a5c https://github.com/dotnet/msquic a7213b4676c1803bb251771291a525482d42e511 - + https://github.com/dotnet/emsdk - 4eb953d7051890da4f36167125c6b41e06d7f56d + aaa56a6622c4991cf65d553250af3c0ade1320bc https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - e7e0ebc663c70ccb19c331af50d418a06dc92df8 + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 662aff66999c435aec09c58643e9fd703eadc3e0 + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - a2af6294767b4a3f4c2ce787c5dda2abeeda7a00 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/linker - 1a6468ff722c8d362f37638989ec01ab9975ac28 + e485816b48273d03bd6266a64dad9bea97f861d5 - + https://github.com/dotnet/xharness - d33e67a6c2cc5fe415917c6f9bd17046a929dcc0 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/xharness - d33e67a6c2cc5fe415917c6f9bd17046a929dcc0 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/xharness - d33e67a6c2cc5fe415917c6f9bd17046a929dcc0 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/arcade - 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -270,17 +270,17 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 91d6b3c1f51888d166701510189505f35714665c - + https://github.com/dotnet/hotreload-utils - 5bc948c6242bc9423c3269d122dcdf0ad6c06a83 + d3e96c2e8ed4d58de217c44423c9ba3b90333724 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/roslyn-analyzers - e101c379c6e3c7011562ee3af3e3de066da0048f + f471d3381584f10f9908432e0b2b2b8ef07a0aa6 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 8bc9373cc09ac..aae2d08e09018 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,8 +7,8 @@ 0 0 7.0.100 - alpha - 1 + preview + 2 $(MajorVersion).$(MinorVersion).0.0 @@ -50,42 +50,42 @@ 3.3.2 4.0.1 4.0.1 - 7.0.0-preview1.21613.1 + 7.0.0-preview1.22068.2 2.0.0-alpha.1.21525.11 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 2.5.1-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 - 7.0.0-beta.22056.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 2.5.1-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 6.0.0-preview.1.102 - 7.0.0-alpha.1.22059.2 - 7.0.0-alpha.1.22059.2 - 7.0.0-alpha.1.22059.2 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 3.1.0 - 7.0.0-alpha.1.22059.2 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 - 1.0.0-alpha.1.22060.1 + 7.0.0-alpha.1.22073.5 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 5.0.0 4.3.0 @@ -114,30 +114,30 @@ 4.3.0 4.3.0 4.3.0 - 6.0.0-rc.2.21454.1 + 6.0.0 4.3.1 5.0.0 5.0.0 5.0.0 4.9.0-rc2.21473.1 - 7.0.0-alpha.1.22059.2 - 7.0.0-alpha.1.22059.2 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 4.5.4 4.5.0 - 7.0.0-alpha.1.22059.2 + 7.0.0-alpha.1.22073.5 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 1.0.0-prerelease.21577.2 1.0.0-prerelease.21577.2 @@ -160,11 +160,12 @@ 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.22062.1 - 1.0.0-prerelease.22062.1 - 1.0.0-prerelease.22062.1 - 1.0.2-alpha.0.22060.2 - 2.4.2-pre.9 + 1.0.0-prerelease.22074.1 + 1.0.0-prerelease.22074.1 + 1.0.0-prerelease.22074.1 + 1.0.2-alpha.0.22074.1 + 2.4.2-pre.22 + 0.12.0-pre.20 2.4.2 3.1.0 12.0.3 @@ -174,25 +175,25 @@ 7.0.100-alpha.1.21528.1 1.1.1-beta1.21467.5 - 6.0.0-preview-20211019.1 + 6.0.0-preview-20220104.1 - 7.0.100-1.22053.1 + 7.0.100-1.22063.2 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-alpha.1.22060.1 + 7.0.0-preview.2.22074.5 7.0.0-alpha.1.21529.3 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 - 11.1.0-alpha.1.21615.1 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 - 7.0.0-alpha.1.21601.1 + 7.0.0-alpha.2.22071.3 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) 1.1.87-gba258badda diff --git a/eng/build.sh b/eng/build.sh index ea8e3089e95f4..167f8e2014182 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, armel, arm64, loongarch64, s390x 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|armel|arm64|loongarch64|s390x|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, armel, arm64, loongarch64, s390x, 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/cross/arm/tizen-build-rootfs.sh b/eng/common/cross/arm/tizen-build-rootfs.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/arm/tizen-fetch.sh b/eng/common/cross/arm/tizen-fetch.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index e94d13d62ef64..f97dca7705408 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -7,7 +7,7 @@ usage() echo "Usage: $0 [BuildArch] [CodeName] [lldbx.y] [--skipunmount] --rootfsdir ]" echo "BuildArch can be: arm(default), armel, arm64, x86" echo "CodeName - optional, Code name for Linux, can be: xenial(default), zesty, bionic, alpine, alpine3.13 or alpine3.14. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen." - echo " for FreeBSD can be: freebsd11, freebsd12, freebsd13" + echo " for FreeBSD can be: freebsd12, freebsd13" echo " for illumos can be: illumos." echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FreeBSD" echo "--skipunmount - optional, will skip the unmount of rootfs folder." @@ -60,13 +60,13 @@ __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="12.2-RELEASE" -__FreeBSDPkg="1.12.0" +__FreeBSDBase="12.3-RELEASE" +__FreeBSDPkg="1.17.0" __FreeBSDABI="12" __FreeBSDPackages="libunwind" __FreeBSDPackages+=" icu" __FreeBSDPackages+=" libinotify" -__FreeBSDPackages+=" lttng-ust" +__FreeBSDPackages+=" openssl" __FreeBSDPackages+=" krb5" __FreeBSDPackages+=" terminfo-db" @@ -206,10 +206,6 @@ while :; do __AlpineVersion=3.14 __AlpinePackages+=" llvm11-libs" ;; - freebsd11) - __FreeBSDBase="11.3-RELEASE" - __FreeBSDABI="11" - ;& freebsd12) __CodeName=freebsd __BuildArch=x64 diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index f7878dddd3921..fba2afda438b6 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -37,6 +37,13 @@ elseif(TARGET_ARCH_NAME STREQUAL "arm") if(TIZEN) set(TIZEN_TOOLCHAIN "armv7hl-tizen-linux-gnueabihf/9.2.0") endif() +elseif(TARGET_ARCH_NAME STREQUAL "armv6") + set(CMAKE_SYSTEM_PROCESSOR armv6l) + if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf) + set(TOOLCHAIN "armv6-alpine-linux-musleabihf") + else() + set(TOOLCHAIN "arm-linux-gnueabihf") + endif() elseif(TARGET_ARCH_NAME STREQUAL "arm64") set(CMAKE_SYSTEM_PROCESSOR aarch64) if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl) @@ -60,7 +67,7 @@ elseif (ILLUMOS) set(CMAKE_SYSTEM_PROCESSOR "x86_64") set(TOOLCHAIN "x86_64-illumos") else() - message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64, s390x and x86 are supported!") + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, armv6, arm64, s390x and x86 are supported!") endif() if(DEFINED ENV{TOOLCHAIN}) @@ -194,7 +201,7 @@ endif() # Specify compile options -if((TARGET_ARCH_NAME MATCHES "^(arm|armel|arm64|s390x)$" AND NOT ANDROID) OR ILLUMOS) +if((TARGET_ARCH_NAME MATCHES "^(arm|armv6|armel|arm64|s390x)$" AND NOT ANDROID) OR ILLUMOS) set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN}) set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN}) set(CMAKE_ASM_COMPILER_TARGET ${TOOLCHAIN}) diff --git a/eng/common/internal/NuGet.config b/eng/common/internal/NuGet.config new file mode 100644 index 0000000000000..769650362f4aa --- /dev/null +++ b/eng/common/internal/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 2427ca6b6aec7..8508397d77640 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -5,13 +5,8 @@ param( [Parameter(Mandatory=$true)][string] $MaestroToken, [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', [Parameter(Mandatory=$true)][string] $WaitPublishingFinish, - [Parameter(Mandatory=$false)][string] $EnableSourceLinkValidation, - [Parameter(Mandatory=$false)][string] $EnableSigningValidation, - [Parameter(Mandatory=$false)][string] $EnableNugetValidation, - [Parameter(Mandatory=$false)][string] $PublishInstallersAndChecksums, [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters, - [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters, - [Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters + [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters ) try { @@ -35,27 +30,6 @@ try { $optionalParams.Add("--no-wait") | Out-Null } - if ("false" -ne $PublishInstallersAndChecksums) { - $optionalParams.Add("--publish-installers-and-checksums") | Out-Null - } - - if ("true" -eq $EnableNugetValidation) { - $optionalParams.Add("--validate-nuget") | Out-Null - } - - if ("true" -eq $EnableSourceLinkValidation) { - $optionalParams.Add("--validate-sourcelinkchecksums") | Out-Null - } - - if ("true" -eq $EnableSigningValidation) { - $optionalParams.Add("--validate-signingchecksums") | Out-Null - - if ("" -ne $SigningValidationAdditionalParameters) { - $optionalParams.Add("--signing-validation-parameters") | Out-Null - $optionalParams.Add($SigningValidationAdditionalParameters) | Out-Null - } - } - & $darc add-build-to-channel ` --id $buildId ` --publishing-infra-version $PublishingInfraVersion ` diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 8cf772b3cbf81..24cec0424e5d6 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -29,14 +29,6 @@ parameters: # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, # not pipeline artifacts, so doesn't affect the use of this parameter. pipelineArtifactNames: [] - # Optional: location and ID of the AzDO build that the build/pipeline artifacts should be - # downloaded from. By default, uses runtime expressions to decide based on the variables set by - # the 'setupMaestroVars' dependency. Overriding this parameter is necessary if SDL tasks are - # running without Maestro++/BAR involved, or to download artifacts from a specific existing build - # to iterate quickly on SDL changes. - AzDOProjectName: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - AzDOPipelineId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - AzDOBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] jobs: - job: Run_SDL @@ -55,11 +47,20 @@ jobs: - name: GuardianVersion value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} pool: - vmImage: windows-2019 + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: - checkout: self clean: true + - template: /eng/common/templates/post-build/setup-maestro-vars.yml + - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - ${{ if ne(parameters.artifactNames, '') }}: - ${{ each artifactName in parameters.artifactNames }}: diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index c4fc18b3ee77a..9d1e3042d8a6c 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -3,9 +3,8 @@ parameters: dependsOn: '' # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: - vmImage: 'windows-2019' - + pool: '' + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) @@ -31,7 +30,18 @@ jobs: displayName: OneLocBuild - pool: ${{ parameters.pool }} + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 variables: - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index ff4ab75c886dc..554e71cfc436d 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -83,7 +83,15 @@ jobs: - ${{ if eq(parameters.enableSourceBuild, true) }}: - Source_Build_Complete pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + runAsPublic: ${{ parameters.runAsPublic }} publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml deleted file mode 100644 index 8990dfc8c87cc..0000000000000 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ /dev/null @@ -1,190 +0,0 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate - publishInstallersAndChecksums: true - symbolPublishingAdditionalParameters: '' - stageName: '' - channelName: '' - channelId: '' - transportFeed: '' - shippingFeed: '' - symbolsFeed: '' - -stages: -- stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} - variables: - - template: ../common-variables.yml - displayName: ${{ parameters.channelName }} Publishing - jobs: - - template: ../setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: publish_symbols - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - variables: - - group: DotNet-Symbol-Server-Pats - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PdbArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - /p:PublishToMSDL=false - ${{ parameters.symbolPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:PublishingInfraVersion=2 - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:ChecksumsTargetStaticFeed=$(InternalChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey) - /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) - /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:PublishToMSDL=false - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - - template: ../../steps/add-build-to-channel.yml - parameters: - ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml deleted file mode 100644 index 3220c6a4f92ff..0000000000000 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ /dev/null @@ -1,192 +0,0 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate - publishInstallersAndChecksums: true - symbolPublishingAdditionalParameters: '' - stageName: '' - channelName: '' - channelId: '' - transportFeed: '' - shippingFeed: '' - symbolsFeed: '' - # If the channel name is empty, no links will be generated - akaMSChannelName: '' - -stages: -- stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} - variables: - - template: ../common-variables.yml - displayName: ${{ parameters.channelName }} Publishing - jobs: - - template: ../setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: publish_symbols - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - variables: - - group: DotNet-Symbol-Server-Pats - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PdbArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - - name: ArtifactsCategory - value: ${{ coalesce(variables._DotNetArtifactsCategory, '.NETCore') }} - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:PublishingInfraVersion=2 - /p:ArtifactsCategory=$(ArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:LatestLinkShortUrlPrefix=dotnet/'${{ parameters.akaMSChannelName }}' - /p:AkaMSClientId=$(akams-client-id) - /p:AkaMSClientSecret=$(akams-client-secret) - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - - template: ../../steps/add-build-to-channel.yml - parameters: - ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index c99fd7503767c..c830e6f277606 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,54 +4,6 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - - # .NET Core 3.1 Dev - - name: PublicDevRelease_31_Channel_Id - value: 128 - - # .NET 5 Dev - - name: Net_5_Dev_Channel_Id - value: 131 - - # .NET Eng - Validation - - name: Net_Eng_Validation_Channel_Id - value: 9 - - # .NET Eng - Latest - - name: Net_Eng_Latest_Channel_Id - value: 2 - - # .NET 3 Eng - Validation - - name: NET_3_Eng_Validation_Channel_Id - value: 390 - - # .NET 3 Eng - - name: NetCore_3_Tools_Channel_Id - value: 344 - - # .NET Core 3.0 Internal Servicing - - name: InternalServicing_30_Channel_Id - value: 184 - - # .NET Core 3.0 Release - - name: PublicRelease_30_Channel_Id - value: 19 - - # .NET Core 3.1 Release - - name: PublicRelease_31_Channel_Id - value: 129 - - # General Testing - - name: GeneralTesting_Channel_Id - value: 529 - - # .NET Core 3.1 Blazor Features - - name: NetCore_31_Blazor_Features_Channel_Id - value: 531 - - # .NET Core Experimental - - name: NetCore_Experimental_Channel_Id - value: 562 # Whether the build is internal or not - name: IsInternalBuild @@ -70,27 +22,6 @@ variables: - name: SymbolToolVersion value: 1.0.1 - # Feed Configurations - # These should include the suffix "/index.json" - - # Default locations for Installers and checksums - # Public Locations - - name: ChecksumsBlobFeedUrl - value: https://dotnetclichecksums.blob.core.windows.net/dotnet/index.json - - name: InstallersBlobFeedUrl - value: https://dotnetcli.blob.core.windows.net/dotnet/index.json - - # Private Locations - - name: InternalChecksumsBlobFeedUrl - value: https://dotnetclichecksumsmsrc.blob.core.windows.net/dotnet/index.json - - name: InternalChecksumsBlobFeedKey - value: $(dotnetclichecksumsmsrc-storage-key) - - - name: InternalInstallersBlobFeedUrl - value: https://dotnetclimsrc.blob.core.windows.net/dotnet/index.json - - name: InternalInstallersBlobFeedKey - value: $(dotnetclimsrc-access-key) - # Skip component governance and codesign validation for SDL. These jobs # create no content. - name: skipComponentGovernanceDetection diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 4f79cf0f33703..2f176571f020c 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,113 +1,114 @@ parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V2 accepts optionally outlining the publishing stages - default is inline. - # Publishing V3 DOES NOT accept inlining the publishing stages. - publishingInfraVersion: 2 - # When set to true the publishing templates from the repo will be used - # otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline - inline: true - - # Only used if inline==false. When set to true will stall the current build until - # the Promotion Pipeline build finishes. Otherwise, the current build will continue - # execution concurrently with the promotion build. - waitPublishingFinish: true - - BARBuildId: '' - PromoteToChannelIds: '' - - enableSourceLinkValidation: false - enableSigningValidation: true - enableSymbolValidation: false - enableNugetValidation: true - publishInstallersAndChecksums: true - SDLValidationParameters: - enable: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true # These parameters let the user customize the call to sdk-task.ps1 for publishing # symbols & general artifacts as well as for signing validation - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' # Which stages should finish execution before post-build stages start - validateDependsOn: - - build - publishDependsOn: - - Validate + - name: validateDependsOn + type: object + default: + - build - # Channel ID's instantiated in this file. - # When adding a new channel implementation the call to `check-channel-consistency.ps1` - # needs to be updated with the new channel ID - NetEngLatestChannelId: 2 - NetEngValidationChannelId: 9 - NetDev5ChannelId: 131 - NetDev6ChannelId: 1296 - GeneralTestingChannelId: 529 - NETCoreToolingDevChannelId: 548 - NETCoreToolingReleaseChannelId: 549 - NETInternalToolingChannelId: 551 - NETCoreExperimentalChannelId: 562 - NetEngServicesIntChannelId: 678 - NetEngServicesProdChannelId: 679 - NetCoreSDK313xxChannelId: 759 - NetCoreSDK313xxInternalChannelId: 760 - NetCoreSDK314xxChannelId: 921 - NetCoreSDK314xxInternalChannelId: 922 - VS166ChannelId: 1010 - VS167ChannelId: 1011 - VS168ChannelId: 1154 - VSMasterChannelId: 1012 - VS169ChannelId: 1473 - VS1610ChannelId: 1692 + - name: publishDependsOn + type: object + default: + - Validate stages: -- ${{ if or(and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')), eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - stage: Validate dependsOn: ${{ parameters.validateDependsOn }} displayName: Validate Build Assets variables: - template: common-variables.yml jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}: - - job: - displayName: Post-build Checks - dependsOn: setupMaestroVars - variables: - - name: TargetChannels - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ] - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Maestro Channels Consistency - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1 - arguments: -PromoteToChannels "$(TargetChannels)" - -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}},${{parameters.VS169ChannelId}},${{parameters.VS1610ChannelId}} - - job: displayName: NuGet Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableNugetValidation }}, 'true') pool: - vmImage: 'windows-2019' - variables: - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -128,19 +129,22 @@ stages: - job: displayName: Signing Validation - dependsOn: setupMaestroVars condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -185,19 +189,22 @@ stages: - job: displayName: SourceLink Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: @@ -223,367 +230,48 @@ stages: - template: /eng/common/templates/job/execute-sdl.yml parameters: enable: ${{ parameters.SDLValidationParameters.enable }} - dependsOn: setupMaestroVars additionalParameters: ${{ parameters.SDLValidationParameters.params }} continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} -- ${{ if or(ge(parameters.publishingInfraVersion, 3), eq(parameters.inline, 'false')) }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: - displayName: Publish Using Darc - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.PublishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish ${{ parameters.waitPublishingFinish }} - -PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }} - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' - -- ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}: - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Dev5_Publish' - channelName: '.NET 5 Dev' - akaMSChannelName: 'net5/dev' - channelId: ${{ parameters.NetDev5ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Dev6_Publish' - channelName: '.NET 6 Dev' - akaMSChannelName: 'net6/dev' - channelId: ${{ parameters.NetDev6ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Latest_Publish' - channelName: '.NET Eng - Latest' - akaMSChannelName: 'eng/daily' - channelId: ${{ parameters.NetEngLatestChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Validation_Publish' - channelName: '.NET Eng - Validation' - akaMSChannelName: 'eng/validation' - channelId: ${{ parameters.NetEngValidationChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'General_Testing_Publish' - channelName: 'General Testing' - akaMSChannelName: 'generaltesting' - channelId: ${{ parameters.GeneralTestingChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Tooling_Dev_Publishing' - channelName: '.NET Core Tooling Dev' - channelId: ${{ parameters.NETCoreToolingDevChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Tooling_Release_Publishing' - channelName: '.NET Core Tooling Release' - channelId: ${{ parameters.NETCoreToolingReleaseChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NET_Internal_Tooling_Publishing' - channelName: '.NET Internal Tooling' - channelId: ${{ parameters.NETInternalToolingChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Experimental_Publishing' - channelName: '.NET Core Experimental' - channelId: ${{ parameters.NETCoreExperimentalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Services_Int_Publish' - channelName: '.NET Eng Services - Int' - channelId: ${{ parameters.NetEngServicesIntChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Services_Prod_Publish' - channelName: '.NET Eng Services - Prod' - channelId: ${{ parameters.NetEngServicesProdChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_314xx_Publishing' - channelName: '.NET Core SDK 3.1.4xx' - channelId: ${{ parameters.NetCoreSDK314xxChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_314xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.4xx Internal' - channelId: ${{ parameters.NetCoreSDK314xxInternalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_313xx_Publishing' - channelName: '.NET Core SDK 3.1.3xx' - channelId: ${{ parameters.NetCoreSDK313xxChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_313xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.3xx Internal' - channelId: ${{ parameters.NetCoreSDK313xxInternalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_6_Publishing' - channelName: 'VS 16.6' - channelId: ${{ parameters.VS166ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_7_Publishing' - channelName: 'VS 16.7' - channelId: ${{ parameters.VS167ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_8_Publishing' - channelName: 'VS 16.8' - channelId: ${{ parameters.VS168ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_Master_Publishing' - channelName: 'VS Master' - channelId: ${{ parameters.VSMasterChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_16_9_Publishing' - channelName: 'VS 16.9' - channelId: ${{ parameters.VS169ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_16_10_Publishing' - channelName: 'VS 16.10' - channelId: ${{ parameters.VS1610ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' +- stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: common-variables.yml + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + + - task: NuGetAuthenticate@0 + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 4a22b2e6f6de7..0c87f149a4ad7 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -2,77 +2,69 @@ parameters: BARBuildId: '' PromoteToChannelIds: '' -jobs: -- job: setupMaestroVars - displayName: Setup Maestro Vars - variables: - - template: common-variables.yml - pool: - vmImage: 'windows-2019' - steps: - - checkout: none - - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars +steps: + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs inputs: - targetType: inline - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 + - task: PowerShell@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + targetType: inline + pwsh: true + script: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } + $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $apiHeaders.Add('Accept', 'application/json') + $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels;isOutput=true]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" + $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + + $BarId = $Env:BARBuildId + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" - Write-Host "##vso[task.setvariable variable=AzDOProjectName;isOutput=true]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId;isOutput=true]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId;isOutput=true]$AzureDevOpsBuildId" + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + MAESTRO_API_TOKEN: $(MaestroApiAccessToken) + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index ba40dc82f1411..d85d6d07d5c7b 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -23,7 +23,7 @@ steps: # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those # changes. - $internalRestoreArgs= + internalRestoreArgs= if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then # Temporarily work around https://github.com/dotnet/arcade/issues/7709 chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh diff --git a/eng/formatting/format.sh b/eng/formatting/format.sh old mode 100644 new mode 100755 diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index bc2e7e5dff9a0..aab934c42ae6b 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -24,6 +24,9 @@ $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'sharedFramework')) $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'crossgen2')) + $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'ilc')) + $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'aotsdk')) + $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'build')) $([MSBuild]::NormalizeDirectory('$(MonoArtifactsPath)', 'cross', $(TargetOS.ToLowerInvariant())-$(TargetArchitecture.ToLowerInvariant()))) diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 373091b13a001..294e9832ad310 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, -armel, -arm64, -loongarch64, -s390x, 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)" @@ -270,6 +270,10 @@ while :; do __BuildArch=arm ;; + armv6|-armv6) + __BuildArch=armv6 + ;; + arm64|-arm64) __BuildArch=arm64 ;; diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index fad1ac58d39c8..b67594cb60fb2 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -213,6 +213,9 @@ elseif (CLR_CMAKE_HOST_ARCH_I386) elseif (CLR_CMAKE_HOST_ARCH_ARM) set(ARCH_HOST_NAME arm) add_definitions(-DHOST_ARM) +elseif (CLR_CMAKE_HOST_ARCH_ARMV6) + set(ARCH_HOST_NAME armv6) + add_definitions(-DHOST_ARMV6) elseif (CLR_CMAKE_HOST_ARCH_ARM64) set(ARCH_HOST_NAME arm64) add_definitions(-DHOST_ARM64 -DHOST_64BIT) @@ -238,6 +241,8 @@ if (CLR_CMAKE_HOST_UNIX) message("Detected Linux x86_64") elseif(CLR_CMAKE_HOST_UNIX_ARM) message("Detected Linux ARM") + elseif(CLR_CMAKE_HOST_UNIX_ARMV6) + message("Detected Linux ARMv6") elseif(CLR_CMAKE_HOST_UNIX_ARM64) message("Detected Linux ARM64") elseif(CLR_CMAKE_HOST_UNIX_LOONGARCH64) @@ -301,6 +306,12 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM) set(ARCH_TARGET_NAME arm) add_compile_definitions($<$>>:TARGET_ARM>) add_compile_definitions($<$>>:TARGET_32BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_ARMV6) + set(ARCH_SOURCES_DIR arm) + set(ARCH_TARGET_NAME armv6) + add_compile_definitions($<$>>:TARGET_ARM>) + add_compile_definitions($<$>>:TARGET_ARMV6>) + add_compile_definitions($<$>>:TARGET_32BIT>) elseif (CLR_CMAKE_TARGET_ARCH_I386) set(ARCH_TARGET_NAME x86) set(ARCH_SOURCES_DIR i386) @@ -507,6 +518,14 @@ if(CLR_CMAKE_HOST_UNIX_ARM) endif(ARM_SOFTFP) endif(CLR_CMAKE_HOST_UNIX_ARM) +if(CLR_CMAKE_HOST_UNIX_ARMV6) + add_compile_options(-mfpu=vfp) + add_definitions(-DCLR_ARM_FPU_CAPABILITY=0x0) + add_compile_options(-march=armv6zk) + add_compile_options(-mcpu=arm1176jzf-s) + add_compile_options(-mfloat-abi=hard) +endif(CLR_CMAKE_HOST_UNIX_ARMV6) + if(CLR_CMAKE_HOST_UNIX_X86) add_compile_options(-msse2) endif() diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index cdf33430b49f1..ecf10a8d4c39e 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -41,6 +41,8 @@ if(CLR_CMAKE_HOST_OS STREQUAL Linux) set(CLR_CMAKE_HOST_UNIX_ARMV7L 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL armv7-a) set(CLR_CMAKE_HOST_UNIX_ARM 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv6 OR CMAKE_SYSTEM_PROCESSOR STREQUAL armv6l) + set(CLR_CMAKE_HOST_UNIX_ARMV6 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) set(CLR_CMAKE_HOST_UNIX_ARM64 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL loongarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL loongarch64) @@ -217,6 +219,13 @@ if(CLR_CMAKE_HOST_UNIX_ARM) if(CLR_CMAKE_HOST_UNIX_ARMV7L) set(CLR_CMAKE_HOST_ARCH_ARMV7L 1) endif() +elseif(CLR_CMAKE_HOST_UNIX_ARMV6) + set(CLR_CMAKE_HOST_ARCH_ARMV6 1) + set(CLR_CMAKE_HOST_ARCH "armv6") + + if(CLR_CMAKE_HOST_UNIX_ARMV6L) + set(CLR_CMAKE_HOST_ARCH_ARMV6L 1) + endif() elseif(CLR_CMAKE_HOST_UNIX_ARM64) set(CLR_CMAKE_HOST_ARCH_ARM64 1) set(CLR_CMAKE_HOST_ARCH "arm64") @@ -277,6 +286,8 @@ if (CLR_CMAKE_TARGET_ARCH STREQUAL x64) set(CLR_CMAKE_TARGET_ARCH_LOONGARCH64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) set(CLR_CMAKE_TARGET_ARCH_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armv6) + set(CLR_CMAKE_TARGET_ARCH_ARMV6 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armel) set(CLR_CMAKE_TARGET_ARCH_ARM 1) set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1) @@ -379,6 +390,8 @@ if(CLR_CMAKE_TARGET_UNIX) set(CLR_CMAKE_TARGET_UNIX_ARM 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) set(CLR_CMAKE_TARGET_UNIX_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armv6) + set(CLR_CMAKE_TARGET_UNIX_ARMV6 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm64) set(CLR_CMAKE_TARGET_UNIX_ARM64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL loongarch64) diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index 136cd67925d0c..860e46427b6b0 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -7,15 +7,15 @@ if (CMAKE_C_COMPILER MATCHES "-?[0-9]+(\.[0-9]+)?$") endif() if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(CMAKE_C_COMPILER_ID MATCHES "Clang") if(APPLE) set(TOOLSET_PREFIX "") else() set(TOOLSET_PREFIX "llvm-") endif() - elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU") if(CMAKE_CROSSCOMPILING) - set(TOOLSET_PREFIX "${CMAKE_CXX_COMPILER_TARGET}-") + set(TOOLSET_PREFIX "${CMAKE_C_COMPILER_TARGET}-") else() set(TOOLSET_PREFIX "") endif() @@ -52,8 +52,8 @@ 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 STREQUAL armv7l OR - CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL s390x)) + elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND + CMAKE_SYSTEM_PROCESSOR MATCHES "^(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 c4af68ba7dc61..0c28f75706de1 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -4,7 +4,7 @@ function(clr_unknown_arch) elseif(CLR_CROSS_COMPONENTS_BUILD) message(FATAL_ERROR "Only AMD64, I386 host are supported for linux cross-architecture component. Found: ${CMAKE_SYSTEM_PROCESSOR}") else() - message(FATAL_ERROR "Only AMD64, ARM64, LOONGARCH64 and ARM are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Only AMD64, ARMV6, ARM64, LOONGARCH64 and ARM are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") endif() endfunction() @@ -155,6 +155,10 @@ function(find_unwind_libs UnwindLibs) find_library(UNWIND_ARCH NAMES unwind-arm) endif() + if(CLR_CMAKE_HOST_ARCH_ARMV6) + find_library(UNWIND_ARCH NAMES unwind-arm) + endif() + if(CLR_CMAKE_HOST_ARCH_ARM64) find_library(UNWIND_ARCH NAMES unwind-aarch64) endif() diff --git a/eng/native/init-os-and-arch.sh b/eng/native/init-os-and-arch.sh index 586534be1c8aa..eda07a5feebbd 100644 --- a/eng/native/init-os-and-arch.sh +++ b/eng/native/init-os-and-arch.sh @@ -53,6 +53,10 @@ case "$CPUName" in fi ;; + armv6l) + arch=armv6 + ;; + i[3-6]86) echo "Unsupported CPU $CPUName detected, build might not succeed!" arch=x86 diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index e8a04c5698ad3..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|arm64|loongarch64|s390x|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|arm64|loongarch64|s390x|x86)$" OR F set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) endif() else() - message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64, loongarch64, s390x 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 "loongarch64") +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/packaging.targets b/eng/packaging.targets index 667837fbff106..c305c64dd9409 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -162,19 +162,18 @@ <_MultiTargetRoslynComponentTargetPrefix>$(PackageId.Replace('.', '_')) - <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>Disable$(PackageId.Replace('.', ''))SourceGenerator - <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>$(_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName.Replace('Abstractions', '')) + Disable$(PackageId.Replace('.', ''))SourceGenerator diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index cf30d702dda60..c9015681d1e17 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -3,6 +3,7 @@ parameters: nameSuffix: '' buildArgs: '' archType: '' + hostedOs: '' osGroup: '' osSubgroup: '' container: '' @@ -35,8 +36,12 @@ parameters: jobs: - template: /eng/common/templates/job/job.yml parameters: - name: ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }} - displayName: ${{ format('Build {0}{1} {2} {3} {4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }} + ${{ if eq(parameters.hostedOs, '') }}: + name: ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }} + displayName: ${{ format('Build {0}{1} {2} {3} {4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }} + ${{ if ne(parameters.hostedOs, '') }}: + name: ${{ format('build_{0}{1}_{2}_{3}_{4}_{5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.hostedOs, parameters.buildConfig, parameters.nameSuffix) }} + displayName: ${{ format('Build {0}{1} {2} {3} {4} {5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.hostedOs, parameters.buildConfig, parameters.nameSuffix) }} pool: ${{ parameters.pool }} container: ${{ parameters.container }} condition: and(succeeded(), ${{ parameters.condition }}) @@ -136,7 +141,7 @@ jobs: df -h displayName: Disk Usage before Build - - ${{ if contains(parameters.nameSuffix, 'Windows_wasm') }}: + - ${{ if eq(parameters.platform, 'Browser_wasm_win') }}: # Update machine certs - task: PowerShell@2 displayName: Update machine certs diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index ade8c7aab981b..4f0200380bc9f 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -52,6 +52,31 @@ jobs: crossrootfsDir: '/crossrootfs/arm' ${{ insert }}: ${{ parameters.jobParameters }} +# Linux armv6 +- ${{ if or(containsValue(parameters.platforms, 'Linux_armv6'), or(and(ne(parameters.runtimeFlavor, 'mono'), in(parameters.platformGroup, 'gcstress')), and(eq(parameters.runtimeFlavor, 'mono'), in(parameters.platformGroup, 'all', 'gcstress')))) }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: Linux + archType: armv6 + targetRid: linux-armv6 + platform: Linux_armv6 + container: + image: ubuntu-20.04-cross-armv6-raspbian-10-20211208135931-e6e3ac4 + registry: mcr + jobParameters: + runtimeFlavor: ${{ parameters.runtimeFlavor }} + stagedBuild: ${{ parameters.stagedBuild }} + buildConfig: ${{ parameters.buildConfig }} + ${{ if eq(parameters.passPlatforms, true) }}: + platforms: ${{ parameters.platforms }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + crossBuild: true + crossrootfsDir: '/crossrootfs/armv6' + ${{ insert }}: ${{ parameters.jobParameters }} + # Linux arm64 - ${{ if or(containsValue(parameters.platforms, 'Linux_arm64'), in(parameters.platformGroup, 'all', 'gcstress')) }}: @@ -273,7 +298,6 @@ jobs: jobTemplate: ${{ parameters.jobTemplate }} helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} variables: ${{ parameters.variables }} - hostedOs: Linux osGroup: Browser archType: wasm targetRid: browser-wasm @@ -282,6 +306,7 @@ jobs: image: ubuntu-18.04-webassembly-20210707133424-12f133e registry: mcr jobParameters: + hostedOs: Linux runtimeFlavor: ${{ parameters.runtimeFlavor }} stagedBuild: ${{ parameters.stagedBuild }} buildConfig: ${{ parameters.buildConfig }} @@ -297,12 +322,12 @@ jobs: jobTemplate: ${{ parameters.jobTemplate }} helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} variables: ${{ parameters.variables }} - hostedOs: windows osGroup: Browser archType: wasm targetRid: browser-wasm platform: Browser_wasm_win jobParameters: + hostedOs: windows runtimeFlavor: ${{ parameters.runtimeFlavor }} stagedBuild: ${{ parameters.stagedBuild }} buildConfig: ${{ parameters.buildConfig }} diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index 04399d26a6a22..f944ad47ba203 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -73,7 +73,7 @@ jobs: - ${{ if not(or(eq(parameters.runtimeVariant, 'minijit'), eq(parameters.runtimeVariant, 'monointerpreter'))) }}: - ${{ if eq(parameters.runtimeVariant, 'llvmfullaot') }}: - ${{ format('{0}_llvmaot_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - - ${{ if not(eq(parameters.runtimeVariant, 'llvmfullaot')) }}: + - ${{ if ne(parameters.runtimeVariant, 'llvmfullaot') }}: - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} @@ -109,7 +109,7 @@ jobs: - name: runtimeVariantArg value: '' - - ${{ if not(eq(parameters.runtimeVariant, '')) }}: + - ${{ if ne(parameters.runtimeVariant, '') }}: - name: runtimeVariantArg value: '/p:RuntimeVariant=${{ parameters.runtimeVariant }}' @@ -319,7 +319,7 @@ jobs: - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) $(runtimeVariantArg) displayName: "LLVM AOT compile CoreCLR tests" - ${{ if eq(parameters.archType, 'arm64') }}: - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) cross $(runtimeVariantArg) + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) cross $(runtimeVariantArg) -maxcpucount:2 displayName: "LLVM AOT cross-compile CoreCLR tests" env: __MonoToolPrefix: aarch64-linux-gnu- @@ -546,6 +546,7 @@ jobs: - jitosr - jitosr_stress - jitosr_pgo + - jitosr_stress_random - jitpartialcompilation - jitpartialcompilation_osr - jitpartialcompilation_osr_pgo diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml index d6b84f837c327..6e378369aa4fc 100644 --- a/eng/pipelines/common/variables.yml +++ b/eng/pipelines/common/variables.yml @@ -11,19 +11,17 @@ variables: - name: isOfficialBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }} -- name: isFullMatrix +- name: isRollingBuild value: ${{ and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }} -- name: isNotFullMatrix - value: ${{ and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }} -- name: isNotManualAndIsPR - value: ${{ and(not(in(variables['Build.DefinitionName'], 'runtime-staging-manual', 'runtime-manual')), eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }} -- name: isManualOrIsNotPR - value: ${{ or(in(variables['Build.DefinitionName'], 'runtime-staging-manual', 'runtime-manual'), and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest'))) }} +- name: isExtraPlatformsBuild + value: ${{ eq(variables['Build.DefinitionName'], 'runtime-extra-platforms') }} +- name: isNotExtraPlatformsBuild + value: ${{ ne(variables['Build.DefinitionName'], 'runtime-extra-platforms') }} # We only run evaluate paths on runtime, runtime-staging and runtime-community pipelines on PRs # keep in sync with /eng/pipelines/common/xplat-setup.yml - name: dependOnEvaluatePaths - value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }} + value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community', 'runtime-extra-platforms')) }} - name: debugOnPrReleaseOnRolling ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: value: Release diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index 05a6bc7c4a63c..e397bcdd456a6 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -22,8 +22,7 @@ jobs: shouldContinueOnError: ${{ and(endsWith(variables['Build.DefinitionName'], 'staging'), eq(variables['Build.Reason'], 'PullRequest')) }} # keep in sync with /eng/pipelines/common/variables.yml - nonPRBuild: ${{ and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }} - dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }} + dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community', 'runtime-extra-platforms')) }} variables: # Disable component governance in our CI builds. These builds are not shipping nor @@ -50,8 +49,12 @@ jobs: value: $(buildConfigUpper) - name: _runSmokeTestsOnlyArg - value: '/p:RunSmokeTestsOnly=$(isNotManualAndIsPR)' - - ${{ if or(eq(parameters.osGroup, 'windows'), eq(parameters.hostedOs, 'windows')) }}: + value: '/p:RunSmokeTestsOnly=$(isNotExtraPlatformsBuild)' + + - name: _hostedOs + value: ${{ parameters.jobParameters.hostedOs }} + + - ${{ if or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')) }}: - name: archiveExtension value: '.zip' - name: archiveType @@ -69,7 +72,7 @@ jobs: - name: logRootNameArg value: 'log ' - - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.hostedOs, 'windows')) }}: + - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.jobParameters.hostedOs, 'windows')) }}: - name: archiveExtension value: '.tar.gz' - name: archiveType @@ -117,12 +120,12 @@ jobs: ${{ if eq(parameters.jobParameters.pool, '') }}: pool: # Public Linux Build Pool - ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: + ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open # Official Build Linux Pool - ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: + ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: name: NetCore1ESPool-Internal demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 @@ -136,7 +139,7 @@ jobs: demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019 # Public Windows Build Pool - ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}: + ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}: name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Open diff --git a/eng/pipelines/coreclr/templates/build-jit-job.yml b/eng/pipelines/coreclr/templates/build-jit-job.yml index c251c06f28679..b5ff3df213af3 100644 --- a/eng/pipelines/coreclr/templates/build-jit-job.yml +++ b/eng/pipelines/coreclr/templates/build-jit-job.yml @@ -107,10 +107,10 @@ jobs: # Build CoreCLR JIT - ${{ if ne(parameters.osGroup, 'windows') }}: - - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) -ci $(compilerArg) -component alljits + - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) -ci $(compilerArg) -component alljits -component spmi displayName: Build CoreCLR JIT - ${{ if eq(parameters.osGroup, 'windows') }}: - - script: set __TestIntermediateDir=int&&$(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) -ci -component alljits + - script: set __TestIntermediateDir=int&&$(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) -ci -component alljits -component spmi displayName: Build CoreCLR JIT - ${{ if eq(parameters.uploadAs, 'azureBlob') }}: @@ -118,7 +118,7 @@ jobs: - script: $(PipScript) install --user --upgrade pip && $(PipScript) install --user azure.storage.blob==12.5.0 --force-reinstall displayName: Upgrade Pip to latest and install azure-storage-blob Python package - - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/jitrollingbuild.py upload -build_type $(buildConfig) -arch $(archType) -host_os $(osGroup) -git_hash $(Build.SourceVersion) + - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/jitrollingbuild.py upload -build_type $(buildConfig) -arch $(archType) -host_os $(osGroup) -git_hash $(Build.SourceVersion) --use_latest_jit_change displayName: Upload JIT to Azure Storage env: CLRJIT_AZ_KEY: $(clrjit_key1) # secret key stored as variable in pipeline diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index b89cd621eda1e..9048e8ed4fe8a 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -132,10 +132,10 @@ jobs: value: '' - ${{ if ne(parameters.testGroup, 'innerloop') }}: - name: clrRuntimeComponentsBuildArg - value: '-component runtime -component alljits -component paltests -component nativeaot ' + value: '-component runtime -component alljits -component paltests -component nativeaot -component spmi ' - ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.archType, 'x86')) }}: - name: clrRuntimeComponentsBuildArg - value: '-component runtime -component jit -component iltools ' + value: '-component runtime -component jit -component iltools -component spmi ' - name: pgoInstrumentArg value: '' @@ -212,7 +212,7 @@ jobs: # Build CoreCLR Managed Components - ${{ if or(ne(parameters.osGroup, 'Linux'), ne(parameters.archType, 'x86')) }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib+clr.nativecorelib+clr.tools+clr.packages+clr.paltestlist $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+clr.paltestlist $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci displayName: Build managed product components and packages - ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.archType, 'x86')) }}: - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index 1a5a346758702..0b2e6f7f80ed2 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -21,6 +21,7 @@ jobs: archType: ${{ parameters.archType }} container: ${{ parameters.container }} pool: ${{ parameters.pool }} + platform: ${{ parameters.platform }} shouldContinueOnError: ${{ parameters.shouldContinueOnError }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths}} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index dd1ff0ebd3b24..627d42fd7add1 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -57,7 +57,7 @@ jobs: - ${{ if and(eq(parameters.runtimeType, 'mono'), ne(parameters.codeGenType, 'AOT')) }}: - ${{ format('mono_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if eq(parameters.runtimeType, 'wasm')}}: - - ${{ format('build_{0}{1}_{2}_{3}_{4}', 'Browser', '', 'wasm', parameters.buildConfig, parameters.runtimeType) }} + - ${{ format('build_{0}{1}_{2}_{3}_{4}_{5}', 'Browser', '', 'wasm', 'Linux', parameters.buildConfig, parameters.runtimeType) }} - ${{ if and(eq(parameters.codeGenType, 'AOT'), ne(parameters.runtimeType, 'wasm'))}}: - ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.codeGenType) }} - ${{ if eq(parameters.runtimeType, 'AndroidMono')}}: diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index ac074ab9903f8..f82e09c9e0a12 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -21,6 +21,7 @@ jobs: archType: ${{ parameters.archType }} container: ${{ parameters.container }} pool: ${{ parameters.pool }} + platform: ${{ parameters.platform }} shouldContinueOnError: ${{ parameters.shouldContinueOnError }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths}} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} @@ -28,26 +29,31 @@ jobs: # Linux arm - ${{ if eq(parameters.platform, 'Linux_arm') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Debian.10.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 - (Debian.11.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 + # Linux armv6 + - ${{ if eq(parameters.platform, 'Linux_armv6') }}: +# - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - (Raspbian.10.Armv6.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:raspbian-10-helix-arm32v6-20211215185610-60748cc + # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-20210106155927-56c6673 + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Ubuntu.2110.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-arm64v8-20211116135000-0f8d97e - - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-20210106155927-56c6673 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: - - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Alpine.313.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-amd64-20210910135845-8a6f4f3 # Linux musl arm64 - - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), eq(parameters.jobParameters.isFullMatrix, true)) }}: + - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true))) }}: - (Alpine.313.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm64v8-20210910135808-8a6f4f3 - (Alpine.314.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 @@ -62,21 +68,16 @@ jobs: - (Ubuntu.2110.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-amd64-20211116135132-0f8d97e - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Centos.7.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af - - (Centos.8.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - - RedHat.7.Amd64.Open - - Ubuntu.1804.Amd64.Open - - SLES.12.Amd64.Open + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125 - - (Ubuntu.2110.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-amd64-20211116135132-0f8d97e - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125 + - (Ubuntu.2110.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.04-helix-amd64-20210922170909-34a2d72 - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20210304164428-5a7c380 - - (Mariner.1.0.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620 - - (openSUSE.15.2.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20211018152525-9cc02fe - - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: - - (Centos.7.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af + - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620 + - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20211018152525-9cc02fe + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af - RedHat.7.Amd64.Open - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 - Ubuntu.1804.Amd64.Open @@ -94,10 +95,9 @@ jobs: # OSX x64 - ${{ if eq(parameters.platform, 'OSX_x64') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - OSX.1014.Amd64.Open - - OSX.1015.Amd64.Open - - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - OSX.1015.Amd64.Open # Android @@ -126,18 +126,18 @@ jobs: - ${{ if eq(parameters.platform, 'windows_x64') }}: # netcoreapp - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: + # libraries on mono outerloop - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - Windows.81.Amd64.Open - Windows.10.Amd64.Server19H1.Open + # libraries on coreclr (outerloop and innerloop), or libraries on mono innerloop - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - Windows.81.Amd64.Open + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.10.Amd64.ServerRS5.Open - - Windows.10.Amd64.Server19H1.Open - - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}: - - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 + - ${{ if ne(parameters.jobParameters.testScope, 'outerloop') }}: + - Windows.10.Amd64.Server19H1.Open - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c - - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}: + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.81.Amd64.Open - Windows.10.Amd64.Server19H1.ES.Open - Windows.11.Amd64.ClientPre.Open @@ -154,20 +154,18 @@ jobs: - ${{ if eq(parameters.platform, 'windows_x86') }}: # netcoreapp - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: + # mono outerloop - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - Windows.7.Amd64.Open - Windows.10.Amd64.ServerRS5.Open + # libraries on coreclr (outerloop and innerloop), or libraries on mono innerloop - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - Windows.7.Amd64.Open + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.10.Amd64.ServerRS5.Open - Windows.10.Amd64.Server19H1.Open - - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}: - - ${{ if eq(parameters.jobParameters.buildConfig, 'Release') }}: - - Windows.10.Amd64.Server19H1.ES.Open - - ${{ if eq(parameters.jobParameters.buildConfig, 'Debug') }}: - - Windows.7.Amd64.Open - - Windows.10.Amd64.Server19H1.Open + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - Windows.10.Amd64.Server19H1.ES.Open + - Windows.7.Amd64.Open # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: diff --git a/eng/pipelines/libraries/outerloop-mono.yml b/eng/pipelines/libraries/outerloop-mono.yml index 1267cf72a62de..17a7101e26004 100644 --- a/eng/pipelines/libraries/outerloop-mono.yml +++ b/eng/pipelines/libraries/outerloop-mono.yml @@ -23,7 +23,7 @@ jobs: platforms: - windows_x86 - Browser_wasm - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - windows_x64 - Linux_x64 - Linux_arm @@ -34,7 +34,7 @@ jobs: nameSuffix: AllSubsets_Mono buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true timeoutInMinutes: 180 - isFullMatrix: ${{ variables['isFullMatrix'] }} + includeAllPlatforms: ${{ variables['isRollingBuild'] }} # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -44,7 +44,7 @@ jobs: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - - ${{ if eq(variables['isFullMatrix'], false) }}: + - ${{ if eq(variables['isRollingBuild'], false) }}: - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml @@ -61,7 +61,7 @@ jobs: nameSuffix: AllSubsets_Mono buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true timeoutInMinutes: 180 - isFullMatrix: ${{ variables['isFullMatrix'] }} + includeAllPlatforms: ${{ variables['isRollingBuild'] }} # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: diff --git a/eng/pipelines/libraries/outerloop.yml b/eng/pipelines/libraries/outerloop.yml index 28932a0baff3c..72c2de49363a2 100644 --- a/eng/pipelines/libraries/outerloop.yml +++ b/eng/pipelines/libraries/outerloop.yml @@ -27,7 +27,7 @@ jobs: - ${{ if eq(variables['includeLinuxOuterloop'], true) }}: - Linux_x64 - Linux_musl_x64 - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - Linux_arm - Linux_arm64 - Linux_musl_arm64 @@ -46,27 +46,27 @@ jobs: platforms: - ${{ if eq(variables['includeWindowsOuterloop'], true) }}: - windows_x86 - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - windows_x64 - ${{ if eq(variables['includeLinuxOuterloop'], true) }}: - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - Linux_x64 - Linux_arm - Linux_arm64 - Linux_musl_x64 - Linux_musl_arm64 - - ${{ if and(eq(variables['includeOsxOuterloop'], true), eq(variables['isFullMatrix'], true)) }}: + - ${{ if and(eq(variables['includeOsxOuterloop'], true), eq(variables['isRollingBuild'], true)) }}: - OSX_arm64 - OSX_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: ${{ variables['isOfficialBuild'] }} - isFullMatrix: ${{ variables['isFullMatrix'] }} + includeAllPlatforms: ${{ variables['isRollingBuild'] }} runTests: true testScope: outerloop liveRuntimeBuildConfig: release - - ${{ if eq(variables['isFullMatrix'], false) }}: + - ${{ if eq(variables['isRollingBuild'], false) }}: - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/libraries/build-job.yml @@ -83,7 +83,7 @@ jobs: helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: ${{ variables['isOfficialBuild'] }} - isFullMatrix: ${{ variables['isFullMatrix'] }} + includeAllPlatforms: ${{ variables['isRollingBuild'] }} runTests: true testScope: outerloop liveRuntimeBuildConfig: release @@ -95,12 +95,12 @@ jobs: buildConfig: Release platforms: - windows_x86 - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - windows_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: ${{ variables['isOfficialBuild'] }} - isFullMatrix: ${{ variables['isFullMatrix'] }} + includeAllPlatforms: ${{ variables['isRollingBuild'] }} framework: net48 runTests: true testScope: outerloop diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index d864487760908..0f2070a49bfbf 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -191,4 +191,8 @@ jobs: - fullpgo_random_gdv - fullpgo_random_edge - fullpgo_random_gdv_edge + - jitosr + - jitosr_stress + - jitosr_stress_random + - jitosr_pgo diff --git a/eng/pipelines/libraries/variables.yml b/eng/pipelines/libraries/variables.yml index 9bb89d7d49384..2abd5adabe2c9 100644 --- a/eng/pipelines/libraries/variables.yml +++ b/eng/pipelines/libraries/variables.yml @@ -6,7 +6,7 @@ variables: value: $(Build.SourcesDirectory)/src/libraries - name: pipelinesPath value: /eng/pipelines/libraries - - name: isFullMatrix + - name: isRollingBuild value: ${{ notIn(variables['Build.Reason'], 'PullRequest') }} - name: includeWindowsOuterloop value: ${{ or(endsWith(variables['Build.DefinitionName'], 'windows'), endsWith(variables['Build.DefinitionName'], 'outerloop')) }} diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml index 5bebcc00a2663..f588ad52b0f33 100644 --- a/eng/pipelines/runtime-community.yml +++ b/eng/pipelines/runtime-community.yml @@ -46,7 +46,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -56,4 +56,4 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) diff --git a/eng/pipelines/runtime-manual.yml b/eng/pipelines/runtime-extra-platforms.yml similarity index 59% rename from eng/pipelines/runtime-manual.yml rename to eng/pipelines/runtime-extra-platforms.yml index 997849ed2b86c..a0642f4ab521c 100644 --- a/eng/pipelines/runtime-manual.yml +++ b/eng/pipelines/runtime-extra-platforms.yml @@ -1,295 +1,217 @@ +# This pipeline includes the platforms that we don't have resources to run on every PR but that we want +# to still have test coverage, we run this pipeline on a schedule and also developers can run it +# via /azp run command on PRs. This pipeline permits us to have the main runtime pipeline run the same +# platforms in PRs and Scheduled builds. + +# Setting batch to true, triggers one build at a time. +# if there is a push while a build in progress, it will wait, +# until the running build finishes, and produce a build with all the changes +# that happened during the last build. trigger: none +schedules: + - cron: "0 9,21 * * *" # run at 9:00 and 21:00 (UTC) which is 1:00 and 13:00 (PST). + displayName: Runtime extra main schedule + branches: + include: + - main + always: false # run only if there were changes since the last successful scheduled run. + - cron: "0 6,18 * * *" # run at 6:00 and 18:00 (UTC) which is 22:00 and 10:00 (PST). + displayName: Runtime extra release schedule + branches: + include: + - release/* + always: false # run only if there were changes since the last successful scheduled run. + variables: - template: /eng/pipelines/common/variables.yml jobs: # -# iOS/tvOS interp - requires AOT Compilation and Interp flags -# Build the whole product using Mono and run libraries tests +# Evaluate paths # -- 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 - runtimeFlavor: mono - platforms: - - iOSSimulator_x64 - - tvOSSimulator_x64 - - iOSSimulator_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - interpreter: true - testRunNamePrefixSuffix: Mono_$(_BuildConfig) +- ${{ if eq(variables.dependOnEvaluatePaths, true) }}: + - template: /eng/pipelines/common/evaluate-default-paths.yml # -# MacCatalyst interp - requires AOT Compilation and Interp flags -# Build the whole product using Mono and run libraries tests +# Build CoreCLR release +# Always as they are needed by Installer and we always build and test the Installer. # - 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 - runtimeFlavor: mono + jobTemplate: /eng/pipelines/coreclr/templates/build-job.yml + buildConfig: release platforms: - - MacCatalyst_x64 - # don't run tests on arm64 PRs until we can get significantly more devices - - ${{ if eq(variables['isFullMatrix'], true) }}: - - MacCatalyst_arm64 + - Linux_x64 + - Linux_arm + - Linux_arm64 + - Linux_musl_x64 + - OSX_x64 + - windows_x64 + - windows_x86 + - windows_arm64 jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - interpreter: true - testRunNamePrefixSuffix: Mono_$(_BuildConfig) # -# MacCatalyst interp - requires AOT Compilation and Interp flags -# Build the whole product using Mono and run libraries tests -# The test app is built with the App Sandbox entitlement +# Build libraries using live CoreLib # - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + jobTemplate: /eng/pipelines/libraries/build-job.yml buildConfig: Release - runtimeFlavor: mono platforms: - - MacCatalyst_x64 - # don't run tests on arm64 PRs until we can get significantly more devices - - ${{ if eq(variables['isFullMatrix'], true) }}: - - MacCatalyst_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono_AppSandbox - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true /p:EnableAppSandbox=true - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - interpreter: true - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + - Linux_x64 + - Linux_arm + - Linux_arm64 + - Linux_musl_x64 + - OSX_x64 + - windows_x64 + - windows_x86 + - windows_arm64 # -# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size -# Build the whole product using Mono and run libraries tests +# Libraries Release Test Execution against a release coreclr runtime +# Only when the PR contains a libraries change # - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + jobTemplate: /eng/pipelines/libraries/run-test-job.yml buildConfig: Release - runtimeFlavor: mono platforms: - - iOS_arm64 - - tvOS_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true - -# -# Build the whole product using Mono and run libraries tests -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml + - Linux_x64 + - Linux_arm + - Linux_arm64 + - Linux_musl_x64 + - OSX_x64 + - windows_x64 + - windows_x86 + - windows_arm64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Android_x86 - - Android_x64 jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + isOfficialBuild: false + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} + testScope: innerloop + liveRuntimeBuildConfig: release + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(variables['isRollingBuild'], true)) +# Run net48 tests on win-x64 - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + jobTemplate: /eng/pipelines/libraries/build-job.yml buildConfig: Release - runtimeFlavor: mono platforms: - - Android_arm - - Android_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - -# -# Build the whole product using Mono and run libraries tests -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml + - windows_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Windows_x64 jobParameters: + framework: net48 + runTests: true testScope: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true - timeoutInMinutes: 120 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(variables['isRollingBuild'], true)) + +#### MONO LEGS # -# Build the whole product using Mono for Android and run runtime tests with interpreter +# Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml buildConfig: Release runtimeFlavor: mono platforms: - - Android_x64 + # BuildWasmApps should only happen on the extra platforms build as we already have coverage for this build on PRs. + - Browser_wasm + - Browser_wasm_win variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 + # map dependencies variables to local variables + - name: wasmbuildtestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests_Interp - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 - runtimeVariant: monointerpreter + nameSuffix: WasmBuildTests + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs) + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:BrowserHost=$(_hostedOs) + scenarios: + - buildwasmapps + condition: >- + or( + eq(variables['wasmbuildtestsContainsChange'], true), + eq(variables['isRollingBuild'], true)) # -# Build the whole product using Mono and run runtime tests with the JIT. +# Build Browser_wasm, on windows, run console and browser tests # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: release runtimeFlavor: mono platforms: - - iOSSimulator_x64 + - Browser_wasm_win variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 + nameSuffix: LibraryTests + buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - -# -# Build the whole product using Mono for Android and run runtime tests with Android devices -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Android_arm64 - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 - # don't run tests on PRs until we can get significantly more devices - # Turn off the testing for now, until https://github.com/dotnet/xharness/issues/663 gets resolved - # ${{ if eq(variables['isFullMatrix'], true) }}: - # # extra steps, run tests - # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml - # extraStepsParameters: - # creator: dotnet-bot - # testRunNamePrefixSuffix: Mono_$(_BuildConfig) + testRunNamePrefixSuffix: Windows_wasm_$(_BuildConfig) + extraHelixArguments: /p:BrowserHost=windows + scenarios: + - normal + - wasmtestonbrowser + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # -# Build Browser_wasm, on windows, run console and browser tests +# Build for Browser/wasm, with EnableAggressiveTrimming=true # - 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 + buildConfig: Release runtimeFlavor: mono platforms: - - Browser_wasm_win + - Browser_wasm variables: # map dependencies variables to local variables - name: librariesContainsChange @@ -297,78 +219,86 @@ jobs: - name: monoContainsChange value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: Windows_wasm - buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows + nameSuffix: LibraryTests_EAT + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) scenarios: - normal - - WasmTestOnBrowser - - WasmTestOnNodeJs condition: >- or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) +# +# Build for Browser/wasm with RunAOTCompilation=true +# - 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 + buildConfig: Release runtimeFlavor: mono platforms: + - Browser_wasm - Browser_wasm_win variables: # map dependencies variables to local variables - - name: wasmbuildtestsContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: Windows_wasm_WBT - buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:TestWasmBuildTests=true /p:TestAssemblies=false + nameSuffix: LibraryTests_AOT + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true /p:BrowserHost=$(_hostedOs) timeoutInMinutes: 180 condition: >- or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows + testRunNamePrefixSuffix: Mono_AOT_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) /p:BrowserHost=$(_hostedOs) scenarios: - - buildwasmapps + - normal condition: >- or( - eq(variables['wasmbuildtestsContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) +# +# Build the whole product using Mono and run libraries tests +# - 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 + buildConfig: Release runtimeFlavor: mono platforms: - - Browser_wasm_win + - Windows_x64 variables: # map dependencies variables to local variables - name: librariesContainsChange @@ -376,34 +306,30 @@ jobs: - name: monoContainsChange value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: - testGroup: innerloop - nameSuffix: Windows_wasm_AOT - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) - timeoutInMinutes: 180 + testScope: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 120 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) - scenarios: - - normal condition: >- or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # -# Build for Browser/wasm, with EnableAggressiveTrimming=true +# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size +# Build the whole product using Mono and run libraries tests # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -412,7 +338,8 @@ jobs: buildConfig: Release runtimeFlavor: mono platforms: - - Browser_wasm + - iOS_arm64 + - tvOS_arm64 variables: # map dependencies variables to local variables - name: librariesContainsChange @@ -421,21 +348,26 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_EAT - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=false /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false + nameSuffix: AllSubsets_Mono + 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( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true /p:RunSmokeTestsOnly=false - scenarios: - - normal + extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) -# -# Build for Browser/wasm with RunAOTCompilation=true -# - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml @@ -443,7 +375,8 @@ jobs: buildConfig: Release runtimeFlavor: mono platforms: - - Browser_wasm + - Android_arm + - Android_arm64 variables: # map dependencies variables to local variables - name: librariesContainsChange @@ -452,17 +385,24 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_AOT - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=false /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true /p:RunSmokeTestsOnly=false - scenarios: - - normal + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # # Build for Browser/wasm and test it on v8, browser, and nodejs @@ -477,8 +417,6 @@ jobs: - Browser_wasm variables: # map dependencies variables to local variables - - name: librariesContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] - name: monoContainsChange value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: @@ -488,8 +426,8 @@ jobs: timeoutInMinutes: 180 condition: >- or( - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -501,44 +439,46 @@ jobs: - WasmTestOnNodeJs condition: >- or( - eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run runtime tests +# Build Mono release +# Only when libraries, mono, or the runtime tests changed +# Currently only these architectures are needed for the runtime tests. +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: release + platforms: + - Linux_arm64 + jobParameters: + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) + # +# Mono Test builds with CoreCLR runtime tests using live libraries debug build +# Only when Mono is changed - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release + jobTemplate: /eng/pipelines/common/templates/runtimes/build-test-job.yml + buildConfig: release runtimeFlavor: mono platforms: - - Browser_wasm - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 10 - - name: timeoutPerTestCollectionInMinutes - value: 200 + - CoreClrTestBuildHost # Either OSX_x64 or Linux_x64 jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 180 - # NOTE: Per PR test execution is not recommended for mobile runtime tests - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) # Wasm debugger tests - template: /eng/pipelines/common/platform-matrix.yml @@ -561,8 +501,7 @@ jobs: condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -586,14 +525,13 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: Windows_wasm_DebuggerTests + nameSuffix: Mono_DebuggerTests buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -630,9 +568,100 @@ jobs: nameSuffix: AllSubsets_Mono_RuntimeTests buildArgs: -s mono+libs -c $(_BuildConfig) timeoutInMinutes: 240 - # NOTE: Per PR test execution is not recommended for mobile runtime tests + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) + +# +# Build the whole product using Mono for Android and run runtime tests with interpreter +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Android_x64 + variables: + - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: pr/dotnet/runtime/$(Build.SourceBranch) + - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: ci/dotnet/runtime/$(Build.SourceBranch) + - name: timeoutPerTestInMinutes + value: 60 + - name: timeoutPerTestCollectionInMinutes + value: 180 + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono_RuntimeTests_Interp + buildArgs: -s mono+libs -c $(_BuildConfig) + timeoutInMinutes: 240 + runtimeVariant: monointerpreter + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) + # NOTE: Per PR test execution is not recommended for runtime tests + ${{ if eq(variables['isRollingBuild'], true) }}: + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + +# +# Mono CoreCLR runtime Test executions using live libraries in jit mode +# Only when Mono is changed +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/templates/runtimes/run-test-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - Linux_arm64 + helixQueueGroup: pr + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + jobParameters: + testGroup: innerloop + liveLibrariesBuildConfig: Release + liveRuntimeBuildConfig: release + runtimeVariant: minijit + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) + +# +# Mono CoreCLR runtime Test executions using live libraries in interpreter mode +# Only when Mono is changed +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/templates/runtimes/run-test-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - Linux_arm64 + helixQueueGroup: pr + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + jobParameters: + testGroup: innerloop + liveLibrariesBuildConfig: Release + liveRuntimeBuildConfig: release + runtimeVariant: monointerpreter + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index 34b0ae68c78e2..1ad7ad72d3171 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -416,7 +416,7 @@ stages: - Build_Android_arm64_release_AllSubsets_Mono - Build_Android_x86_release_AllSubsets_Mono - Build_Android_x64_release_AllSubsets_Mono - - Build_Browser_wasm_release_AllSubsets_Mono + - Build_Browser_wasm_Linux_release_AllSubsets_Mono - Build_iOS_arm_release_AllSubsets_Mono - Build_iOS_arm64_release_AllSubsets_Mono - Build_iOSSimulator_x64_release_AllSubsets_Mono diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index 4288d372433df..c51d639d29f0f 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -75,7 +75,7 @@ jobs: - iOSSimulator_x64 - tvOSSimulator_x64 # don't run tests on arm64 PRs until we can get significantly more devices - - ${{ if eq(variables['isManualOrIsNotPR'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - iOSSimulator_arm64 variables: # map dependencies variables to local variables @@ -93,8 +93,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -105,8 +104,7 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # MacCatalyst interp - requires AOT Compilation and Interp flags @@ -121,7 +119,7 @@ jobs: platforms: - MacCatalyst_x64 # don't run tests on arm64 PRs until we can get significantly more devices - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - MacCatalyst_arm64 variables: # map dependencies variables to local variables @@ -139,8 +137,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -149,10 +146,9 @@ jobs: testRunNamePrefixSuffix: Mono_$(_BuildConfig) condition: >- or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # # MacCatalyst interp - requires AOT Compilation and Interp flags @@ -168,7 +164,7 @@ jobs: platforms: - MacCatalyst_x64 # don't run tests on arm64 PRs until we can get significantly more devices - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - MacCatalyst_arm64 variables: # map dependencies variables to local variables @@ -185,8 +181,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -195,53 +190,9 @@ jobs: testRunNamePrefixSuffix: Mono_$(_BuildConfig) condition: >- or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) - -# -# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size -# Build the whole product using Mono and run libraries tests -# -- 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 - runtimeFlavor: mono - platforms: - - iOS_arm64 - - tvOS_arm64 - variables: - # map dependencies variables to local variables - - name: librariesContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] - - name: monoContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] - 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:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true - timeoutInMinutes: 180 - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true - condition: >- - or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run libraries tests @@ -271,8 +222,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -282,47 +232,7 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - -- 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 - runtimeFlavor: mono - platforms: - - Android_arm - - Android_arm64 - variables: - # map dependencies variables to local variables - - name: librariesContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] - - name: monoContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) - timeoutInMinutes: 180 - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - condition: >- - or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run libraries tests @@ -334,7 +244,7 @@ jobs: buildConfig: Release runtimeFlavor: mono platforms: - - Windows_x64 + - Linux_armv6 variables: # map dependencies variables to local variables - name: librariesContainsChange @@ -344,65 +254,17 @@ jobs: jobParameters: testScope: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + buildArgs: -s mono+clr+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true timeoutInMinutes: 120 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - condition: >- - or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - -# -# Build the whole product using Mono for Android and run runtime tests with interpreter -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Android_x64 - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests_Interp - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 - runtimeVariant: monointerpreter - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - # NOTE: Per PR test execution is not recommended for runtime tests - ${{ if eq(variables['isManualOrIsNotPR'], true) }}: + eq(variables['isRollingBuild'], true)) + ${{ if eq(variables['isRollingBuild'], true) }}: # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) @@ -438,9 +300,8 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - ${{ if eq(variables['isManualOrIsNotPR'], true) }}: + eq(variables['isRollingBuild'], true)) + ${{ if eq(variables['isRollingBuild'], true) }}: # extra steps, run tests extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml extraStepsParameters: @@ -448,46 +309,38 @@ jobs: testRunNamePrefixSuffix: Mono_$(_BuildConfig) # -# Build the whole product using Mono for Android and run runtime tests with Android devices +# Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml buildConfig: Release runtimeFlavor: mono platforms: - - Android_arm64 + - Browser_wasm_win variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 + # map dependencies variables to local variables + - name: wasmbuildtestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 + nameSuffix: WasmBuildTests + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs) + timeoutInMinutes: 180 condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) - # don't run tests on PRs until we can get significantly more devices - # Turn off the testing for now, until https://github.com/dotnet/runtime/issues/60128 gets resolved - # ${{ if eq(variables['isFullMatrix'], true) }}: - # # extra steps, run tests - # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml - # extraStepsParameters: - # creator: dotnet-bot - # testRunNamePrefixSuffix: Mono_$(_BuildConfig) + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:BrowserHost=$(_hostedOs) + scenarios: + - buildwasmapps + condition: >- + eq(variables['wasmbuildtestsContainsChange'], true) # # Build Browser_wasm, on windows, run console and browser tests @@ -508,41 +361,37 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: Windows_wasm - buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows $(_runSmokeTestsOnlyArg) + nameSuffix: LibraryTests + buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows $(_runSmokeTestsOnlyArg) + testRunNamePrefixSuffix: Windows_wasm_$(_BuildConfig) + extraHelixArguments: /p:BrowserHost=windows scenarios: - normal - - WasmTestOnBrowser + - wasmtestonbrowser condition: >- or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # -# Build Browser_wasm, on windows, and run tests with AOT +# Build for Browser/wasm with RunAOTCompilation=true # -# Disabled due to https://github.com/dotnet/runtime/issues/61721 - 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 + buildConfig: Release runtimeFlavor: mono platforms: - Browser_wasm_win @@ -553,55 +402,49 @@ jobs: - name: monoContainsChange value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: Windows_wasm_AOT - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) + nameSuffix: LibraryTests_AOT + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true /p:BrowserHost=$(_hostedOs) timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) + testRunNamePrefixSuffix: Mono_AOT_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) /p:BrowserHost=$(_hostedOs) scenarios: - normal condition: >- or( eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['monoContainsChange'], true)) -# -# Build Browser_wasm, on windows, and run Wasm.Build.Tests -# +# Wasm debugger tests - windows - 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 + buildConfig: Release runtimeFlavor: mono platforms: - Browser_wasm_win variables: # map dependencies variables to local variables - - name: wasmbuildtestsContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] + - name: wasmdebuggertestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: Windows_wasm_WBT - buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:TestWasmBuildTests=true /p:TestAssemblies=false + nameSuffix: Mono_DebuggerTests + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows timeoutInMinutes: 180 condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -609,12 +452,7 @@ jobs: testRunNamePrefixSuffix: Mono_$(_BuildConfig) extraHelixArguments: /p:BrowserHost=windows scenarios: - - buildwasmapps - condition: >- - or( - eq(variables['wasmbuildtestsContainsChange'], true), - eq(variables['isManualOrIsNotPR'], true), - eq(variables['isFullMatrix'], true)) + - wasmdebuggertests # Wasm debugger tests - template: /eng/pipelines/common/platform-matrix.yml @@ -635,9 +473,7 @@ jobs: buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false timeoutInMinutes: 180 condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -646,36 +482,46 @@ jobs: scenarios: - wasmdebuggertests -# Wasm debugger tests - windows +# +# Build the whole product using Mono for Android and run runtime tests with Android devices +# - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml buildConfig: Release runtimeFlavor: mono platforms: - - Browser_wasm_win + - Android_arm64 variables: - # map dependencies variables to local variables - - name: wasmdebuggertestsContainsChange - value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] + - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: pr/dotnet/runtime/$(Build.SourceBranch) + - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: ci/dotnet/runtime/$(Build.SourceBranch) + - name: timeoutPerTestInMinutes + value: 60 + - name: timeoutPerTestCollectionInMinutes + value: 180 jobParameters: testGroup: innerloop - nameSuffix: Windows_wasm_DebuggerTests - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows - timeoutInMinutes: 180 + nameSuffix: AllSubsets_Mono_RuntimeTests + buildArgs: -s mono+libs -c $(_BuildConfig) + timeoutInMinutes: 240 condition: >- or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true), - eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=windows - scenarios: - - wasmdebuggertests + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isRollingBuild'], true)) + # don't run tests on PRs until we can get significantly more devices + # Turn off the testing for now, until https://github.com/dotnet/runtime/issues/60128 gets resolved + # ${{ if eq(variables['isRollingBuild'], true) }}: + # # extra steps, run tests + # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + # extraStepsParameters: + # creator: dotnet-bot + # testRunNamePrefixSuffix: Mono_$(_BuildConfig) # # CoreCLR Build for running Apple Silicon libraries-innerloop @@ -685,7 +531,7 @@ jobs: jobTemplate: /eng/pipelines/coreclr/templates/build-job.yml buildConfig: release platforms: - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - OSX_arm64 jobParameters: testGroup: innerloop @@ -697,12 +543,11 @@ jobs: jobTemplate: /eng/pipelines/libraries/build-job.yml buildConfig: Release platforms: - - ${{ if eq(variables['isFullMatrix'], true) }}: + - ${{ if eq(variables['isRollingBuild'], true) }}: - OSX_arm64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: ${{ variables['isOfficialBuild'] }} - isFullMatrix: ${{ variables['isFullMatrix'] }} runTests: true testScope: innerloop liveRuntimeBuildConfig: release diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 5d7f3ffde2f81..9d3bbfe477d8e 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -91,7 +91,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build the whole product using GNU compiler toolchain @@ -114,7 +114,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build CoreCLR OSX_x64 checked @@ -133,7 +133,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build CoreCLR release @@ -178,7 +178,7 @@ jobs: # # Build CoreCLR Formatting Job # Only when CoreCLR is changed, and only in the 'main' branch (no release branches; -# both CI and PR builds). +# both Rolling and PR builds). # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -194,7 +194,7 @@ jobs: eq(variables['System.PullRequest.TargetBranch'], 'main')), or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr_jit.containsChange'], true), - eq(variables['isFullMatrix'], true))) + eq(variables['isRollingBuild'], true))) # # CoreCLR NativeAOT debug build and smoke tests @@ -211,7 +211,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -233,7 +233,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -257,7 +257,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -277,7 +277,7 @@ jobs: condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # Build Mono AOT offset headers once, for consumption elsewhere # Only when mono changed @@ -297,7 +297,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # Build the whole product using Mono runtime # Only when libraries, mono or installer are changed @@ -323,7 +323,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -343,7 +343,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run libraries tests, multi-scenario @@ -364,7 +364,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono + nameSuffix: LibraryTests buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true timeoutInMinutes: 180 condition: >- @@ -372,7 +372,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -385,7 +385,7 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests @@ -404,13 +404,13 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_WasmBuildTests + nameSuffix: WasmBuildTests buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -420,8 +420,8 @@ jobs: - buildwasmapps condition: >- or( - eq(variables['wasmbuildtestsContainsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['wasmbuildtestsContainsChange'], true), + eq(variables['isRollingBuild'], true)) # # Build for Browser/wasm, with EnableAggressiveTrimming=true @@ -442,7 +442,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_EAT + nameSuffix: LibraryTests_EAT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false timeoutInMinutes: 180 condition: >- @@ -450,7 +450,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -463,7 +463,7 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build for Browser/wasm with RunAOTCompilation=true @@ -484,7 +484,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_AOT + nameSuffix: LibraryTests_AOT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true timeoutInMinutes: 180 condition: >- @@ -492,7 +492,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -505,29 +505,7 @@ jobs: or( eq(variables['librariesContainsChange'], true), eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) - -# Build and test libraries under single-file publishing -- 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 - - Linux_x64 - jobParameters: - testGroup: innerloop - isFullMatrix: ${{ variables.isFullMatrix }} - isSingleFile: true - nameSuffix: SingleFile - buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) /p:TestSingleFile=true /p:ArchiveTests=true - timeoutInMinutes: 120 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: SingleFile_$(_BuildConfig) + eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono and run runtime tests @@ -557,49 +535,35 @@ jobs: buildArgs: -s mono+libs -c $(_BuildConfig) timeoutInMinutes: 180 condition: >- - eq(variables['isFullMatrix'], true) - # NOTE: Per PR test execution is not recommended for mobile runtime tests - # extra steps, run tests + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) extraStepsTemplate: /eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml extraStepsParameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) -# -# Build the whole product using Mono for Android and run runtime tests with Android emulator -# +# Build and test libraries under single-file publishing - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml buildConfig: Release - runtimeFlavor: mono platforms: - - Android_x64 - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 + - windows_x64 + - Linux_x64 jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 240 - condition: >- - eq(variables['isFullMatrix'], true) - # NOTE: Per PR test execution is not recommended for mobile runtime tests + isSingleFile: true + nameSuffix: SingleFile + buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) /p:TestSingleFile=true /p:ArchiveTests=true + timeoutInMinutes: 120 # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + testRunNamePrefixSuffix: SingleFile_$(_BuildConfig) # # Build Mono and Installer on LLVMJIT mode @@ -621,7 +585,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -641,7 +605,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono and Installer on LLVMAOT mode @@ -664,7 +628,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -683,7 +647,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono debug @@ -709,7 +673,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono release AOT cross-compilers @@ -740,7 +704,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -767,7 +731,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono release @@ -790,7 +754,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono release @@ -810,7 +774,7 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build Mono release with LLVM AOT @@ -830,7 +794,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Build libraries using live CoreLib @@ -849,8 +813,6 @@ jobs: - windows_arm - windows_arm64 - windows_x86 - jobParameters: - liveRuntimeBuildConfig: release - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -864,9 +826,12 @@ jobs: - OSX_x64 - windows_x64 - FreeBSD_x64 + - ${{ if eq(variables['isRollingBuild'], false) }}: + # we need to build windows_x86 for debug on PRs in order to test + # against a checked runtime when the PR contains coreclr changes + - windows_x86 jobParameters: testScope: innerloop - liveRuntimeBuildConfig: release # # Libraries Build that only run when coreclr is changed @@ -874,7 +839,7 @@ jobs: # and those are already built above # -- ${{ if eq(variables['isFullMatrix'], false) }}: +- ${{ if eq(variables['isRollingBuild'], false) }}: - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/libraries/build-job.yml @@ -884,45 +849,24 @@ jobs: - Linux_musl_arm - Linux_musl_arm64 jobParameters: - liveRuntimeBuildConfig: release condition: >- eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true) -# -# Libraries Build that only run when libraries is changed -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/libraries/build-job.yml - buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} - platforms: - - ${{ if eq(variables['isFullMatrix'], false) }}: - - windows_x86 - jobParameters: - liveRuntimeBuildConfig: release - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) - - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/libraries/build-job.yml buildConfig: Release platforms: - windows_x86 - - ${{ if eq(variables['isFullMatrix'], true) }}: - - windows_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: - isFullMatrix: ${{ variables.isFullMatrix }} framework: net48 runTests: true testScope: innerloop condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -931,14 +875,13 @@ jobs: platforms: - windows_x64 jobParameters: - isFullMatrix: ${{ variables.isFullMatrix }} framework: allConfigurations runTests: true useHelix: false condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Installer Build and Test @@ -1006,7 +949,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # CoreCLR Test executions using live libraries @@ -1029,7 +972,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -1049,7 +992,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -1065,7 +1008,7 @@ jobs: condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr_AppleSilicon.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Mono Test builds with CoreCLR runtime tests using live libraries debug build @@ -1083,7 +1026,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Mono CoreCLR runtime Test executions using live libraries in jit mode @@ -1095,8 +1038,6 @@ jobs: runtimeFlavor: mono platforms: - OSX_x64 - - ${{ if eq(variables['isFullMatrix'], true) }}: - - Linux_arm64 helixQueueGroup: pr helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: @@ -1108,7 +1049,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Mono CoreCLR runtime Test executions using live libraries in interpreter mode @@ -1120,8 +1061,6 @@ jobs: runtimeFlavor: mono platforms: - OSX_x64 - - ${{ if eq(variables['isFullMatrix'], true) }}: - - Linux_arm64 helixQueueGroup: pr helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: @@ -1133,7 +1072,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Mono CoreCLR runtime Test executions using live libraries and LLVM AOT # Only when Mono is changed @@ -1158,7 +1097,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Mono CoreCLR runtime Test executions using live libraries and LLVM Full AOT @@ -1171,8 +1110,7 @@ jobs: runtimeFlavor: mono platforms: - Linux_x64 - # Disabled pending outcome of https://github.com/dotnet/runtime/issues/60234 investigation - #- Linux_arm64 + - Linux_arm64 helixQueueGroup: pr helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: @@ -1184,7 +1122,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Release Test Execution against a release mono runtime. @@ -1203,7 +1141,6 @@ jobs: helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: false - isFullMatrix: ${{ variables.isFullMatrix }} runtimeDisplayName: mono testScope: innerloop liveRuntimeBuildConfig: release @@ -1211,7 +1148,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Release Test Execution against a release mono interpreter runtime. @@ -1229,7 +1166,6 @@ jobs: helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: false - isFullMatrix: ${{ variables.isFullMatrix }} interpreter: true runtimeDisplayName: mono_interpreter testScope: innerloop @@ -1238,7 +1174,7 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Release Test Execution against a release coreclr runtime @@ -1250,18 +1186,15 @@ jobs: buildConfig: Release platforms: - windows_x86 - - ${{ if eq(variables['isFullMatrix'], true) }}: - - windows_arm64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: false - isFullMatrix: ${{ variables.isFullMatrix }} testScope: innerloop liveRuntimeBuildConfig: release condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Debug Test Execution against a release coreclr runtime @@ -1276,20 +1209,15 @@ jobs: - OSX_x64 - Linux_x64 - Linux_musl_x64 - - ${{ if eq(variables['isFullMatrix'], true) }}: - - Linux_arm64 - - ${{ if eq(variables['isFullMatrix'], false) }}: - - windows_x86 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: isOfficialBuild: false - isFullMatrix: ${{ variables.isFullMatrix }} testScope: innerloop liveRuntimeBuildConfig: release condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Test Execution against a checked runtime @@ -1313,7 +1241,7 @@ jobs: condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) # # Libraries Test Execution against a checked runtime @@ -1335,7 +1263,7 @@ jobs: condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -1352,4 +1280,4 @@ jobs: or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(variables['isFullMatrix'], true)) + eq(variables['isRollingBuild'], true)) diff --git a/eng/pipelines/runtimelab.yml b/eng/pipelines/runtimelab.yml index 9f1cd90822e83..27e954a9a7026 100644 --- a/eng/pipelines/runtimelab.yml +++ b/eng/pipelines/runtimelab.yml @@ -190,7 +190,7 @@ stages: - Linux_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: - isFullMatrix: false + isRollingBuild: false isOfficialBuild: false testScope: innerloop liveRuntimeBuildConfig: Release @@ -207,7 +207,7 @@ stages: - windows_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: - isFullMatrix: false + isRollingBuild: false isOfficialBuild: false testScope: innerloop liveRuntimeBuildConfig: Release diff --git a/eng/targetingpacks.targets b/eng/targetingpacks.targets index 4213c84e709d9..150ddf7401c9e 100644 --- a/eng/targetingpacks.targets +++ b/eng/targetingpacks.targets @@ -43,13 +43,13 @@ RuntimeFrameworkName="$(LocalFrameworkOverrideName)" LatestRuntimeFrameworkVersion="$(ProductVersion)" RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.Mono.**RID**" - RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-loongarch64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;browser-wasm;ios-arm64;ios-arm;iossimulator-arm64;iossimulator-x64;iossimulator-x86;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" + RuntimePackRuntimeIdentifiers="linux-arm;linux-armv6;linux-arm64;linux-musl-arm64;linux-loongarch64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;browser-wasm;ios-arm64;ios-arm;iossimulator-arm64;iossimulator-x64;iossimulator-x86;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" RuntimePackLabels="Mono" Condition="'@(KnownRuntimePack)' == '' or !@(KnownRuntimePack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/testing/tests.props b/eng/testing/tests.props index 86c661d4bb281..3025ab6233504 100644 --- a/eng/testing/tests.props +++ b/eng/testing/tests.props @@ -7,6 +7,7 @@ $(TestDependsOn);GenerateRunScript;RunTests true $(MSBuildThisFileDirectory)ILLinkDescriptors\ + true diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets index 85ee6deb32db3..e6783add3640a 100644 --- a/eng/testing/tests.singlefile.targets +++ b/eng/testing/tests.singlefile.targets @@ -12,7 +12,7 @@ chmod +rwx $(AssemblyName) && ./$(AssemblyName) - + true true true @@ -20,6 +20,30 @@ $(SingleFileHostSourcePath).exe + + $(CoreCLRILCompilerDir) + $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll + $(CoreCLRAotSdkDir) + $(NetCoreAppCurrentTestHostSharedFrameworkPath) + $(NoWarn);IL3050;IL3052;IL3055;IL1005 + false + + + true + + + + + + + + + + + + + + diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 191d2c2295690..bed571a306402 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -29,13 +29,13 @@ See also eng\testing\WasmRunnerTemplate.sh --> - + - + diff --git a/eng/testing/xunit/xunit.props b/eng/testing/xunit/xunit.props index 3f9c4b67141a2..a2ed68f1ecbc9 100644 --- a/eng/testing/xunit/xunit.props +++ b/eng/testing/xunit/xunit.props @@ -10,6 +10,7 @@ + diff --git a/global.json b/global.json index f191cfdd2e352..43ff763c74d86 100644 --- a/global.json +++ b/global.json @@ -12,12 +12,12 @@ "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.22056.6", - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22056.6", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22056.6", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22056.6", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.22075.6", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22075.6", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22075.6", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22075.6", "Microsoft.Build.NoTargets": "3.1.0", "Microsoft.Build.Traversal": "3.0.23", - "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.22059.2" + "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.22073.5" } } diff --git a/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj b/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj index db820d395a125..685f941510195 100644 --- a/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj +++ b/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj @@ -15,7 +15,7 @@ lib\netstandard2.0\ILVerification.dll - 1.8.1 + $(SystemReflectionMetadataVersion) netstandard2.0 Build,Analyzers diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 2440f6ca999ca..38e5488938b6d 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -247,7 +247,6 @@ add_subdirectory(debug) add_subdirectory(binder) add_subdirectory(classlibnative) add_subdirectory(dlls) -add_subdirectory(ToolBox) add_subdirectory(tools) add_subdirectory(unwinder) add_subdirectory(interop) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index e1230d59401d8..3d21bffd3d24f 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -140,8 +140,6 @@ - - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs deleted file mode 100644 index dc2a0a05708c1..0000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** -** Represents address Kinds used with local variables, parameters, and -** fields. -** -** -===========================================================*/ -// Only statics, does not need to be marked with the serializable attribute - -namespace System.Diagnostics.SymbolStore -{ - internal enum SymAddressKind - { - // ILOffset: addr1 = IL local var or param index. - ILOffset = 1, - - // NativeRVA: addr1 = RVA into module. - NativeRVA = 2, - - // NativeRegister: addr1 = register the var is stored in. - NativeRegister = 3, - - // NativeRegisterRelative: addr1 = register, addr2 = offset. - NativeRegisterRelative = 4, - - // NativeOffset: addr1 = offset from start of parent. - NativeOffset = 5, - - // NativeRegisterRegister: addr1 = reg low, addr2 = reg high. - NativeRegisterRegister = 6, - - // NativeRegisterStack: addr1 = reg low, addr2 = reg stk, addr3 = offset. - NativeRegisterStack = 7, - - // NativeStackRegister: addr1 = reg stk, addr2 = offset, addr3 = reg high. - NativeStackRegister = 8, - - // BitField: addr1 = field start, addr = field length. - BitField = 9, - - // NativeSectionOffset: addr1 = section, addr = offset - NativeSectionOffset = 10, - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs deleted file mode 100644 index fbd9f7e4bc1ae..0000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** Small value class used by the SymbolStore package for passing -** around metadata tokens. -** -===========================================================*/ - -using System.Diagnostics.CodeAnalysis; - -namespace System.Diagnostics.SymbolStore -{ - internal struct SymbolToken - { - internal int m_token; - - public SymbolToken(int val) { m_token = val; } - - public int GetToken() { return m_token; } - - public override int GetHashCode() { return m_token; } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is SymbolToken) - return Equals((SymbolToken)obj); - else - return false; - } - - public bool Equals(SymbolToken obj) - { - return obj.m_token == m_token; - } - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs index c86aa1b2e62bf..a619dc4b1ca79 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs @@ -16,14 +16,6 @@ namespace System { public static partial class Math { - [Intrinsic] - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern double Abs(double value); - - [Intrinsic] - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern float Abs(float value); - [Intrinsic] [MethodImpl(MethodImplOptions.InternalCall)] public static extern double Acos(double d); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs index f45b3837abdd9..bfe5bcce8db99 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs @@ -11,18 +11,6 @@ namespace System.Reflection { public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable { - public AssemblyName(string assemblyName) - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - nInit(); - } - internal AssemblyName(string? name, byte[]? publicKey, byte[]? publicKeyToken, @@ -44,23 +32,6 @@ internal AssemblyName(string? name, _flags = flags; } - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern void nInit(); - - // This call opens and closes the file, but does not add the - // assembly to the domain. - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern AssemblyName nGetFileInformation(string s); - - internal static AssemblyName GetFileInformationCore(string assemblyFile) - { - string fullPath = Path.GetFullPath(assemblyFile); - return nGetFileInformation(fullPath); - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern byte[]? ComputePublicKeyToken(); - internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) { #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 70cd4fb988f08..9def7541aa4c6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -314,14 +314,7 @@ public ModuleBuilder DefineDynamicModule(string name) private ModuleBuilder DefineDynamicModuleInternalNoLock(string name) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') { throw new ArgumentException(SR.Argument_InvalidName, nameof(name)); @@ -467,14 +460,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers /// The name of module for the look up. private ModuleBuilder? GetDynamicModuleNoLock(string name) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); for (int i = 0; i < _assemblyData._moduleBuilderList.Count; i++) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs index e4c35c9dbbc03..c3e22c5d34071 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs @@ -20,17 +20,12 @@ public sealed class FieldBuilder : FieldInfo internal FieldBuilder(TypeBuilder typeBuilder, string fieldName, Type type, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, FieldAttributes attributes) { - if (fieldName == null) - throw new ArgumentNullException(nameof(fieldName)); - - if (fieldName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(fieldName)); + ArgumentException.ThrowIfNullOrEmpty(fieldName); if (fieldName[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(fieldName)); - if (type == null) - throw new ArgumentNullException(nameof(type)); + ArgumentNullException.ThrowIfNull(type); if (type == typeof(void)) throw new ArgumentException(SR.Argument_BadFieldType); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index 275cecbead57a..1b35f5cdbb15f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -1273,11 +1273,7 @@ public virtual void UsingNamespace(string usingNamespace) // Specifying the namespace to be used in evaluating locals and watches // for the current active lexical scope. - if (usingNamespace == null) - throw new ArgumentNullException(nameof(usingNamespace)); - - if (usingNamespace.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(usingNamespace)); + ArgumentException.ThrowIfNullOrEmpty(usingNamespace); MethodBuilder? methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) 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 176f5a3fd3729..9d11aacaf53ea 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 @@ -61,24 +61,18 @@ internal MethodBuilder(string name, MethodAttributes attributes, CallingConventi Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers, ModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TypeBuilder type) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); - if (mod == null) - throw new ArgumentNullException(nameof(mod)); + ArgumentNullException.ThrowIfNull(mod); if (parameterTypes != null) { foreach (Type t in parameterTypes) { - if (t == null) - throw new ArgumentNullException(nameof(parameterTypes)); + ArgumentNullException.ThrowIfNull(t, nameof(parameterTypes)); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index fe5da8367cdd4..cbe0a7b39dde5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -233,7 +233,7 @@ private int GetTypeRefNested(Type type, Module? refedModule, string? strRefedMod typeName = UnmangleTypeName(typeName); } - Debug.Assert(!type.IsByRef, "Must not be ByRef."); + Debug.Assert(!type.IsByRef, "Must not be ByRef. Get token from TypeSpec."); Debug.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments."); ModuleBuilder thisModule = this; @@ -948,14 +948,7 @@ private MethodBuilder DefineGlobalMethodNoLock(string name, MethodAttributes att { throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated); } - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); if ((attributes & MethodAttributes.Static) == 0) { throw new ArgumentException(SR.Argument_GlobalFunctionHasToBeStatic); @@ -1081,19 +1074,16 @@ private int GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition) // instructions. Tokens are always relative to the Module. For example, // the token value for System.String is likely to be different from // Module to Module. Calling GetTypeToken will cause a reference to be - // added to the Module. This reference becomes a perminate part of the Module, - // multiple calles to this method with the same class have no additional side affects. - // This function is optimized to use the TypeDef token if Type is within the same module. - // We should also be aware of multiple dynamic modules and multiple implementation of Type!!! - if (type.IsByRef) - { - throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); - } - - if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) || - type.IsGenericParameter || - type.IsArray || - type.IsPointer) + // added to the Module. This reference becomes a permanent part of the Module, + // multiple calls to this method with the same class have no additional side-effects. + // This function is optimized to use the TypeDef token if the Type is within the + // same module. We should also be aware of multiple dynamic modules and multiple + // implementations of a Type. + if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) + || type.IsGenericParameter + || type.IsArray + || type.IsPointer + || type.IsByRef) { byte[] sig = SignatureHelper.GetTypeSigToken(this, type).InternalGetSignature(out int length); return GetTokenFromTypeSpec(sig, length); @@ -1355,18 +1345,8 @@ internal int GetArrayMethodToken(Type arrayClass, string methodName, CallingConv private int GetArrayMethodTokenNoLock(Type arrayClass, string methodName, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes) { - if (arrayClass == null) - { - throw new ArgumentNullException(nameof(arrayClass)); - } - if (methodName == null) - { - throw new ArgumentNullException(nameof(methodName)); - } - if (methodName.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(methodName)); - } + ArgumentNullException.ThrowIfNull(arrayClass); + ArgumentException.ThrowIfNullOrEmpty(methodName); if (!arrayClass.IsArray) { throw new ArgumentException(SR.Argument_HasToBeArrayClass); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs index ae6e704b2a5c8..89accc39caeb9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs @@ -34,10 +34,7 @@ internal PropertyBuilder( int prToken, // the metadata token for this property TypeBuilder containingType) // the containing type { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs index 6d9b8121fa6b4..ad80acad07835 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs @@ -480,11 +480,7 @@ internal TypeBuilder( string fullname, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, ModuleBuilder module, PackingSize iPackingSize, int iTypeSize, TypeBuilder? enclosingType) { - if (fullname == null) - throw new ArgumentNullException(nameof(fullname)); - - if (fullname.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(fullname)); + ArgumentException.ThrowIfNullOrEmpty(fullname); if (fullname[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(fullname)); @@ -581,11 +577,7 @@ private FieldBuilder DefineDataHelper(string name, byte[]? data, int size, Field FieldBuilder fdBuilder; TypeAttributes typeAttributes; - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (size <= 0 || size >= 0x003f0000) throw new ArgumentException(SR.Argument_BadSizeForData); @@ -1282,11 +1274,7 @@ private MethodBuilder DefineMethodNoLock(string name, MethodAttributes attribute Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); AssemblyBuilder.CheckContext(returnType); AssemblyBuilder.CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes); @@ -1374,23 +1362,9 @@ private MethodBuilder DefinePInvokeMethodHelper( lock (SyncRoot) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - - if (dllName == null) - throw new ArgumentNullException(nameof(dllName)); - - if (dllName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(dllName)); - - if (importName == null) - throw new ArgumentNullException(nameof(importName)); - - if (importName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(importName)); + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(dllName); + ArgumentException.ThrowIfNullOrEmpty(importName); if ((attributes & MethodAttributes.Abstract) != 0) throw new ArgumentException(SR.Argument_BadPInvokeMethod); @@ -1792,10 +1766,7 @@ private PropertyBuilder DefinePropertyNoLock(string name, PropertyAttributes att Type returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); AssemblyBuilder.CheckContext(returnType); AssemblyBuilder.CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes); @@ -1847,10 +1818,7 @@ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type ev private EventBuilder DefineEventNoLock(string name, EventAttributes attributes, Type eventtype) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); @@ -1922,7 +1890,9 @@ private EventBuilder DefineEventNoLock(string name, EventAttributes attributes, int tkParent = 0; if (m_typeParent != null) + { tkParent = m_module.GetTypeTokenInternal(m_typeParent); + } ModuleBuilder module = m_module; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index 9368fc25d340b..cdc15dc8fb6e0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -194,7 +194,9 @@ public int this[int index] } } +#pragma warning disable CA1066 // IEquatable interface implementation isn't used internal readonly struct MetadataImport +#pragma warning restore CA1067 { private readonly IntPtr m_metadataImport2; private readonly object? m_keepalive; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 977d73e5c3b99..3708e71cb4510 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -558,8 +558,7 @@ private static partial void GetTypeByName(string name, bool throwOnError, bool i internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule scope) { - if (string.IsNullOrEmpty(name)) - throw new ArgumentException(null, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); RuntimeType? type = null; GetTypeByNameUsingCARules(name, new QCallModule(ref scope), ObjectHandleOnStack.Create(ref type)); @@ -1246,7 +1245,7 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) } } - public unsafe partial struct ModuleHandle + public unsafe partial struct ModuleHandle : IEquatable { #region Public Static Members public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index a0d7026b54407..bf83df6c0f975 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -1941,7 +1941,7 @@ private static PropertyInfo GetPropertyInfo(RuntimeType reflectedType, int tkPro } Debug.Fail("Unreachable code"); - throw new SystemException(); + throw new UnreachableException(); } internal static void ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception? e) diff --git a/src/coreclr/ToolBox/CMakeLists.txt b/src/coreclr/ToolBox/CMakeLists.txt deleted file mode 100644 index 4e7f4368681d1..0000000000000 --- a/src/coreclr/ToolBox/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(SOS) -add_subdirectory(superpmi) diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 830c673ea06a6..7b48a0a90ce83 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -972,7 +972,7 @@ namespace BINDER_SPACE { // Search Assembly.ni.dll, then Assembly.dll // The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies. - SString candidates[] = { W(".ni.dll"), W(".dll") }; + const WCHAR* const candidates[] = { W(".ni.dll"), W(".dll") }; // Loop through the binding paths looking for a matching assembly for (int i = 0; i < 2; i++) diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index 499e20d928887..e349b99b3c14e 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -176,8 +176,8 @@ namespace BinderTracing { static thread_local bool t_AssemblyLoadStartInProgress = false; - AssemblyBindOperation::AssemblyBindOperation(AssemblySpec *assemblySpec, const WCHAR *assemblyPath) - : m_bindRequest { assemblySpec, nullptr, assemblyPath } + AssemblyBindOperation::AssemblyBindOperation(AssemblySpec *assemblySpec, const SString& assemblyPath) + : m_bindRequest { assemblySpec, SString::Empty(), assemblyPath } , m_populatedBindRequest { false } , m_checkedIgnoreBind { false } , m_ignoreBind { false } diff --git a/src/coreclr/binder/inc/assemblyidentity.hpp b/src/coreclr/binder/inc/assemblyidentity.hpp index cc0916c8780af..ef4768d3b8cd9 100644 --- a/src/coreclr/binder/inc/assemblyidentity.hpp +++ b/src/coreclr/binder/inc/assemblyidentity.hpp @@ -30,12 +30,9 @@ namespace BINDER_SPACE IDENTITY_FLAG_PUBLIC_KEY_TOKEN = 0x004, IDENTITY_FLAG_PUBLIC_KEY = 0x008, IDENTITY_FLAG_CULTURE = 0x010, - IDENTITY_FLAG_LANGUAGE = 0x020, IDENTITY_FLAG_PROCESSOR_ARCHITECTURE = 0x040, IDENTITY_FLAG_RETARGETABLE = 0x080, IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL = 0x100, - IDENTITY_FLAG_CUSTOM = 0x200, - IDENTITY_FLAG_CUSTOM_NULL = 0x400, IDENTITY_FLAG_CONTENT_TYPE = 0x800, IDENTITY_FLAG_FULL_NAME = (IDENTITY_FLAG_SIMPLE_NAME | IDENTITY_FLAG_VERSION) @@ -50,7 +47,6 @@ namespace BINDER_SPACE // Need to pre-populate SBuffers because of bogus asserts static const BYTE byteArr[] = { 0 }; m_publicKeyOrTokenBLOB.SetImmutable(byteArr, sizeof(byteArr)); - m_customBLOB.SetImmutable(byteArr, sizeof(byteArr)); } ~AssemblyIdentity() { @@ -83,7 +79,6 @@ namespace BINDER_SPACE SBuffer m_publicKeyOrTokenBLOB; PEKIND m_kProcessorArchitecture; AssemblyContentType m_kContentType; - SBuffer m_customBLOB; DWORD m_dwIdentityFlags; }; diff --git a/src/coreclr/binder/inc/bindertracing.h b/src/coreclr/binder/inc/bindertracing.h index 75d8270b8eee5..ca28c04519638 100644 --- a/src/coreclr/binder/inc/bindertracing.h +++ b/src/coreclr/binder/inc/bindertracing.h @@ -27,7 +27,7 @@ namespace BinderTracing { public: // This class assumes the assembly spec will have a longer lifetime than itself - AssemblyBindOperation(AssemblySpec *assemblySpec, const WCHAR *assemblyPath = nullptr); + AssemblyBindOperation(AssemblySpec *assemblySpec, const SString& assemblyPath = SString::Empty()); ~AssemblyBindOperation(); void SetResult(PEAssembly *assembly, bool cached = false); diff --git a/src/coreclr/binder/inc/stringlexer.hpp b/src/coreclr/binder/inc/stringlexer.hpp index 41af7e7baa18d..f08e046982c56 100644 --- a/src/coreclr/binder/inc/stringlexer.hpp +++ b/src/coreclr/binder/inc/stringlexer.hpp @@ -55,32 +55,28 @@ namespace BINDER_SPACE inline StringLexer(); inline ~StringLexer(); - inline void Init(SString &inputString, BOOL fSupportEscaping); + inline void Init(SString &inputString); static inline BOOL IsWhitespace(WCHAR wcChar); static inline BOOL IsEOS(WCHAR wcChar); static inline BOOL IsQuoteCharacter(WCHAR wcChar); - virtual BOOL IsSeparatorChar(WCHAR wcChar) = NULL; - virtual LEXEME_TYPE GetLexemeType(WCHAR wcChar) = NULL; + BOOL IsSeparatorChar(WCHAR wcChar); + LEXEME_TYPE GetLexemeType(WCHAR wcChar); protected: static const WCHAR INVALID_CHARACTER = -1; - LEXEME_TYPE GetNextLexeme(SString ¤tString, BOOL fPermitUnescapedQuotes = FALSE); + LEXEME_TYPE GetNextLexeme(SString ¤tString); inline WCHAR PopCharacter(BOOL *pfIsEscaped); inline void PushCharacter(WCHAR wcCurrentChar, BOOL fIsEscaped); inline WCHAR GetRawCharacter(); - inline void PushRawCharacter(); - inline WCHAR DecodeUTF16Character(); inline WCHAR GetNextCharacter(BOOL *pfIsEscaped); - inline WCHAR ParseUnicode(); - LEXEME_TYPE ParseString(SString ¤tString, - BOOL fPermitUnescapeQuotes); + LEXEME_TYPE ParseString(SString ¤tString); void TrimTrailingWhiteSpaces(SString ¤tString); @@ -89,8 +85,6 @@ namespace BINDER_SPACE WCHAR m_wcCurrentChar; BOOL m_fCurrentCharIsEscaped; - BOOL m_fSupportEscaping; - BOOL m_fReadRawCharacter; }; #include "stringlexer.inl" diff --git a/src/coreclr/binder/inc/stringlexer.inl b/src/coreclr/binder/inc/stringlexer.inl index bfe4bddeaa4c1..42f7f73ed0bbc 100644 --- a/src/coreclr/binder/inc/stringlexer.inl +++ b/src/coreclr/binder/inc/stringlexer.inl @@ -25,12 +25,10 @@ StringLexer::~StringLexer() // Nothing to do here } -void StringLexer::Init(SString &inputString, BOOL fSupportEscaping) +void StringLexer::Init(SString &inputString) { m_cursor = inputString.Begin(); m_end = inputString.End(); - m_fSupportEscaping = fSupportEscaping; - m_fReadRawCharacter = FALSE; } BOOL StringLexer::IsWhitespace(WCHAR wcChar) @@ -55,6 +53,7 @@ WCHAR StringLexer::PopCharacter(BOOL *pfIsEscaped) { m_wcCurrentChar = INVALID_CHARACTER; *pfIsEscaped = m_fCurrentCharIsEscaped; + m_cursor++; } else { @@ -71,172 +70,63 @@ void StringLexer::PushCharacter(WCHAR wcCurrentChar, m_wcCurrentChar = wcCurrentChar; m_fCurrentCharIsEscaped = fIsEscaped; + m_cursor--; } WCHAR StringLexer::GetRawCharacter() { WCHAR wcCurrentChar = 0; - if (m_cursor <= m_end) + if (m_cursor < m_end) { wcCurrentChar = m_cursor[0]; - m_fReadRawCharacter = TRUE; m_cursor++; - } - else - { - m_fReadRawCharacter = FALSE; - } - - return wcCurrentChar; -} - -void StringLexer::PushRawCharacter() -{ - if (m_fReadRawCharacter) - { - m_cursor--; - m_fReadRawCharacter = FALSE; - } -} -WCHAR StringLexer::DecodeUTF16Character() -{ - // See http://www.ietf.org/rfc/rfc2781.txt for details on UTF-16 encoding. - - WCHAR wcCurrentChar = 0; - SCOUNT_T nCharacters = m_end - m_cursor + 1; - WCHAR wcChar1 = GetRawCharacter(); - - if (wcChar1 < 0xd800) - { - wcCurrentChar = wcChar1; + // do not allow \0 anywhere in the string. + if (wcCurrentChar == 0) + { + wcCurrentChar = INVALID_CHARACTER; + } } else { - // StringLexer is not designed to handle UTF-16 characters beyond the Basic Multilingual Plane, - // since it stores all characters in 16-bit WCHARs. - // However, since the vast majority of the time, we (Microsoft) produce the manifests, - // this is likely a non-scenario, as the other Unicode planes would never be used in practice. - - if (wcChar1 <= 0xdbff) // 0xd800 - 0xdbff indicates the first WCHAR of a surrogate pair - { - if (nCharacters >= 2) - { - GetRawCharacter(); // Skip the second WCHAR of the surrogate pair - } - } - // Otherwise, the character is either in the 0xdc00 - 0xdfff range, indicating the second WCHAR of a surrogate pair, - // or in the 0xE000 - 0xFFFF range, which has within it ranges of invalid characters, and which we conservatively treat - // as invalid. - - wcCurrentChar = INVALID_CHARACTER; + // EOS + wcCurrentChar = 0; } return wcCurrentChar; } - WCHAR StringLexer::GetNextCharacter(BOOL *pfIsEscaped) { *pfIsEscaped = FALSE; - WCHAR wcCurrentChar = GetRawCharacter(); // DecodeUTF16Character() + WCHAR wcCurrentChar = GetRawCharacter(); if (wcCurrentChar == L'\\') { - WCHAR wcTempChar = GetRawCharacter(); // DecodeUTF16Character() + WCHAR wcTempChar = GetRawCharacter(); - if (m_fSupportEscaping) - { - // Handle standard escapes - switch (wcTempChar) - { - case L'"': - case L'\'': - case L',': - case L'\\': - case L'/': - case L'=': - break; - case L't': - wcTempChar = 9; - break; - case L'n': - wcTempChar = 10; - break; - case L'r': - wcTempChar = 13; - break; - case L'u': - wcTempChar = ParseUnicode(); - break; - default: - return INVALID_CHARACTER; - } - - *pfIsEscaped = TRUE; - wcCurrentChar = wcTempChar; - } - else - { - // Do not handle escapes except for quotes - switch (wcTempChar) - { - case L'"': - case L'\'': - *pfIsEscaped = TRUE; - wcCurrentChar = wcTempChar; - break; - default: - PushRawCharacter(); - break; - } - } - } - - return wcCurrentChar; -} - -WCHAR StringLexer::ParseUnicode() -{ - int nCharacters = 0; - WCHAR wcUnicodeChar = 0; - - for(;;) - { - WCHAR wcCurrentChar = DecodeUTF16Character(); - nCharacters++; - - if (wcCurrentChar == L';') + // Handle standard escapes + switch (wcTempChar) { + case L'"': + case L'\'': + case L',': + case L'\\': + case L'=': + case L't': + case L'n': + case L'r': break; - } - else if ((wcCurrentChar == INVALID_CHARACTER) || (nCharacters >= 9)) - { + default: return INVALID_CHARACTER; } - wcUnicodeChar <<= 4; - - if ((wcCurrentChar >= L'0') && (wcCurrentChar <= L'9')) - { - wcUnicodeChar += (wcCurrentChar - L'0'); - } - else if ((wcCurrentChar >= L'a') && (wcCurrentChar <= L'f')) - { - wcUnicodeChar += (wcCurrentChar - L'a') + 10; - } - else if ((wcCurrentChar >= L'A') && (wcCurrentChar <= L'F')) - { - wcUnicodeChar += (wcCurrentChar - L'A') + 10; - } - else - { - return INVALID_CHARACTER; - } + *pfIsEscaped = TRUE; + wcCurrentChar = wcTempChar; } - return wcUnicodeChar; + return wcCurrentChar; } #endif diff --git a/src/coreclr/binder/inc/textualidentityparser.hpp b/src/coreclr/binder/inc/textualidentityparser.hpp index a5187d254a652..2b60c3110f37f 100644 --- a/src/coreclr/binder/inc/textualidentityparser.hpp +++ b/src/coreclr/binder/inc/textualidentityparser.hpp @@ -28,12 +28,9 @@ namespace BINDER_SPACE TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity); ~TextualIdentityParser(); - virtual BOOL IsSeparatorChar(WCHAR wcChar); - virtual StringLexer::LEXEME_TYPE GetLexemeType(WCHAR wcChar); - static HRESULT Parse(/* in */ SString &textualIdentity, - /* out */ AssemblyIdentity *pAssemblyIdentity, - /* in */ BOOL fPermitUnescapedQuotes = FALSE); + /* out */ AssemblyIdentity *pAssemblyIdentity); + static HRESULT ToString(/* in */ AssemblyIdentity *pAssemblyIdentity, /* in */ DWORD dwIdentityFlags, /* out */ SString &textualIdentity); @@ -45,6 +42,7 @@ namespace BINDER_SPACE /* in */ BOOL fValidateHex, /* in */ BOOL fIsToken, /* out */ SBuffer &publicKeyOrTokenBLOB); + static void BlobToHex(/* in */ SBuffer &publicKeyOrTokenBLOB, /* out */ SString &publicKeyOrToken); @@ -52,8 +50,7 @@ namespace BINDER_SPACE /* out */ SString &contentString); protected: - BOOL Parse(/* in */ SString &textualIdentity, - /* in */ BOOL fPermitUnescapedQuotes = FALSE); + BOOL Parse(/* in */ SString &textualIdentity); BOOL PopulateAssemblyIdentity(/* in */ SString &attributeString, /* in */ SString &valueString); diff --git a/src/coreclr/binder/stringlexer.cpp b/src/coreclr/binder/stringlexer.cpp index b6b722fa77ab9..44ec23e3b517c 100644 --- a/src/coreclr/binder/stringlexer.cpp +++ b/src/coreclr/binder/stringlexer.cpp @@ -19,7 +19,7 @@ namespace BINDER_SPACE { StringLexer::LEXEME_TYPE - StringLexer::GetNextLexeme(SString ¤tString, BOOL fPermitUnescapedQuotes) + StringLexer::GetNextLexeme(SString ¤tString) { BOOL fIsEscaped = FALSE; WCHAR wcCurrentChar = INVALID_CHARACTER; @@ -43,11 +43,11 @@ namespace BINDER_SPACE // First character of string lexeme; push it back PushCharacter(wcCurrentChar, fIsEscaped); - return ParseString(currentString, fPermitUnescapedQuotes); + return ParseString(currentString); } StringLexer::LEXEME_TYPE - StringLexer::ParseString(SString ¤tString, BOOL fPermitUnescapedQuotes) + StringLexer::ParseString(SString ¤tString) { BOOL fIsFirstCharacter = TRUE; WCHAR wcCurrentChar = INVALID_CHARACTER; @@ -99,7 +99,7 @@ namespace BINDER_SPACE break; } - if (!fPermitUnescapedQuotes && !fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote)) + if (!fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote)) { // Unescaped quotes in the middle of the string are an error return LEXEME_TYPE_INVALID; @@ -147,4 +147,24 @@ namespace BINDER_SPACE currentString.Truncate(cursor + 1); } } + + BOOL StringLexer::IsSeparatorChar(WCHAR wcChar) + { + return ((wcChar == W(',')) || (wcChar == W('='))); + } + + StringLexer::LEXEME_TYPE StringLexer::GetLexemeType(WCHAR wcChar) + { + switch (wcChar) + { + case W('='): + return LEXEME_TYPE_EQUALS; + case W(','): + return LEXEME_TYPE_COMMA; + case 0: + return LEXEME_TYPE_END_OF_STREAM; + default: + return LEXEME_TYPE_STRING; + } + } }; diff --git a/src/coreclr/binder/textualidentityparser.cpp b/src/coreclr/binder/textualidentityparser.cpp index f69e0bf66b202..35587df3cb7e4 100644 --- a/src/coreclr/binder/textualidentityparser.cpp +++ b/src/coreclr/binder/textualidentityparser.cpp @@ -200,30 +200,9 @@ namespace BINDER_SPACE // Nothing to do here } - BOOL TextualIdentityParser::IsSeparatorChar(WCHAR wcChar) - { - return ((wcChar == W(',')) || (wcChar == W('='))); - } - - StringLexer::LEXEME_TYPE TextualIdentityParser::GetLexemeType(WCHAR wcChar) - { - switch (wcChar) - { - case W('='): - return LEXEME_TYPE_EQUALS; - case W(','): - return LEXEME_TYPE_COMMA; - case 0: - return LEXEME_TYPE_END_OF_STREAM; - default: - return LEXEME_TYPE_STRING; - } - } - /* static */ HRESULT TextualIdentityParser::Parse(SString &textualIdentity, - AssemblyIdentity *pAssemblyIdentity, - BOOL fPermitUnescapedQuotes) + AssemblyIdentity *pAssemblyIdentity) { HRESULT hr = S_OK; @@ -233,7 +212,7 @@ namespace BINDER_SPACE { TextualIdentityParser identityParser(pAssemblyIdentity); - if (!identityParser.Parse(textualIdentity, fPermitUnescapedQuotes)) + if (!identityParser.Parse(textualIdentity)) { IF_FAIL_GO(FUSION_E_INVALID_NAME); } @@ -335,18 +314,6 @@ namespace BINDER_SPACE textualIdentity.Append(ContentTypeToString(pAssemblyIdentity->m_kContentType)); } - if (AssemblyIdentity::Have(dwIdentityFlags, AssemblyIdentity::IDENTITY_FLAG_CUSTOM)) - { - textualIdentity.Append(W(", Custom=")); - tmpString.Clear(); - BlobToHex(pAssemblyIdentity->m_customBLOB, tmpString); - textualIdentity.Append(tmpString); - } - else if (AssemblyIdentity::Have(dwIdentityFlags, - AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL)) - { - textualIdentity.Append(W(", Custom=null")); - } } EX_CATCH_HRESULT(hr); @@ -486,19 +453,19 @@ namespace BINDER_SPACE publicKeyOrToken.CloseBuffer(cbPublicKeyOrTokenBLOB * 2); } - BOOL TextualIdentityParser::Parse(SString &textualIdentity, BOOL fPermitUnescapedQuotes) + BOOL TextualIdentityParser::Parse(SString &textualIdentity) { BOOL fIsValid = TRUE; SString unicodeTextualIdentity; // Lexer modifies input string textualIdentity.ConvertToUnicode(unicodeTextualIdentity); - Init(unicodeTextualIdentity, TRUE /* fSupportEscaping */); + Init(unicodeTextualIdentity); SmallStackSString currentString; // Identity format is simple name (, attr = value)* - GO_IF_NOT_EXPECTED(GetNextLexeme(currentString, fPermitUnescapedQuotes), LEXEME_TYPE_STRING); + GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING); m_pAssemblyIdentity->m_simpleName.Set(currentString); m_pAssemblyIdentity->m_simpleName.Normalize(); m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME); @@ -532,7 +499,7 @@ namespace BINDER_SPACE // Lexer modifies input string textualString.ConvertToUnicode(unicodeTextualString); - Init(unicodeTextualString, TRUE /* fSupportEscaping */); + Init(unicodeTextualString); SmallStackSString currentString; GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING); @@ -549,8 +516,7 @@ namespace BINDER_SPACE { BOOL fIsValid = TRUE; - if (EqualsCaseInsensitive(attributeString, W("culture")) || - EqualsCaseInsensitive(attributeString, W("language"))) + if (EqualsCaseInsensitive(attributeString, W("culture"))) { GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CULTURE); GO_IF_WILDCARD(valueString); @@ -586,8 +552,7 @@ namespace BINDER_SPACE GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); GO_IF_WILDCARD(valueString); - if (!EqualsCaseInsensitive(valueString, W("null")) && - !EqualsCaseInsensitive(valueString, W("neutral"))) + if (!EqualsCaseInsensitive(valueString, W("null"))) { GO_IF_VALIDATE_FAILED(ValidatePublicKeyToken, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); @@ -606,8 +571,7 @@ namespace BINDER_SPACE GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY); - if (!EqualsCaseInsensitive(valueString, W("null")) && - !EqualsCaseInsensitive(valueString, W("neutral"))) + if (!EqualsCaseInsensitive(valueString, W("null"))) { GO_IF_VALIDATE_FAILED(ValidatePublicKey, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY); HexToBlob(valueString, @@ -661,23 +625,6 @@ namespace BINDER_SPACE fIsValid = FALSE; } } - else if (EqualsCaseInsensitive(attributeString, W("custom"))) - { - GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CUSTOM); - - if (EqualsCaseInsensitive(valueString, W("null"))) - { - m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL); - } - else - { - GO_IF_VALIDATE_FAILED(ValidateHex, AssemblyIdentity::IDENTITY_FLAG_CUSTOM); - HexToBlob(valueString, - FALSE /* fValidateHex */, - FALSE /* fIsToken */, - m_pAssemblyIdentity->m_customBLOB); - } - } Exit: return fIsValid; diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index ed9d735a7d428..30cd7d2785267 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -345,6 +345,9 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do ( if not "!string:-nativeaot-=!"=="!string!" ( set __CMakeTarget=!__CMakeTarget! nativeaot ) + if not "!string:-spmi-=!"=="!string!" ( + set __CMakeTarget=!__CMakeTarget! spmi + ) ) if [!__CMakeTarget!] == [] ( set __CMakeTarget=install @@ -745,7 +748,7 @@ echo -all: Builds all configurations and platforms. echo Build architecture: one of -x64, -x86, -arm, -arm64 ^(default: -x64^). echo Build type: one of -Debug, -Checked, -Release ^(default: -Debug^). echo -component ^ : specify this option one or more times to limit components built to those specified. -echo Allowed ^: hosts jit alljits runtime paltests iltools +echo Allowed ^: hosts jit alljits runtime paltests iltools nativeaot spmi echo -enforcepgo: verify after the build that PGO was used for key DLLs, and fail the build if not echo -pgoinstrument: generate instrumented code for profile guided optimization enabled binaries. echo -cmakeargs: user-settable additional arguments passed to CMake. diff --git a/src/coreclr/build-runtime.sh b/src/coreclr/build-runtime.sh index 8d42b92ce95c0..a1e03198ac6df 100755 --- a/src/coreclr/build-runtime.sh +++ b/src/coreclr/build-runtime.sh @@ -22,7 +22,7 @@ usage_list+=("-pgodatapath: path to profile guided optimization data.") usage_list+=("-pgoinstrument: generate instrumented code for profile guided optimization enabled binaries.") usage_list+=("-skipcrossarchnative: Skip building cross-architecture native binaries.") usage_list+=("-staticanalyzer: use scan_build static analyzer.") -usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', and 'nativeaot'. Can be specified multiple times.") +usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', 'nativeaot', and 'spmi'. Can be specified multiple times.") setup_dirs_local() { diff --git a/src/coreclr/classlibnative/float/floatdouble.cpp b/src/coreclr/classlibnative/float/floatdouble.cpp index 67aceb60ea13e..d20b772eb2207 100644 --- a/src/coreclr/classlibnative/float/floatdouble.cpp +++ b/src/coreclr/classlibnative/float/floatdouble.cpp @@ -42,15 +42,6 @@ #pragma float_control(precise, off) #endif -/*=====================================Abs====================================== -** -==============================================================================*/ -FCIMPL1_V(double, COMDouble::Abs, double x) - FCALL_CONTRACT; - - return fabs(x); -FCIMPLEND - /*=====================================Acos===================================== ** ==============================================================================*/ diff --git a/src/coreclr/classlibnative/float/floatsingle.cpp b/src/coreclr/classlibnative/float/floatsingle.cpp index 965998fbaa2ba..1694fd78cb846 100644 --- a/src/coreclr/classlibnative/float/floatsingle.cpp +++ b/src/coreclr/classlibnative/float/floatsingle.cpp @@ -8,18 +8,6 @@ #include "floatsingle.h" -// Windows x86 and Windows ARM/ARM64 may not define _isnanf() or _copysignf() but they do -// define _isnan() and _copysign(). We will redirect the macros to these other functions if -// the macro is not defined for the platform. This has the side effect of a possible implicit -// upcasting for arguments passed in and an explicit downcasting for the _copysign() call. -#if (defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_ARM64)) && !defined(TARGET_UNIX) - -#if !defined(_copysignf) -#define _copysignf (float)_copysign -#endif - -#endif - // The default compilation mode is /fp:precise, which disables floating-point intrinsics. This // default compilation mode has previously caused performance regressions in floating-point code. // We enable /fp:fast semantics for the majority of the math functions, as it will speed up performance @@ -40,15 +28,6 @@ #pragma float_control(precise, off) #endif -/*=====================================Abs===================================== -** -==============================================================================*/ -FCIMPL1_V(float, COMSingle::Abs, float x) - FCALL_CONTRACT; - - return fabsf(x); -FCIMPLEND - /*=====================================Acos===================================== ** ==============================================================================*/ diff --git a/src/coreclr/classlibnative/inc/floatdouble.h b/src/coreclr/classlibnative/inc/floatdouble.h index 9163349127ca1..43fecbd47431f 100644 --- a/src/coreclr/classlibnative/inc/floatdouble.h +++ b/src/coreclr/classlibnative/inc/floatdouble.h @@ -9,7 +9,6 @@ class COMDouble { public: - FCDECL1_V(static double, Abs, double x); FCDECL1_V(static double, Acos, double x); FCDECL1_V(static double, Acosh, double x); FCDECL1_V(static double, Asin, double x); diff --git a/src/coreclr/classlibnative/inc/floatsingle.h b/src/coreclr/classlibnative/inc/floatsingle.h index 09a0512b230db..765032ce6371e 100644 --- a/src/coreclr/classlibnative/inc/floatsingle.h +++ b/src/coreclr/classlibnative/inc/floatsingle.h @@ -9,7 +9,6 @@ class COMSingle { public: - FCDECL1_V(static float, Abs, float x); FCDECL1_V(static float, Acos, float x); FCDECL1_V(static float, Acosh, float x); FCDECL1_V(static float, Asin, float x); diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index d5fc9f5e1ee8e..533d5255002b4 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -92,7 +92,6 @@ endif(CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_BASICFREEZE) add_definitions(-DFEATURE_CORECLR) -add_definitions(-DFEATURE_CORESYSTEM) if(FEATURE_DBGIPC) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_DI) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_VM) diff --git a/src/coreclr/components.cmake b/src/coreclr/components.cmake index c23a38539247e..3eaa2c966bf32 100644 --- a/src/coreclr/components.cmake +++ b/src/coreclr/components.cmake @@ -6,6 +6,7 @@ add_component(runtime) add_component(paltests paltests_install) add_component(iltools) add_component(nativeaot) +add_component(spmi) # Define coreclr_all as the fallback component and make every component depend on this component. # iltools and paltests should be minimal subsets, so don't add a dependency on coreclr_misc diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 9aaf6e6e4cb17..7936b3a1279a8 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -6542,61 +6542,6 @@ bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEAssembly *pPEAssembly, return true; } -#if defined(FEATURE_CORESYSTEM) -/* static */ -// We extract "ni.dll from the NGEN image name to obtain the IL image name. -// In the end we add given ilExtension. -// This dependecy is based on Apollo installer behavior. -bool ClrDataAccess::GetILImageNameFromNgenImage( LPCWSTR ilExtension, - _Out_writes_(cchFilePath) LPWSTR wszFilePath, - const DWORD cchFilePath) -{ - if (wszFilePath == NULL || cchFilePath == 0) - { - return false; - } - - _wcslwr_s(wszFilePath, cchFilePath); - // Find the "ni.dll" extension. - // If none exists use NGEN image name. - // - const WCHAR* ngenExtension = W("ni.dll"); - - if (wcslen(ilExtension) <= wcslen(ngenExtension)) - { - LPWSTR wszFileExtension = wcsstr(wszFilePath, ngenExtension); - if (wszFileExtension != 0) - { - LPWSTR wszNextFileExtension = wszFileExtension; - // Find last occurrence - do - { - wszFileExtension = wszNextFileExtension; - wszNextFileExtension = wcsstr(wszFileExtension + 1, ngenExtension); - } while (wszNextFileExtension != 0); - - // Overwrite ni.dll with ilExtension - if (!memcpy_s(wszFileExtension, - wcslen(ngenExtension)*sizeof(WCHAR), - ilExtension, - wcslen(ilExtension)*sizeof(WCHAR))) - { - wszFileExtension[wcslen(ilExtension)] = '\0'; - return true; - } - } - } - - //Use ngen filename if there is no ".ni" - if (wcsstr(wszFilePath, W(".ni")) == 0) - { - return true; - } - - return false; -} -#endif // FEATURE_CORESYSTEM - void * ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, bool* isAlternate) @@ -6705,7 +6650,6 @@ ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, goto ErrExit; } -#if defined(FEATURE_CORESYSTEM) const WCHAR* ilExtension = W("dll"); WCHAR ngenImageName[MAX_LONGPATH] = {0}; if (wcscpy_s(ngenImageName, ARRAY_SIZE(ngenImageName), uniPath) != 0) @@ -6716,12 +6660,6 @@ ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, { goto ErrExit; } - // Transform NGEN image name into IL Image name - if (!GetILImageNameFromNgenImage(ilExtension, uniPath, ARRAY_SIZE(uniPath))) - { - goto ErrExit; - } -#endif//FEATURE_CORESYSTEM // RVA size in ngen image and IL image is the same. Because the only // different is in RVA. That is 4 bytes column fixed. @@ -6943,11 +6881,6 @@ bool ClrDataAccess::TargetConsistencyAssertsEnabled() return m_fEnableTargetConsistencyAsserts; } -#ifdef FEATURE_CORESYSTEM -#define ctime_s _ctime32_s -#define time_t __time32_t -#endif - // // VerifyDlls - Validate that the mscorwks in the target matches this version of mscordacwks // Only done on Windows and Mac builds at the moment. @@ -7503,34 +7436,8 @@ BOOL OutOfProcessExceptionEventGetProcessIdAndThreadId(HANDLE hProcess, HANDLE h *pPId = (DWORD)(SIZE_T)hProcess; *pThreadId = (DWORD)(SIZE_T)hThread; #else -#if !defined(FEATURE_CORESYSTEM) - HMODULE hKernel32 = WszGetModuleHandle(W("kernel32.dll")); -#else - HMODULE hKernel32 = WszGetModuleHandle(W("api-ms-win-core-processthreads-l1-1-1.dll")); -#endif - if (hKernel32 == NULL) - { - return FALSE; - } - - typedef WINBASEAPI DWORD (WINAPI GET_PROCESSID_OF_THREAD)(HANDLE); - GET_PROCESSID_OF_THREAD * pGetProcessIdOfThread; - - typedef WINBASEAPI DWORD (WINAPI GET_THREADID)(HANDLE); - GET_THREADID * pGetThreadId; - - pGetProcessIdOfThread = (GET_PROCESSID_OF_THREAD *)GetProcAddress(hKernel32, "GetProcessIdOfThread"); - pGetThreadId = (GET_THREADID *)GetProcAddress(hKernel32, "GetThreadId"); - - // OOP callbacks are used on Win7 or later. We should have having below two APIs available. - _ASSERTE((pGetProcessIdOfThread != NULL) && (pGetThreadId != NULL)); - if ((pGetProcessIdOfThread == NULL) || (pGetThreadId == NULL)) - { - return FALSE; - } - - *pPId = (*pGetProcessIdOfThread)(hThread); - *pThreadId = (*pGetThreadId)(hThread); + *pPId = GetProcessIdOfThread(hThread); + *pThreadId = GetThreadId(hThread); #endif // TARGET_UNIX return TRUE; } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index ebb5d12c0ce3a..1ff143cf7cce1 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -657,21 +657,21 @@ void DacDbiInterfaceImpl::GetAppDomainFullName( // Get the values of the JIT Optimization and EnC flags. void DacDbiInterfaceImpl::GetCompilerFlags ( - VMPTR_DomainFile vmDomainFile, + VMPTR_DomainAssembly vmDomainAssembly, BOOL *pfAllowJITOpts, BOOL *pfEnableEnC) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - if (pDomainFile == NULL) + if (pDomainAssembly == NULL) { ThrowHR(E_FAIL); } // Get the underlying module - none of this is AppDomain specific - Module * pModule = pDomainFile->GetModule(); + Module * pModule = pDomainAssembly->GetModule(); DWORD dwBits = pModule->GetDebuggerInfoBits(); *pfAllowJITOpts = !CORDisableJITOptimizations(dwBits); *pfEnableEnC = pModule->IsEditAndContinueEnabled(); @@ -712,15 +712,15 @@ bool DacDbiInterfaceImpl::CanSetEnCBits(Module * pModule) } // DacDbiInterfaceImpl::SetEnCBits // Set the values of the JIT optimization and EnC flags. -HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainFile vmDomainFile, +HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC) { DD_ENTER_MAY_THROW; DWORD dwBits = 0; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); HRESULT hr = S_OK; @@ -1082,15 +1082,15 @@ ULONG DacDbiInterfaceImpl::TranslateInstrumentedILOffsetToOriginal(ULONG // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // -void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, TargetBuffer * pCodeInfo, mdToken * pLocalSigToken) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); RVA methodRVA = 0; DWORD implFlags; @@ -1323,7 +1323,7 @@ void DacDbiInterfaceImpl::GetMethodRegionInfo(MethodDesc * pMethodDe // isn't currently available. In this case, all values in pCodeInfo will be // cleared. -void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, NativeCodeFunctionData * pCodeInfo) { @@ -1334,8 +1334,8 @@ void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainFile vmDomainFil // pre-initialize: pCodeInfo->Clear(); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); MethodDesc* pMethodDesc = FindLoadedMethodRefOrDef(pModule, functionToken); pCodeInfo->vmNativeCodeMethodDescToken.SetHostPtr(pMethodDesc); @@ -1760,7 +1760,7 @@ void DacDbiInterfaceImpl::GetClassInfo(VMPTR_AppDomain vmAppDomain, } // DacDbiInterfaceImpl::GetClassInfo // DacDbi API: Get field information and object size for an instantiated generic type -void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, DacDbiArrayList * pFieldList, @@ -1768,9 +1768,9 @@ void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainFile { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - _ASSERTE(pDomainFile != NULL); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + _ASSERTE(pDomainAssembly != NULL); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); TypeHandle thExact; TypeHandle thApprox; @@ -2503,11 +2503,11 @@ void DacDbiInterfaceImpl::GetClassTypeInfo(TypeHandle typeH pTypeInfo->ClassTypeData.vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule)); if (pAppDomain) { - pTypeInfo->ClassTypeData.vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile())); + pTypeInfo->ClassTypeData.vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainAssembly())); } else { - pTypeInfo->ClassTypeData.vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->ClassTypeData.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); } } // DacDbiInterfaceImpl::GetClassTypeInfo @@ -2567,7 +2567,7 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle case ELEMENT_TYPE_BYREF: pTypeInfo->vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); pTypeInfo->metadataToken = mdTokenNil; - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); break; case ELEMENT_TYPE_CLASS: @@ -2590,11 +2590,11 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle pTypeInfo->vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule)); if (pAppDomain) { - pTypeInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile())); + pTypeInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainAssembly())); } else { - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); } break; } @@ -2602,7 +2602,7 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle default: pTypeInfo->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); pTypeInfo->metadataToken = mdTokenNil; - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); break; } return; @@ -2889,8 +2889,8 @@ TypeHandle DacDbiInterfaceImpl::GetClassOrValueTypeHandle(DebuggerIPCE_BasicType // otherwise, have the loader look it up using the metadata token and domain file else { - DomainFile * pDomainFile = pData->vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pData->vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, pData->metadataToken); if (typeHandle.IsNull()) @@ -3292,7 +3292,7 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, CorElementType simpleType, mdTypeDef *pMetadataToken, VMPTR_Module *pVmModule, - VMPTR_DomainFile *pVmDomainFile) + VMPTR_DomainAssembly *pVmDomainAssembly) { DD_ENTER_MAY_THROW; @@ -3300,8 +3300,8 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, // if we fail to get either a valid type handle or module, we will want to send back // a NULL domain file too, so we'll to preinitialize this here. - _ASSERTE(pVmDomainFile != NULL); - *pVmDomainFile = VMPTR_DomainFile::NullPtr(); + _ASSERTE(pVmDomainAssembly != NULL); + *pVmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); // FindLoadedElementType will return NULL if the type hasn't been loaded yet. TypeHandle typeHandle = FindLoadedElementType(simpleType); @@ -3322,8 +3322,8 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, if (pAppDomain) { - pVmDomainFile->SetHostPtr(pModule->GetDomainFile()); - if (pVmDomainFile->IsNull()) + pVmDomainAssembly->SetHostPtr(pModule->GetDomainAssembly()); + if (pVmDomainAssembly->IsNull()) ThrowHR(CORDBG_E_TARGET_INCONSISTENT); } } @@ -3483,7 +3483,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateType(VMPTR_Object delegateObject, Delega HRESULT DacDbiInterfaceImpl::GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef) { DD_ENTER_MAY_THROW; @@ -3514,7 +3514,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateFunctionData( if (hr != S_OK) return hr; - ppFunctionDomainFile->SetDacTargetPtr(dac_cast(pMD.GetDacPtr()->GetModule()->GetDomainFile())); + ppFunctionDomainAssembly->SetDacTargetPtr(dac_cast(pMD.GetDacPtr()->GetModule()->GetDomainAssembly())); *pMethodDef = pMD.GetDacPtr()->GetMemberDef(); return hr; @@ -3725,17 +3725,17 @@ void DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, Dac BaseDomain* pBaseDomain = currentElement.pFunc->GetAssembly()->GetDomain(); AppDomain* pDomain = NULL; - DomainFile* pDomainFile = NULL; + DomainAssembly* pDomainAssembly = NULL; pDomain = pBaseDomain->AsAppDomain(); _ASSERTE(pDomain != NULL); - pDomainFile = pModule->GetDomainFile(); - _ASSERTE(pDomainFile != NULL); + pDomainAssembly = pModule->GetDomainAssembly(); + _ASSERTE(pDomainAssembly != NULL); currentFrame.vmAppDomain.SetHostPtr(pDomain); - currentFrame.vmDomainFile.SetHostPtr(pDomainFile); + currentFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); currentFrame.ip = currentElement.ip; currentFrame.methodDef = currentElement.pFunc->GetMemberDef(); currentFrame.isLastForeignExceptionFrame = (currentElement.flags & STEF_LAST_FRAME_FROM_FOREIGN_STACK_TRACE) != 0; @@ -3879,8 +3879,8 @@ FieldDesc * DacDbiInterfaceImpl::GetEnCFieldDesc(const EnCHangingFieldInfo * pEn { FieldDesc * pFD = NULL; - DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pEnCFieldInfo->GetObjectTypeData().vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); // get the type handle for the object TypeHandle typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, @@ -3918,8 +3918,8 @@ PTR_CBYTE DacDbiInterfaceImpl::GetPtrToEnCField(FieldDesc * pFD, const EnCHangin #else PTR_EditAndContinueModule pEnCModule; - DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pEnCFieldInfo->GetObjectTypeData().vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); // make sure we actually have an EditAndContinueModule _ASSERTE(pModule->IsEditAndContinueCapable()); @@ -4066,7 +4066,7 @@ BOOL DacDbiInterfaceImpl::GetAssemblyPath( // Get the manifest module for this assembly Assembly * pAssembly = vmAssembly.GetDacPtr(); - Module * pManifestModule = pAssembly->GetManifestModule(); + Module * pManifestModule = pAssembly->GetModule(); // Get the path for the manifest module. // since we no longer support Win9x, we assume all paths will be in unicode format already @@ -4090,8 +4090,8 @@ void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, TypeRefData * pTargetRefInfo) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = pTypeRefInfo->vmDomainFile.GetDacPtr(); - Module * pReferencingModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = pTypeRefInfo->vmDomainAssembly.GetDacPtr(); + Module * pReferencingModule = pDomainAssembly->GetModule(); BOOL fSuccess = FALSE; // Resolve the type ref @@ -4117,9 +4117,9 @@ void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, _ASSERTE(pTargetModule != NULL); _ASSERTE( TypeFromToken(targetTypeDef) == mdtTypeDef ); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); - pTargetRefInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainFile())); + pTargetRefInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainAssembly())); pTargetRefInfo->typeToken = targetTypeDef; } else @@ -4347,19 +4347,19 @@ void DacDbiInterfaceImpl::GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * -void DacDbiInterfaceImpl::GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule) +void DacDbiInterfaceImpl::GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) { DD_ENTER_MAY_THROW; _ASSERTE(pModule != NULL); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - pModule->SetHostPtr(pDomainFile->GetModule()); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + pModule->SetHostPtr(pDomainAssembly->GetModule()); } -// Implement IDacDbiInterface::GetDomainFileData -void DacDbiInterfaceImpl::GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData) +// Implement IDacDbiInterface::GetDomainAssemblyData +void DacDbiInterfaceImpl::GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData) { DD_ENTER_MAY_THROW; @@ -4367,12 +4367,11 @@ void DacDbiInterfaceImpl::GetDomainFileData(VMPTR_DomainFile vmDomainFile, Domai ZeroMemory(pData, sizeof(*pData)); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); // @dbgtodo - is this efficient DAC usage (perhaps a dac-cop rule)? Are we round-tripping the pointer? - // Should we have a GetDomainAssembly() that returns a PTR_DomainAssembly? - pData->vmDomainAssembly.SetHostPtr(pDomainFile->GetDomainAssembly()); + pData->vmDomainAssembly.SetHostPtr(pDomainAssembly); pData->vmAppDomain.SetHostPtr(pAppDomain); } @@ -4494,41 +4493,30 @@ void DacDbiInterfaceImpl::EnumerateModulesInAssembly( DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr(); - // If the domain is not yet fully-loaded, don't advertise it yet. - // It's not ready to be inspected. - DomainModuleIterator iterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - - while (iterator.Next()) + // Debugger isn't notified of Resource / Inspection-only modules. + if (pDomainAssembly->GetModule()->IsVisibleToDebugger()) { - DomainFile * pDomainFile = iterator.GetDomainFile(); + _ASSERTE(pDomainAssembly->IsLoaded()); - // Debugger isn't notified of Resource / Inspection-only modules. - if (!pDomainFile->GetModule()->IsVisibleToDebugger()) - { - continue; - } - - _ASSERTE(pDomainFile->IsLoaded()); - - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); - vmDomainFile.SetHostPtr(pDomainFile); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + vmDomainAssembly.SetHostPtr(pDomainAssembly); - fpCallback(vmDomainFile, pUserData); + fpCallback(vmDomainAssembly, pUserData); } } // Implementation of IDacDbiInterface::ResolveAssembly // Returns NULL if not found. VMPTR_DomainAssembly DacDbiInterfaceImpl::ResolveAssembly( - VMPTR_DomainFile vmScope, + VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmScope.GetDacPtr(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmScope.GetDacPtr(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); + Module * pModule = pDomainAssembly->GetModule(); VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); @@ -5428,6 +5416,16 @@ GENERICS_TYPE_TOKEN DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD if (dwExactGenericArgsTokenIndex == 0) { + // In a rare case of VS4Mac debugging VS4Mac ARM64 optimized code we get a null generics argument token. We aren't sure + // why the token is null, it may be a bug or it may be by design in the runtime. In the interest of time we are working + // around the issue rather than investigating the root cause. This workaround should only cause us to degrade generic + // types from exact type parameters to approximate or canonical type parameters. In the future if we discover this issue + // is happening more frequently than we expect or the workaround is more impactful than we expect we may need to remove + // this workaround and resolve the underlying issue. + if (rawToken == 0) + { + return rawToken; + } // In this case the real generics type token is the MethodTable of the "this" object. // Note that we want the target address here. @@ -6058,7 +6056,7 @@ void DacDbiInterfaceImpl::GetTypedByRefInfo(CORDB_ADDRESS pTypedByRe "ref=0x%08x, cls=0x%08x, mod=0x%p\n", pObjectData->objRef, pObjectData->typedByrefType.metadataToken, - pObjectData->typedByrefType.vmDomainFile.GetDacPtr())); + pObjectData->typedByrefType.vmDomainAssembly.GetDacPtr())); } // DacDbiInterfaceImpl::GetTypedByRefInfo // Get the string data associated withn obj and put it into the pointers @@ -7015,7 +7013,7 @@ bool DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS addr) } bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_AppDomain * pAppDomain, - OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *pDomainFile) + OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *pDomainAssembly) { DD_ENTER_MAY_THROW; @@ -7035,7 +7033,7 @@ bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_Ap { pAppDomain->SetDacTargetPtr(PTR_HOST_TO_TADDR(baseDomain->AsAppDomain())); pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module)); - pDomainFile->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainFile())); + pDomainAssembly->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainAssembly())); } else { diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index e484a28008b0c..e885703113197 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -96,7 +96,7 @@ class DacDbiInterfaceImpl : IStringHolder * pStrName); // Get the values of the JIT Optimization and EnC flags. - void GetCompilerFlags (VMPTR_DomainFile vmDomainFile, + void GetCompilerFlags (VMPTR_DomainAssembly vmDomainAssembly, BOOL * pfAllowJITOpts, BOOL * pfEnableEnC); @@ -104,7 +104,7 @@ class DacDbiInterfaceImpl : bool CanSetEnCBits(Module * pModule); // Set the values of the JIT optimization and EnC flags. - HRESULT SetCompilerFlags(VMPTR_DomainFile vmDomainFile, + HRESULT SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC); @@ -133,7 +133,7 @@ class DacDbiInterfaceImpl : bool IsValidObject(CORDB_ADDRESS obj); - bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *mod); + bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *mod); @@ -218,7 +218,7 @@ class DacDbiInterfaceImpl : // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // - void GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, + void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, TargetBuffer * pCodeInfo, mdToken * pLocalSigToken); @@ -229,7 +229,7 @@ class DacDbiInterfaceImpl : // whether it's an instantiated generic // its EnC version number // hot and cold region information. - void GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, + void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, NativeCodeFunctionData * pCodeInfo); @@ -260,7 +260,7 @@ class DacDbiInterfaceImpl : ClassInfo * pData); // get field information and object size for an instantiated generic type - void GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, + void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, DacDbiArrayList * pFieldList, @@ -336,7 +336,7 @@ class DacDbiInterfaceImpl : CorElementType simpleType, mdTypeDef * pMetadataToken, VMPTR_Module * pVmModule, - VMPTR_DomainFile * pVmDomainFile); + VMPTR_DomainAssembly * pVmDomainAssembly); BOOL IsExceptionObject(VMPTR_Object vmObject); @@ -352,7 +352,7 @@ class DacDbiInterfaceImpl : HRESULT GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef); HRESULT GetDelegateTargetObject( @@ -730,10 +730,10 @@ class DacDbiInterfaceImpl : // Gets properties for a module void GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData); - // Gets properties for a domainfile - void GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData); + // Gets properties for a domain assembly + void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData); - void GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule); + void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule); // Yields true if the address is a CLR stub. BOOL IsTransitionStub(CORDB_ADDRESS address); @@ -829,8 +829,8 @@ class DacDbiInterfaceImpl : // Return the current appdomain the specified thread is in. VMPTR_AppDomain GetCurrentAppDomain(VMPTR_Thread vmThread); - // Given an assembly ref token and metadata scope (via the DomainFile), resolve the assembly. - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainFile vmScope, mdToken tkAssemblyRef); + // Given an assembly ref token and metadata scope (via the DomainAssembly), resolve the assembly. + VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef); // Hijack the thread diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 251b5dde74fdf..b8a84043b396f 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -514,7 +514,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread #endif // FEATURE_COMINTEROP Module * pModule = (pMD ? pMD->GetModule() : NULL); - DomainFile * pDomainFile = (pModule ? pModule->GetDomainFile() : NULL); + DomainAssembly * pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); if (frameData.stubFrame.frameType == STUBFRAME_FUNC_EVAL) { @@ -522,14 +522,14 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread DebuggerEval * pDE = pFEF->GetDebuggerEval(); frameData.stubFrame.funcMetadataToken = pDE->m_methodToken; - frameData.stubFrame.vmDomainFile.SetHostPtr( - pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainFile() : NULL); + frameData.stubFrame.vmDomainAssembly.SetHostPtr( + pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainAssembly() : NULL); frameData.stubFrame.vmMethodDesc = VMPTR_MethodDesc::NullPtr(); } else { frameData.stubFrame.funcMetadataToken = (pMD == NULL ? NULL : pMD->GetMemberDef()); - frameData.stubFrame.vmDomainFile.SetHostPtr(pDomainFile); + frameData.stubFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD); } @@ -702,11 +702,11 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter, // Although MiniDumpNormal tries to dump all AppDomains, it's possible // target corruption will keep one from being present. This should mean // we'll just fail later, but struggle on for now. - DomainFile *pDomainFile = NULL; + DomainAssembly *pDomainAssembly = NULL; EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY { - pDomainFile = (pModule ? pModule->GetDomainFile() : NULL); - _ASSERTE(pDomainFile != NULL); + pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); + _ASSERTE(pDomainAssembly != NULL); } EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY @@ -783,7 +783,7 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter, // pFuncData->funcMetadataToken = pMD->GetMemberDef(); - pFuncData->vmDomainFile.SetHostPtr(pDomainFile); + pFuncData->vmDomainAssembly.SetHostPtr(pDomainAssembly); // PERF: this is expensive to get so I stopped fetching it eagerly // It is only needed if we haven't already got a cached copy diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 57a4dc1bbab8f..7a03d984e3ac7 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -14,14 +14,11 @@ #define __DACIMPL_H__ #include "gcinterface.dac.h" - -#if defined(TARGET_ARM) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers //--------------------------------------------------------------------------------------- // Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for // storing code:DAC_INSTANCE . Otherwise, the DAC uses the STL unordered_map to. #define DAC_HASHTABLE -#endif // TARGET_ARM|| FEATURE_CORESYSTEM #ifndef DAC_HASHTABLE #pragma push_macro("return") @@ -509,7 +506,6 @@ struct ProcessModIter bool m_nextDomain; AppDomain::AssemblyIterator m_assemIter; Assembly* m_curAssem; - Assembly::ModuleIterator m_modIter; ProcessModIter(void) : m_domainIter(FALSE) @@ -545,7 +541,7 @@ struct ProcessModIter } // Note: DAC doesn't need to keep the assembly alive - see code:CollectibleAssemblyHolder#CAH_DAC - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); return pAssembly; } return NULL; @@ -554,27 +550,13 @@ struct ProcessModIter Module* NextModule(void) { SUPPORTS_DAC; - for (;;) + m_curAssem = NextAssem(); + if (!m_curAssem) { - if (!m_curAssem) - { - m_curAssem = NextAssem(); - if (!m_curAssem) - { - return NULL; - } - - m_modIter = m_curAssem->IterateModules(); - } - - if (!m_modIter.Next()) - { - m_curAssem = NULL; - continue; - } - - return m_modIter.GetModule(); + return NULL; } + + return m_curAssem->GetModule(); } }; @@ -1520,11 +1502,6 @@ class ClrDataAccess DWORD &dwSize, _Out_writes_(cchPath) LPWSTR wszPath, const DWORD cchPath); -#if defined(FEATURE_CORESYSTEM) - static bool GetILImageNameFromNgenImage(LPCWSTR ilExtension, - _Out_writes_(cchFilePath) LPWSTR wszFilePath, - const DWORD cchFilePath); -#endif // FEATURE_CORESYSTEM }; extern ClrDataAccess* g_dacImpl; diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 1e327721f4a92..cd81cde5ac69e 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2607,10 +2607,7 @@ ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS assemblyData->ModuleCount = 0; assemblyData->isDomainNeutral = FALSE; - pAssembly->GetManifestFile(); - - ModuleIterator mi = pAssembly->IterateModules(); - while (mi.Next()) + if (pAssembly->GetModule()) { assemblyData->ModuleCount++; } @@ -2628,17 +2625,17 @@ ClrDataAccess::GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, _In if (name) name[0] = 0; - if (!pAssembly->GetManifestFile()->GetPath().IsEmpty()) + if (!pAssembly->GetPEAssembly()->GetPath().IsEmpty()) { - if (!pAssembly->GetManifestFile()->GetPath().DacGetUnicode(count, name, pNeeded)) + if (!pAssembly->GetPEAssembly()->GetPath().DacGetUnicode(count, name, pNeeded)) hr = E_FAIL; else if (name) name[count-1] = 0; } - else if (!pAssembly->GetManifestFile()->IsDynamic()) + else if (!pAssembly->GetPEAssembly()->IsDynamic()) { StackSString displayName; - pAssembly->GetManifestFile()->GetDisplayName(displayName, 0); + pAssembly->GetPEAssembly()->GetDisplayName(displayName, 0); const WCHAR *val = displayName.GetUnicode(); @@ -2673,9 +2670,9 @@ ClrDataAccess::GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, _Inout_u Assembly* pAssembly = PTR_Assembly(TO_TADDR(assembly)); // Turn from bytes to wide characters - if (!pAssembly->GetManifestFile()->GetPath().IsEmpty()) + if (!pAssembly->GetPEAssembly()->GetPath().IsEmpty()) { - if (!pAssembly->GetManifestFile()->GetPath(). + if (!pAssembly->GetPEAssembly()->GetPath(). DacGetUnicode(count, location, pNeeded)) { hr = E_FAIL; @@ -2703,21 +2700,14 @@ ClrDataAccess::GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int coun SOSDacEnter(); Assembly* pAssembly = PTR_Assembly(TO_TADDR(assembly)); - ModuleIterator mi = pAssembly->IterateModules(); - unsigned int n = 0; if (modules) { - while (mi.Next() && n < count) - modules[n++] = HOST_CDADDR(mi.GetModule()); - } - else - { - while (mi.Next()) - n++; + if (pAssembly->GetModule() && count > 0) + modules[0] = HOST_CDADDR(pAssembly->GetModule()); } if (pNeeded) - *pNeeded = n; + *pNeeded = 1; SOSDacLeave(); return hr; diff --git a/src/coreclr/debug/daccess/task.cpp b/src/coreclr/debug/daccess/task.cpp index 30abc5e090cc9..319d3506b9b88 100644 --- a/src/coreclr/debug/daccess/task.cpp +++ b/src/coreclr/debug/daccess/task.cpp @@ -948,6 +948,11 @@ ClrDataAssembly::Release(THIS) return newRefs; } +struct TrivialModuleIterator +{ + Module* m_module; +}; + HRESULT STDMETHODCALLTYPE ClrDataAssembly::StartEnumModules( /* [out] */ CLRDATA_ENUM* handle) @@ -958,11 +963,10 @@ ClrDataAssembly::StartEnumModules( EX_TRY { - Assembly::ModuleIterator* iter = new (nothrow) - Assembly::ModuleIterator; + TrivialModuleIterator* iter = new (nothrow) TrivialModuleIterator; if (iter) { - *iter = m_assembly->IterateModules(); + iter->m_module = m_assembly->GetModule(); *handle = TO_CDENUM(iter); status = S_OK; } @@ -995,12 +999,13 @@ ClrDataAssembly::EnumModule( EX_TRY { - Assembly::ModuleIterator* iter = - FROM_CDENUM(Assembly::ModuleIterator, *handle); - if (iter->Next()) + TrivialModuleIterator* iter = FROM_CDENUM(TrivialModuleIterator, *handle); + if (iter->m_module) { *mod = new (nothrow) - ClrDataModule(m_dac, iter->GetModule()); + ClrDataModule(m_dac, iter->m_module); + + iter->m_module = NULL; status = *mod ? S_OK : E_OUTOFMEMORY; } else @@ -1031,8 +1036,7 @@ ClrDataAssembly::EndEnumModules( EX_TRY { - Assembly::ModuleIterator* iter = - FROM_CDENUM(Assembly::ModuleIterator, handle); + TrivialModuleIterator* iter = FROM_CDENUM(TrivialModuleIterator, handle); delete iter; status = S_OK; } @@ -1170,7 +1174,7 @@ ClrDataAssembly::GetFileName( { COUNT_T _nameLen; - if (m_assembly->GetManifestFile()->GetPath(). + if (m_assembly->GetPEAssembly()->GetPath(). DacGetUnicode(bufLen, name, &_nameLen)) { if (nameLen) diff --git a/src/coreclr/debug/di/breakpoint.cpp b/src/coreclr/debug/di/breakpoint.cpp index eb156c49e04d9..ad45df5c618ac 100644 --- a/src/coreclr/debug/di/breakpoint.cpp +++ b/src/coreclr/debug/di/breakpoint.cpp @@ -201,7 +201,7 @@ HRESULT CordbFunctionBreakpoint::Activate(BOOL fActivate) pProcess->InitIPCEvent(pEvent, DB_IPCE_BREAKPOINT_ADD, true, pAppDomain->GetADToken()); pEvent->BreakpointData.funcMetadataToken = m_code->GetMetadataToken(); - pEvent->BreakpointData.vmDomainFile = m_code->GetModule()->GetRuntimeDomainFile(); + pEvent->BreakpointData.vmDomainAssembly = m_code->GetModule()->GetRuntimeDomainAssembly(); pEvent->BreakpointData.encVersion = m_code->GetVersion(); BOOL codeIsIL = m_code->IsIL(); diff --git a/src/coreclr/debug/di/cordb.cpp b/src/coreclr/debug/di/cordb.cpp index e195f3731a9e6..2f014d1fa587c 100644 --- a/src/coreclr/debug/di/cordb.cpp +++ b/src/coreclr/debug/di/cordb.cpp @@ -84,16 +84,6 @@ //***************************************************************************** STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb) { -#if !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - // This API should not be called for Windows CoreCLR unless we are doing interop-debugging - // (which is only supported internally). Use code:CoreCLRCreateCordbObject instead. - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) - { - _ASSERTE(!"Deprecated entry point CreateCordbObject() is called on Windows CoreCLR\n"); - return E_NOTIMPL; - } -#endif // !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - if (ppCordb == NULL) { return E_INVALIDARG; diff --git a/src/coreclr/debug/di/divalue.cpp b/src/coreclr/debug/di/divalue.cpp index b8c9e745260db..5e79a5ee1c92b 100644 --- a/src/coreclr/debug/di/divalue.cpp +++ b/src/coreclr/debug/di/divalue.cpp @@ -2464,7 +2464,7 @@ HRESULT CordbObjectValue::EnumerateExceptionCallStack(ICorDebugExceptionObjectCa CorDebugExceptionObjectStackFrame& currentStackFrame = pStackFrames[index]; CordbAppDomain* pAppDomain = GetProcess()->LookupOrCreateAppDomain(currentDacFrame.vmAppDomain); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(currentDacFrame.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(currentDacFrame.vmDomainAssembly); hr = pModule->QueryInterface(IID_ICorDebugModule, reinterpret_cast(¤tStackFrame.pModule)); _ASSERTE(SUCCEEDED(hr)); @@ -2653,18 +2653,18 @@ HRESULT CordbObjectValue::GetFunctionHelper(ICorDebugFunction **ppFunction) return hr; mdMethodDef functionMethodDef = 0; - VMPTR_DomainFile functionDomainFile; + VMPTR_DomainAssembly functionDomainAssembly; NativeCodeFunctionData nativeCodeForDelFunc; - hr = pDAC->GetDelegateFunctionData(delType, pDelegateObj, &functionDomainFile, &functionMethodDef); + hr = pDAC->GetDelegateFunctionData(delType, pDelegateObj, &functionDomainAssembly, &functionMethodDef); if (hr != S_OK) return hr; // TODO: How to ensure results are sanitized? // Also, this is expensive. Do we really care that much about this? - pDAC->GetNativeCodeInfo(functionDomainFile, functionMethodDef, &nativeCodeForDelFunc); + pDAC->GetNativeCodeInfo(functionDomainAssembly, functionMethodDef, &nativeCodeForDelFunc); - RSSmartPtr funcModule(GetProcess()->LookupOrCreateModule(functionDomainFile)); + RSSmartPtr funcModule(GetProcess()->LookupOrCreateModule(functionDomainAssembly)); RSSmartPtr func; { RSLockHolder lockHolder(GetProcess()->GetProcessLock()); diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index 6d6a7a55befa2..55f9e8a29c87d 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -48,17 +48,17 @@ STDAPI ReOpenMetaDataWithMemoryEx( // // Arguments: // pProcess - process that this module lives in -// vmDomainFile - CLR cookie for module. +// vmDomainAssembly - CLR cookie for module. CordbModule::CordbModule( CordbProcess * pProcess, VMPTR_Module vmModule, - VMPTR_DomainFile vmDomainFile) -: CordbBase(pProcess, vmDomainFile.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainFile), enumCordbModule), + VMPTR_DomainAssembly vmDomainAssembly) +: CordbBase(pProcess, vmDomainAssembly.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainAssembly), enumCordbModule), m_pAssembly(0), m_pAppDomain(0), m_classes(11), m_functions(101), - m_vmDomainFile(vmDomainFile), + m_vmDomainAssembly(vmDomainAssembly), m_vmModule(vmModule), m_EnCCount(0), m_fForceMetaDataSerialize(FALSE), @@ -84,11 +84,11 @@ CordbModule::CordbModule( m_fInMemory = modInfo.fInMemory; m_vmPEFile = modInfo.vmPEAssembly; - if (!vmDomainFile.IsNull()) + if (!vmDomainAssembly.IsNull()) { - DomainFileInfo dfInfo; + DomainAssemblyInfo dfInfo; - pProcess->GetDAC()->GetDomainFileData(vmDomainFile, &dfInfo); // throws + pProcess->GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &dfInfo); // throws m_pAppDomain = pProcess->LookupOrCreateAppDomain(dfInfo.vmAppDomain); m_pAssembly = m_pAppDomain->LookupOrCreateAssembly(dfInfo.vmDomainAssembly); @@ -115,21 +115,21 @@ CordbModule::CordbModule( // Callback helper for code:CordbModule::DbgAssertModuleDeleted // // Arguments -// vmDomainFile - domain file in the enumeration +// vmDomainAssembly - domain file in the enumeration // pUserData - pointer to the CordbModule that we just got an exit event for. // -void DbgAssertModuleDeletedCallback(VMPTR_DomainFile vmDomainFile, void * pUserData) +void DbgAssertModuleDeletedCallback(VMPTR_DomainAssembly vmDomainAssembly, void * pUserData) { CordbModule * pThis = reinterpret_cast(pUserData); INTERNAL_DAC_CALLBACK(pThis->GetProcess()); - if (!pThis->m_vmDomainFile.IsNull()) + if (!pThis->m_vmDomainAssembly.IsNull()) { - VMPTR_DomainFile vmDomainFileDeleted = pThis->m_vmDomainFile; + VMPTR_DomainAssembly vmDomainAssemblyDeleted = pThis->m_vmDomainAssembly; - CONSISTENCY_CHECK_MSGF((vmDomainFileDeleted != vmDomainFile), - ("A Module Unload event was sent for a module, but it still shows up in the enumeration.\n vmDomainFileDeleted=%p\n", - VmPtrToCookie(vmDomainFileDeleted))); + CONSISTENCY_CHECK_MSGF((vmDomainAssemblyDeleted != vmDomainAssembly), + ("A Module Unload event was sent for a module, but it still shows up in the enumeration.\n vmDomainAssemblyDeleted=%p\n", + VmPtrToCookie(vmDomainAssemblyDeleted))); } } @@ -1499,7 +1499,7 @@ HRESULT CordbModule::EnableClassLoadCallbacks(BOOL bClassLoadCallbacks) if (m_fDynamic && !bClassLoadCallbacks) return E_INVALIDARG; - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; // Send a Set Class Load Flag event to the left side. There is no need to wait for a response, and this can be @@ -1511,7 +1511,7 @@ HRESULT CordbModule::EnableClassLoadCallbacks(BOOL bClassLoadCallbacks) DB_IPCE_SET_CLASS_LOAD_FLAG, false, (GetAppDomain()->GetADToken())); - event.SetClassLoad.vmDomainFile = this->m_vmDomainFile; + event.SetClassLoad.vmDomainAssembly = this->m_vmDomainAssembly; event.SetClassLoad.flag = (bClassLoadCallbacks == TRUE); HRESULT hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, @@ -2041,7 +2041,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) return E_INVALIDARG; } - if (m_vmDomainFile.IsNull() || m_pAppDomain == NULL) + if (m_vmDomainAssembly.IsNull() || m_pAppDomain == NULL) { return E_UNEXPECTED; } @@ -2050,7 +2050,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) *ppClass = NULL; EX_TRY { - TypeRefData inData = {m_vmDomainFile, token}; + TypeRefData inData = {m_vmDomainAssembly, token}; TypeRefData outData; { @@ -2058,7 +2058,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) pProcess->GetDAC()->ResolveTypeReference(&inData, &outData); } - CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainFile); + CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainAssembly); IfFailThrow(pModule->LookupClassByToken(outData.typeToken, ppClass)); } EX_CATCH_HRESULT(hr); @@ -2271,7 +2271,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, FAIL_IF_NEUTERED(this); INTERNAL_SYNC_API_ENTRY(this->GetProcess()); // - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; #ifdef FEATURE_ENC_SUPPORTED @@ -2288,7 +2288,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, DebuggerIPCEvent event; GetProcess()->InitIPCEvent(&event, DB_IPCE_APPLY_CHANGES, false, VMPTR_AppDomain::NullPtr()); - event.ApplyChanges.vmDomainFile = this->m_vmDomainFile; + event.ApplyChanges.vmDomainAssembly = this->m_vmDomainAssembly; // Have the left-side create a buffer for us to store the delta into ULONG cbSize = cbMetaData+cbIL; @@ -2354,7 +2354,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, CordbModule* pModule = NULL; - pModule = pAppDomain->LookupOrCreateModule(retEvent->EnCUpdate.vmDomainFile); // throws + pModule = pAppDomain->LookupOrCreateModule(retEvent->EnCUpdate.vmDomainAssembly); // throws _ASSERTE(pModule != NULL); // update to the newest version @@ -2412,7 +2412,7 @@ HRESULT CordbModule::SetJMCStatus( FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; // @todo -allow the other parameters. These are functions that have default status @@ -2431,7 +2431,7 @@ HRESULT CordbModule::SetJMCStatus( // Tell the LS that this module is/is not user code DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_SET_MODULE_JMC_STATUS, true, this->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_vmDomainFile; + event.SetJMCFunctionStatus.vmDomainAssembly = m_vmDomainAssembly; event.SetJMCFunctionStatus.dwStatus = fIsUserCode; @@ -2520,10 +2520,10 @@ CordbAssembly * CordbModule::ResolveAssemblyInternal(mdToken tkAssemblyRef) CordbAssembly * pAssembly = NULL; - if (!m_vmDomainFile.IsNull()) + if (!m_vmDomainAssembly.IsNull()) { // Get DAC to do the real work to resolve the assembly - VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainFile, tkAssemblyRef); + VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainAssembly, tkAssemblyRef); // now find the ICorDebugAssembly corresponding to it if (!vmDomainAssembly.IsNull() && m_pAppDomain != NULL) @@ -2694,7 +2694,7 @@ HRESULT CordbModule::SetJITCompilerFlags(DWORD dwFlags) if (SUCCEEDED(hr)) { // DD interface will check if it's a valid time to change the flags. - hr = pProcess->GetDAC()->SetCompilerFlags(GetRuntimeDomainFile(), fAllowJitOpts, fEnableEnC); + hr = pProcess->GetDAC()->SetCompilerFlags(GetRuntimeDomainAssembly(), fAllowJitOpts, fEnableEnC); } } } @@ -2730,7 +2730,7 @@ HRESULT CordbModule::GetJITCompilerFlags(DWORD *pdwFlags ) BOOL fEnableEnC; pProcess->GetDAC()->GetCompilerFlags ( - GetRuntimeDomainFile(), + GetRuntimeDomainAssembly(), &fAllowJitOpts, &fEnableEnC); @@ -5169,8 +5169,8 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffsetImpl(Instantiation *currentInst int skipBytes = 0; -#if defined(TARGET_X86) && defined(FEATURE_CORESYSTEM) - // Skip nop sleds on x86 coresystem. The JIT adds these instructions as a security measure, +#if defined(PSEUDORANDOM_NOP_INSERTION) + // Skip nop sleds the JIT adds. These instructions as a security measure, // and incorrectly reports to us the wrong offset of the call instruction. const BYTE nop_opcode = 0x90; while (fetched && nativeBuffer[0] == nop_opcode) diff --git a/src/coreclr/debug/di/nativepipeline.h b/src/coreclr/debug/di/nativepipeline.h index f1b973ea5967c..fc03b27772474 100644 --- a/src/coreclr/debug/di/nativepipeline.h +++ b/src/coreclr/debug/di/nativepipeline.h @@ -146,28 +146,6 @@ class INativeEventPipeline virtual BOOL TerminateProcess(UINT32 exitCode) = 0; - // - // Resume any suspended threads in the currend process. - // This decreases the suspend count of each thread by at most 1. - // Call multiple times until it returns S_FALSE if you want to really ensure - // all threads are running. - // - // Notes: - // On Windows the OS may suspend threads when continuing a 2nd-chance exception. - // Call this to get them resumed again. On other platforms this - // will typically be a no-op, so I provide a default implementation to avoid - // everyone having to override this. - // - // Return Value: - // S_OK if at least one thread was resumed from a suspended state - // S_FALSE if nothing was done - // An error code indicating why we were not able to attempt this - - virtual HRESULT EnsureThreadsRunning() - { - return S_FALSE; - } - #ifdef TARGET_UNIX // Used by debugger side (RS) to cleanup the target (LS) named pipes // and semaphores when the debugger detects the debuggee process exited. diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index 59af4cc8d9c64..1abed121f3e5a 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -414,7 +414,6 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( WCHAR *mutableFilePath = (WCHAR *)filePath; -#if defined(FEATURE_CORESYSTEM) size_t pathLen = wcslen(mutableFilePath); const WCHAR *nidll = W(".ni.dll"); @@ -429,7 +428,6 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( { wcscpy_s(mutableFilePath+pathLen-dllLen, dllLen, W(".exe")); } -#endif//FEATURE_CORESYSTEM ALLOW_DATATARGET_MISSING_MEMORY( pMDII = LookupMetaDataFromDebuggerForSingleFile(pModule, mutableFilePath, dwImageTimeStamp, dwImageSize); @@ -2564,10 +2562,10 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbAppDomain* pAppD { VMPTR_AppDomain appDomain; VMPTR_Module mod; - VMPTR_DomainFile domainFile; + VMPTR_DomainAssembly domainAssembly; HRESULT hr = E_FAIL; - if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainFile)) + if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainAssembly)) { if (pAppDomainOverride) { @@ -4431,15 +4429,15 @@ class ShimModuleCallbackData // Callback invoked from DAC enumeration. // // arguments: - // vmDomainFile - VMPTR for Module + // vmDomainAssembly - VMPTR for Module // pData - a 'this' pointer // - static void Callback(VMPTR_DomainFile vmDomainFile, void * pData) + static void Callback(VMPTR_DomainAssembly vmDomainAssembly, void * pData) { ShimModuleCallbackData * pThis = static_cast (pData); INTERNAL_DAC_CALLBACK(pThis->m_pProcess); - CordbModule * pModule = pThis->m_pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainFile); + CordbModule * pModule = pThis->m_pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainAssembly); pThis->SetAndMoveNext(pModule); } @@ -5065,7 +5063,7 @@ void CordbProcess::RawDispatchEvent( case DB_IPCE_METADATA_UPDATE: { - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->MetadataUpdateData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->MetadataUpdateData.vmDomainAssembly); pModule->RefreshMetaData(); } break; @@ -5073,7 +5071,7 @@ void CordbProcess::RawDispatchEvent( case DB_IPCE_LOAD_MODULE: { _ASSERTE (pAppDomain != NULL); - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainAssembly); { pModule->SetLoadEventContinueMarker(); @@ -5125,12 +5123,12 @@ void CordbProcess::RawDispatchEvent( { STRESS_LOG3(LF_CORDB, LL_INFO100, "RCET::HRCE: unload module on thread %#x Mod:0x%x AD:0x%08x\n", dwVolatileThreadId, - VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile), + VmPtrToCookie(pEvent->UnloadModuleData.vmDomainAssembly), VmPtrToCookie(pEvent->vmAppDomain)); PREFIX_ASSUME (pAppDomain != NULL); - CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainFile); + CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainAssembly); if (module == NULL) { @@ -5151,7 +5149,7 @@ void CordbProcess::RawDispatchEvent( pCallback1->UnloadModule(pAppDomain, module); } - pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile)); + pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainAssembly)); } break; @@ -5163,13 +5161,13 @@ void CordbProcess::RawDispatchEvent( "RCET::HRCE: load class on thread %#x Tok:0x%08x Mod:0x%08x Asm:0x%08x AD:0x%08x\n", dwVolatileThreadId, pEvent->LoadClass.classMetadataToken, - VmPtrToCookie(pEvent->LoadClass.vmDomainFile), + VmPtrToCookie(pEvent->LoadClass.vmDomainAssembly), LsPtrToCookie(pEvent->LoadClass.classDebuggerAssemblyToken), VmPtrToCookie(pEvent->vmAppDomain))); _ASSERTE (pAppDomain != NULL); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadClass.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadClass.vmDomainAssembly); if (pModule == NULL) { LOG((LF_CORDB, LL_INFO100, "Load Class on not-loaded Module - continue()ing!" )); @@ -5221,13 +5219,13 @@ void CordbProcess::RawDispatchEvent( "RCET::HRCE: unload class on thread %#x Tok:0x%08x Mod:0x%08x AD:0x%08x\n", dwVolatileThreadId, pEvent->UnloadClass.classMetadataToken, - VmPtrToCookie(pEvent->UnloadClass.vmDomainFile), + VmPtrToCookie(pEvent->UnloadClass.vmDomainAssembly), VmPtrToCookie(pEvent->vmAppDomain))); // get the appdomain object _ASSERTE (pAppDomain != NULL); - CordbModule *pModule = pAppDomain->LookupOrCreateModule(pEvent->UnloadClass.vmDomainFile); + CordbModule *pModule = pAppDomain->LookupOrCreateModule(pEvent->UnloadClass.vmDomainAssembly); if (pModule == NULL) { LOG((LF_CORDB, LL_INFO100, "Unload Class on not-loaded Module - continue()ing!" )); @@ -5304,7 +5302,7 @@ void CordbProcess::RawDispatchEvent( // determine first whether custom notifications for this type are enabled -- if not // we just return without doing anything. CordbClass * pNotificationClass = LookupClass(pAppDomain, - pEvent->CustomNotification.vmDomainFile, + pEvent->CustomNotification.vmDomainAssembly, pEvent->CustomNotification.classToken); // if the class is NULL, that means the debugger never enabled notifications for it. Otherwise, @@ -5580,7 +5578,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE (pAppDomain != NULL); // Find the Right Side module for this module. - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->UpdateModuleSymsData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->UpdateModuleSymsData.vmDomainAssembly); _ASSERTE(pModule != NULL); // This is a legacy event notification for updated PDBs. @@ -5654,7 +5652,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE(NULL != pAppDomain); - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); CordbFunction * pCurFunction = NULL; @@ -5710,7 +5708,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE(NULL != pAppDomain); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); // Find the function we're remapping to, which must be the latest version @@ -7626,27 +7624,7 @@ HRESULT CordbProcess::GetRuntimeOffsets() { -#if !defined FEATURE_CORESYSTEM - // kernel32!OpenThread does not exist on all platforms (missing on Win98). - // So we need to delay load it. - typedef HANDLE (WINAPI *FPOPENTHREAD)(DWORD dwDesiredAccess, - BOOL bInheritHandle, - DWORD dwThreadId); - - - - HMODULE mod = WszGetModuleHandle(W("kernel32.dll")); - - _ASSERTE(mod != NULL); // can't fail since Kernel32.dll is already loaded. - - const FPOPENTHREAD pfnOpenThread = (FPOPENTHREAD)GetProcAddress(mod, "OpenThread"); - - if (pfnOpenThread != NULL) - { - m_hHelperThread = pfnOpenThread(SYNCHRONIZE, FALSE, dwHelperTid); - CONSISTENCY_CHECK_MSGF(m_hHelperThread != NULL, ("Failed to get helper-thread handle. tid=0x%x\n", dwHelperTid)); - } -#elif TARGET_UNIX +#if TARGET_UNIX m_hHelperThread = NULL; //RS is supposed to be able to live without a helper thread handle. #else m_hHelperThread = OpenThread(SYNCHRONIZE, FALSE, dwHelperTid); @@ -7673,8 +7651,6 @@ HRESULT CordbProcess::GetRuntimeOffsets() m_runtimeOffsets.m_excepNotForRuntimeBPAddr)); LOG((LF_CORDB, LL_INFO10000, " m_notifyRSOfSyncCompleteBPAddr= 0x%p\n", m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr)); - LOG((LF_CORDB, LL_INFO10000, " m_raiseException= 0x%p\n", - m_runtimeOffsets.m_raiseExceptionAddr)); LOG((LF_CORDB, LL_INFO10000, " m_debuggerWordTLSIndex= 0x%08x\n", m_runtimeOffsets.m_debuggerWordTLSIndex)); #endif // FEATURE_INTEROP_DEBUGGING @@ -9819,27 +9795,22 @@ HRESULT CordbProcess::EnsureClrInstanceIdSet() // If we didn't expect a specific CLR, then attempt to attach to any. if (m_clrInstanceId == 0) { - -#ifdef FEATURE_CORESYSTEM + // The only case in which we were allowed to request the "default" CLR instance + // ID is when we're running in V2 mode. In V3, the client is required to pass + // a non-zero value to OpenVirtualProcess. Since V2 is no longer supported we + // no longer attempt to find it. if(m_cordb->GetTargetCLR() != 0) { m_clrInstanceId = PTR_TO_CORDB_ADDRESS(m_cordb->GetTargetCLR()); return S_OK; } -#endif - // The only case in which we're allowed to request the "default" CLR instance - // ID is when we're running in V2 mode. In V3, the client is required to pass - // a non-zero value to OpenVirtualProcess. + // In V3, the client is required to pass a non-zero value to OpenVirtualProcess. + // In V2 mode we should be setting target CLR up front but return an error + // if we haven't. _ASSERTE(m_pShim != NULL); + return E_UNEXPECTED; - HRESULT hr = m_pShim->FindLoadedCLR(&m_clrInstanceId); - if (FAILED(hr)) - { - // Couldn't find a loaded clr - no CLR instance ID yet - _ASSERTE(m_clrInstanceId == 0); - return hr; - } } // We've (now) got a valid CLR instance id @@ -14910,26 +14881,6 @@ HRESULT CordbProcess::IsReadyForDetach() pAppDomain = m_appDomains.FindNext(&foundAppDomain); } - // If we're using the shim, give a chance to early-out if the OS doesn't support detach - // so that the user can continue to debug in that case. - // Ideally we'd just rely on the failure from DebugActiveProcessStop, but by then it's too late - // to recover. This function is our only chance to distinguish between graceful detach failures - // and hard detach failures (after which the process object is neutered). - if (m_pShim != NULL) - { -#if !defined(FEATURE_CORESYSTEM) // CORESYSTEM TODO - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - typedef BOOL (*DebugActiveProcessStopSig) (DWORD); - DebugActiveProcessStopSig pDebugActiveProcessStop = - reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); - if (pDebugActiveProcessStop == NULL) - return COR_E_PLATFORMNOTSUPPORTED; -#endif - } - return S_OK; } @@ -14976,16 +14927,16 @@ void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain) // CordbProcess::LookupClass // Looks up a previously constructed CordbClass instance without creating. May return NULL if the // CordbClass instance doesn't exist. -// Argument: (in) vmDomainFile - pointer to the domainfile for the module +// Argument: (in) vmDomainAssembly - pointer to the domain assembly for the module // (in) mdTypeDef - metadata token for the class // Return value: pointer to a previously created CordbClass instance or NULL in none exists -CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken) +CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainAssembly vmDomainAssembly, mdTypeDef classToken) { _ASSERTE(ThreadHoldsProcessLock()); if (pAppDomain != NULL) { - CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmDomainFile)); + CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmDomainAssembly)); if (pModule != NULL) { return pModule->LookupClass(classToken); @@ -14998,7 +14949,7 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do // Look for a specific module in the process. // // Arguments: -// vmDomainFile - non-null module to lookup +// vmDomainAssembly - non-null module to lookup // // Returns: // a CordbModule object for the given cookie. Object may be from the cache, or created @@ -15006,23 +14957,23 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do // Never returns null. Throws on error. // // Notes: -// A VMPTR_DomainFile has appdomain affinity, but is ultimately scoped to a process. -// So if we get a raw VMPTR_DomainFile (eg, from the stackwalker or from some other +// A VMPTR_DomainAssembly has appdomain affinity, but is ultimately scoped to a process. +// So if we get a raw VMPTR_DomainAssembly (eg, from the stackwalker or from some other // lookup function), then we need to do a process wide lookup since we don't know which // appdomain it's in. If you know the appdomain, you can use code:CordbAppDomain::LookupOrCreateModule. // -CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); RSLockHolder lockHolder(GetProcess()->GetProcessLock()); - _ASSERTE(!vmDomainFile.IsNull()); + _ASSERTE(!vmDomainAssembly.IsNull()); - DomainFileInfo data; - GetDAC()->GetDomainFileData(vmDomainFile, &data); // throws + DomainAssemblyInfo data; + GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &data); // throws CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(data.vmAppDomain); - return pAppDomain->LookupOrCreateModule(vmDomainFile); + return pAppDomain->LookupOrCreateModule(vmDomainAssembly); } //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/debug/di/publish.cpp b/src/coreclr/debug/di/publish.cpp index 1d7741fb9ea75..d27e28a4abc37 100644 --- a/src/coreclr/debug/di/publish.cpp +++ b/src/coreclr/debug/di/publish.cpp @@ -43,54 +43,8 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, { HandleHolder hSnapshotHolder; -#if !defined(FEATURE_CORESYSTEM) - // Load the dll "kernel32.dll". - HModuleHolder hDll = WszLoadLibrary(W("kernel32")); - _ASSERTE(hDll != NULL); - - if (hDll == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to load the dll for enumerating processes. " - "LoadLibrary (kernel32.dll) failed.\n")); - return FALSE; - } -#else - // Load the dll "api-ms-win-obsolete-kernel32-l1-1-0.dll". - HModuleHolder hDll = WszLoadLibrary(W("api-ms-win-obsolete-kernel32-l1-1-0.dll")); - _ASSERTE(hDll != NULL); - - if (hDll == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to load the dll for enumerating processes. " - "LoadLibrary (api-ms-win-obsolete-kernel32-l1-1-0.dll) failed.\n")); - return FALSE; - } -#endif - - // Create the Process' Snapshot - // Get the pointer to the requested function - FARPROC pProcAddr = GetProcAddress(hDll, "CreateToolhelp32Snapshot"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (CreateToolhelp32Snapshot) failed.\n")); - return FALSE; - } - - - - // Handle from CreateToolHelp32Snapshot must be freed via CloseHandle(). - typedef HANDLE CREATETOOLHELP32SNAPSHOT(DWORD, DWORD); - - HANDLE hSnapshot = - ((CREATETOOLHELP32SNAPSHOT *)pProcAddr)(TH32CS_SNAPPROCESS, NULL); - + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (hSnapshot == INVALID_HANDLE_VALUE) { LOG((LF_CORDB, LL_INFO1000, @@ -101,29 +55,13 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. hSnapshotHolder.Assign(hSnapshot); - // Get the first process in the process list - // Get the pointer to the requested function - pProcAddr = GetProcAddress(hDll, "Process32First"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (Process32First) failed.\n")); - return FALSE; - } - PROCESSENTRY32 PE32; // need to initialize the dwSize field before calling Process32First PE32.dwSize = sizeof (PROCESSENTRY32); - typedef BOOL PROCESS32FIRST(HANDLE, LPPROCESSENTRY32); - - BOOL succ = - ((PROCESS32FIRST *)pProcAddr)(hSnapshot, &PE32); - + // Get the first process in the process list + BOOL succ = Process32First(hSnapshot, &PE32); if (succ != TRUE) { LOG((LF_CORDB, LL_INFO1000, @@ -132,29 +70,14 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, return FALSE; } - // Loop over and get all the remaining processes - // Get the pointer to the requested function - pProcAddr = GetProcAddress(hDll, "Process32Next"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (Process32Next) failed.\n")); - return FALSE; - } - - typedef BOOL PROCESS32NEXT(HANDLE, LPPROCESSENTRY32); - int iIndex = 0; do { ProcessId [iIndex++] = PE32.th32ProcessID; - succ = ((PROCESS32NEXT *)pProcAddr)(hSnapshot, &PE32); + succ = Process32Next(hSnapshot, &PE32); } while ((succ == TRUE) && (iIndex < (int)dwArraySize)); @@ -177,16 +100,12 @@ const DWORD SAFETY_TIMEOUT = 2000; // ****************************************** CorpubPublish::CorpubPublish() - : CordbCommonBase(0), - m_fpGetModuleFileNameEx(NULL) + : CordbCommonBase(0) + , m_fpGetModuleFileNameEx(NULL) { // Try to get psapi!GetModuleFileNameExW once, and then every process object can use it. // If we can't get it, then we'll fallback to getting information from the IPC block. -#if !defined(FEATURE_CORESYSTEM) - m_hPSAPIdll = WszLoadLibrary(W("psapi.dll")); -#else m_hPSAPIdll = WszLoadLibrary(W("api-ms-win-obsolete-psapi-l1-1-0.dll")); -#endif if (m_hPSAPIdll != NULL) { diff --git a/src/coreclr/debug/di/rsappdomain.cpp b/src/coreclr/debug/di/rsappdomain.cpp index 081baa95216d5..e140b8a77f13f 100644 --- a/src/coreclr/debug/di/rsappdomain.cpp +++ b/src/coreclr/debug/di/rsappdomain.cpp @@ -829,7 +829,7 @@ CordbAssembly * CordbAppDomain::LookupOrCreateAssembly(VMPTR_Assembly vmAssembly // Lookup or create a module within the appdomain // // Arguments: -// vmDomainFile - non-null module to lookup +// vmDomainAssembly - non-null module to lookup // // Returns: // a CordbModule object for the given cookie. Object may be from the cache, or created @@ -839,26 +839,26 @@ CordbAssembly * CordbAppDomain::LookupOrCreateAssembly(VMPTR_Assembly vmAssembly // Notes: // If you don't know which appdomain the module is in, use code:CordbProcess::LookupOrCreateModule. // -CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_DomainFile vmDomainFile) +CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); CordbModule * pModule; RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // @dbgtodo locking: push this up. - _ASSERTE(!vmDomainFile.IsNull() || !vmModule.IsNull()); + _ASSERTE(!vmDomainAssembly.IsNull() || !vmModule.IsNull()); // check to see if the module is present in this app domain - pModule = m_modules.GetBase(vmDomainFile.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainFile)); + pModule = m_modules.GetBase(vmDomainAssembly.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainAssembly)); if (pModule != NULL) { return pModule; } if (vmModule.IsNull()) - GetProcess()->GetDAC()->GetModuleForDomainFile(vmDomainFile, &vmModule); + GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule); - RSInitHolder pModuleInit(new CordbModule(GetProcess(), vmModule, vmDomainFile)); + RSInitHolder pModuleInit(new CordbModule(GetProcess(), vmModule, vmDomainAssembly)); pModule = pModuleInit.TransferOwnershipToHash(&m_modules); // The appdomains should match. @@ -868,12 +868,12 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_D } -CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); - _ASSERTE(!vmDomainFile.IsNull()); - return LookupOrCreateModule(VMPTR_Module::NullPtr(), vmDomainFile); + _ASSERTE(!vmDomainAssembly.IsNull()); + return LookupOrCreateModule(VMPTR_Module::NullPtr(), vmDomainAssembly); } @@ -890,7 +890,7 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) // invokes this callback. // static -void CordbAppDomain::ModuleEnumerationCallback(VMPTR_DomainFile vmModule, void * pUserData) +void CordbAppDomain::ModuleEnumerationCallback(VMPTR_DomainAssembly vmModule, void * pUserData) { CONTRACTL { diff --git a/src/coreclr/debug/di/rsclass.cpp b/src/coreclr/debug/di/rsclass.cpp index 40d886de9935e..4fe8930712a4e 100644 --- a/src/coreclr/debug/di/rsclass.cpp +++ b/src/coreclr/debug/di/rsclass.cpp @@ -781,11 +781,11 @@ void CordbClass::Init(ClassLoadLevel desiredLoadLevel) if(desiredLoadLevel == FullInfo) { VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); - VMPTR_DomainFile vmDomainFile = m_pModule->GetRuntimeDomainFile(); - if (!vmDomainFile.IsNull()) + VMPTR_DomainAssembly vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); + if (!vmDomainAssembly.IsNull()) { - DomainFileInfo info; - pDac->GetDomainFileData(vmDomainFile, &info); + DomainAssemblyInfo info; + pDac->GetDomainAssemblyData(vmDomainAssembly, &info); vmAppDomain = info.vmAppDomain; } pDac->GetClassInfo(vmAppDomain, vmTypeHandle, &m_classInfo); @@ -941,7 +941,7 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, fieldToken, ELEMENT_TYPE_MAX, classToken, - m_pModule->GetRuntimeDomainFile()); + m_pModule->GetRuntimeDomainAssembly()); } else { @@ -966,7 +966,7 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, // This is used only for log messages, and could // be removed. classToken, // metadata token for the class - m_pModule->GetRuntimeDomainFile()); // Domain file for the class + m_pModule->GetRuntimeDomainAssembly()); // Domain file for the class } } // CordbClass::InitFieldData diff --git a/src/coreclr/debug/di/rsfunction.cpp b/src/coreclr/debug/di/rsfunction.cpp index b901a1ded88fe..f2384411bc0f2 100644 --- a/src/coreclr/debug/di/rsfunction.cpp +++ b/src/coreclr/debug/di/rsfunction.cpp @@ -705,7 +705,7 @@ HRESULT CordbFunction::GetILCodeAndSigToken() // and we also fallback on creating an empty ILCode object. // See issue DD 273199 for cases where IL and NGEN metadata mismatch (different RVAs). ALLOW_DATATARGET_MISSING_OR_INCONSISTENT_MEMORY( - pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainFile(), + pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo, &localVarSigToken); @@ -782,7 +782,7 @@ HRESULT CordbFunction::InitParentClassOfFunction() } mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile = m_pModule->GetRuntimeDomainFile(); + VMPTR_DomainAssembly vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); classMetadataToken = InitParentClassOfFunctionHelper(m_MDToken); @@ -795,7 +795,7 @@ HRESULT CordbFunction::InitParentClassOfFunction() CordbAssembly *pAssembly = m_pModule->GetCordbAssembly(); PREFIX_ASSUME(pAssembly != NULL); - CordbModule* pClassModule = pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainFile); + CordbModule* pClassModule = pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainAssembly); PREFIX_ASSUME(pClassModule != NULL); CordbClass *pClass; @@ -850,7 +850,7 @@ HRESULT CordbFunction::InitNativeCodeInfo() // All we actually need is the start address and method desc which are cheap to get relative // to some of the other members. So far this doesn't appear to be a perf hotspot, but if it // shows up in some scenario it wouldn't be too hard to improve it - pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainFile(), m_MDToken, &codeInfo); + pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo); } // populate the m_nativeCode pointer with the code info we found @@ -904,7 +904,7 @@ HRESULT CordbFunction::SetJMCStatus(BOOL fIsUserCode) DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_SET_METHOD_JMC_STATUS, true, m_pModule->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_pModule->GetRuntimeDomainFile(); + event.SetJMCFunctionStatus.vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); event.SetJMCFunctionStatus.funcMetadataToken = m_MDToken; event.SetJMCFunctionStatus.dwStatus = fIsUserCode; @@ -956,7 +956,7 @@ HRESULT CordbFunction::GetJMCStatus(BOOL * pfIsUserCode) // Ask the left-side if a method is user code or not. DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_GET_METHOD_JMC_STATUS, true, m_pModule->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_pModule->GetRuntimeDomainFile(); + event.SetJMCFunctionStatus.vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); event.SetJMCFunctionStatus.funcMetadataToken = m_MDToken; diff --git a/src/coreclr/debug/di/rsmain.cpp b/src/coreclr/debug/di/rsmain.cpp index 5594b299e2d12..cc30e2c84136e 100644 --- a/src/coreclr/debug/di/rsmain.cpp +++ b/src/coreclr/debug/di/rsmain.cpp @@ -961,15 +961,12 @@ Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion) } Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion, const ProcessDescriptor& pd) - : CordbBase(NULL, 0, enumCordb), - m_processes(11), - m_initialized(false), - m_debuggerSpecifiedVersion(iDebuggerVersion), - m_pd(pd) -#ifdef FEATURE_CORESYSTEM - , - m_targetCLR(0) -#endif + : CordbBase(NULL, 0, enumCordb) + , m_processes(11) + , m_initialized(false) + , m_debuggerSpecifiedVersion(iDebuggerVersion) + , m_pd(pd) + , m_targetCLR(0) { g_pRSDebuggingInfo->m_Cordb = this; @@ -1420,10 +1417,7 @@ HRESULT Cordb::SetTargetCLR(HMODULE hmodTargetCLR) if (m_initialized) return E_FAIL; -#ifdef FEATURE_CORESYSTEM m_targetCLR = hmodTargetCLR; -#endif - return S_OK; } @@ -1528,16 +1522,6 @@ bool Cordb::IsInteropDebuggingSupported() // We explicitly refrain from checking the unmanaged callback. See comment in // ICorDebug::SetUnmanagedHandler for details. #ifdef FEATURE_INTEROP_DEBUGGING - -#if !defined(FEATURE_CORESYSTEM) - // Interop debugging is only supported internally on CoreCLR. - // Check if the special reg key is set. If not, then we don't allow interop debugging. - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) - { - return false; - } -#endif // FEATURE_CORESYSTEM - return true; #else return false; diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index 690917c2795a9..acb8d4c32473c 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -2324,9 +2324,7 @@ class Cordb : public CordbBase, public ICorDebug, public ICorDebugRemote CorDebugInterfaceVersion GetDebuggerVersion() const; -#ifdef FEATURE_CORESYSTEM HMODULE GetTargetCLR() { return m_targetCLR; } -#endif private: bool IsCreateProcessSupported(); @@ -2347,11 +2345,7 @@ class Cordb : public CordbBase, public ICorDebug, public ICorDebugRemote // Store information about the process to be debugged ProcessDescriptor m_pd; -//Note - this code could be useful outside coresystem, but keeping the change localized -// because we are late in the win8 release -#ifdef FEATURE_CORESYSTEM HMODULE m_targetCLR; -#endif }; @@ -2511,13 +2505,13 @@ class CordbAppDomain : public CordbBase, CordbModule * GetModuleFromMetaDataInterface(IUnknown *pIMetaData); // Lookup a module from the cache. Create and to the cache if needed. - CordbModule * LookupOrCreateModule(VMPTR_Module vmModuleToken, VMPTR_DomainFile vmDomainFileToken); + CordbModule * LookupOrCreateModule(VMPTR_Module vmModuleToken, VMPTR_DomainAssembly vmDomainAssemblyToken); // Lookup a module from the cache. Create and to the cache if needed. - CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFileToken); + CordbModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssemblyToken); // Callback from DAC for module enumeration - static void ModuleEnumerationCallback(VMPTR_DomainFile vmModule, void * pUserData); + static void ModuleEnumerationCallback(VMPTR_DomainAssembly vmModule, void * pUserData); // Use DAC to add any modules for this assembly. void PrepopulateModules(); @@ -2549,7 +2543,7 @@ class CordbAppDomain : public CordbBase, // Cache of modules in this appdomain. In the VM, modules live in an assembly. // This cache lives on the appdomain because we generally want to do appdomain (or process) // wide lookup. - // This is indexed by VMPTR_DomainFile, which has appdomain affinity. + // This is indexed by VMPTR_DomainAssembly, which has appdomain affinity. // This is populated by code:CordbAppDomain::LookupOrCreateModule (which may be invoked // anytime the RS gets hold of a VMPTR), and are removed at the unload event. CordbSafeHashTable m_modules; @@ -3460,9 +3454,9 @@ class CordbProcess : // Looks up a previously constructed CordbClass instance without creating. May return NULL if the // CordbClass instance doesn't exist. - CordbClass * LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken); + CordbClass * LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainAssembly vmDomainAssembly, mdTypeDef classToken); - CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFile); + CordbModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly); #ifdef FEATURE_INTEROP_DEBUGGING CordbUnmanagedThread *GetUnmanagedThread(DWORD dwThreadId) @@ -4147,7 +4141,7 @@ class CordbModule : public CordbBase, public: CordbModule(CordbProcess * process, VMPTR_Module vmModule, - VMPTR_DomainFile vmDomainFile); + VMPTR_DomainAssembly vmDomainAssembly); virtual ~CordbModule(); virtual void Neuter(); @@ -4354,9 +4348,9 @@ class CordbModule : public CordbBase, const WCHAR * GetNGenImagePath(); - const VMPTR_DomainFile GetRuntimeDomainFile () + const VMPTR_DomainAssembly GetRuntimeDomainAssembly () { - return m_vmDomainFile; + return m_vmDomainAssembly; } const VMPTR_Module GetRuntimeModule() @@ -4391,7 +4385,7 @@ class CordbModule : public CordbBase, // The real handle into the VM for a module. This is appdomain aware. // This is the primary VM counterpart for the CordbModule. - VMPTR_DomainFile m_vmDomainFile; + VMPTR_DomainAssembly m_vmDomainAssembly; VMPTR_Module m_vmModule; @@ -4806,7 +4800,7 @@ class CordbType : public CordbBase, public ICorDebugType, public ICorDebugType2 void DestNaryType(Instantiation *pInst); CorElementType GetElementType() { return m_elementType; } - VMPTR_DomainFile GetDomainFile(); + VMPTR_DomainAssembly GetDomainAssembly(); VMPTR_Module GetModule(); // If this is a ptr type, get the CordbType that it points to. @@ -6266,10 +6260,6 @@ class CordbThread : public CordbBase, public ICorDebugThread, BOOL ConvertFrameForILMethodWithoutMetadata(ICorDebugFrame * pFrame, ICorDebugInternalFrame2 ** ppInternalFrame2); - // Gets/sets m_fCreationEventQueued - bool CreateEventWasQueued(); - void SetCreateEventQueued(); - //----------------------------------------------------------- // Data members //----------------------------------------------------------- @@ -6327,11 +6317,6 @@ class CordbThread : public CordbBase, public ICorDebugThread, // Both events will set this bit high. Be careful not to reset this bit inbetween them. bool m_fException; - // True if a creation event has been queued for this thread - // The event may or may not have been dispatched yet - // Bugfix DevDiv2\DevDiv 77523 - this is only being set from ShimProcess::QueueFakeThreadAttachEventsNativeOrder - bool m_fCreationEventQueued; - // Object handle for Exception object in debuggee. VMPTR_OBJECTHANDLE m_vmExcepObjHandle; diff --git a/src/coreclr/debug/di/rsstackwalk.cpp b/src/coreclr/debug/di/rsstackwalk.cpp index 42732435db409..b115349593fc2 100644 --- a/src/coreclr/debug/di/rsstackwalk.cpp +++ b/src/coreclr/debug/di/rsstackwalk.cpp @@ -634,7 +634,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) _ASSERTE(pCurrentAppDomain != NULL); // Lookup the module - CordbModule* pModule = pCurrentAppDomain->LookupOrCreateModule(pFuncData->vmDomainFile); + CordbModule* pModule = pCurrentAppDomain->LookupOrCreateModule(pFuncData->vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); // Create or look up a CordbNativeCode. There is one for each jitted instance of a method, diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 577574b796019..38a498752771a 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -81,7 +81,6 @@ CordbThread::CordbThread(CordbProcess * pProcess, VMPTR_Thread vmThread) : m_fFloatStateValid(false), m_floatStackTop(0), m_fException(false), - m_fCreationEventQueued(false), m_EnCRemapFunctionIP(NULL), m_userState(kInvalidUserState), m_hCachedThread(INVALID_HANDLE_VALUE), @@ -1630,8 +1629,8 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); - VMPTR_DomainFile vmDomainFile = pNativeCode->GetModule()->m_vmDomainFile; - _ASSERTE(!vmDomainFile.IsNull()); + VMPTR_DomainAssembly vmDomainAssembly = pNativeCode->GetModule()->m_vmDomainAssembly; + _ASSERTE(!vmDomainAssembly.IsNull()); // If this thread is stopped due to an exception, never allow SetIP if (HasException()) @@ -1643,7 +1642,7 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, GetProcess()->InitIPCEvent(&event, DB_IPCE_SET_IP, true, GetAppDomain()->GetADToken()); event.SetIP.fCanSetIPOnly = fCanSetIPOnly; event.SetIP.vmThreadToken = m_vmThreadToken; - event.SetIP.vmDomainFile = vmDomainFile; + event.SetIP.vmDomainAssembly = vmDomainAssembly; event.SetIP.mdMethod = pNativeCode->GetMetadataToken(); event.SetIP.vmMethodDesc = pNativeCode->GetVMNativeCodeMethodDescToken(); event.SetIP.startAddress = pNativeCode->GetAddress(); @@ -1655,7 +1654,7 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, "mod:0x%x MethodDef:0x%x offset:0x%x il?:0x%x\n", GetCurrentThreadId(), VmPtrToCookie(m_vmThreadToken), - VmPtrToCookie(vmDomainFile), + VmPtrToCookie(vmDomainAssembly), pNativeCode->GetMetadataToken(), offset, fIsIL)); @@ -2790,21 +2789,6 @@ HRESULT CordbThread::GetBlockingObjects(ICorDebugBlockingObjectEnum **ppBlocking return hr; } -// ---------------------------------------------------------------------------- -// CordbThread::SetCreateEventQueued -void CordbThread::SetCreateEventQueued() -{ - m_fCreationEventQueued = true; -} - -// ---------------------------------------------------------------------------- -// CordbThread::CreateEventWasQueued -bool CordbThread::CreateEventWasQueued() -{ - return m_fCreationEventQueued; -} - - #ifdef FEATURE_INTEROP_DEBUGGING /* ------------------------------------------------------------------------- * * Unmanaged Thread classes @@ -5265,7 +5249,7 @@ CordbInternalFrame::CordbInternalFrame(CordbThread * pThread, // Find the module of the function. Note that this module isn't necessarily in the same domain as our frame. // FuncEval frames can point to methods they are going to invoke in another domain. CordbModule * pModule = NULL; - pModule = GetProcess()->LookupOrCreateModule(pData->stubFrame.vmDomainFile); + pModule = GetProcess()->LookupOrCreateModule(pData->stubFrame.vmDomainAssembly); _ASSERTE(pModule != NULL); // @@ -9661,7 +9645,7 @@ HRESULT CordbEval::CallParameterizedFunction(ICorDebugFunction *pFunction, event.FuncEval.vmThreadToken = m_thread->m_vmThreadToken; event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = m_function->GetMetadataToken(); - event.FuncEval.vmDomainFile = m_function->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_function->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = nArgs; event.FuncEval.genericArgsCount = nTypeArgs; @@ -9844,7 +9828,7 @@ HRESULT CordbEval::NewParameterizedObject(ICorDebugFunction * pConstructor, event.FuncEval.vmThreadToken = m_thread->m_vmThreadToken; event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = m_function->GetMetadataToken(); - event.FuncEval.vmDomainFile = m_function->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_function->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = nArgs; event.FuncEval.genericArgsCount = nTypeArgs; @@ -9945,7 +9929,7 @@ HRESULT CordbEval::NewParameterizedObjectNoConstructor(ICorDebugClass * pClass, event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = (mdTypeDef)m_class->m_id; - event.FuncEval.vmDomainFile = m_class->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_class->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = nTypeArgs; @@ -10040,7 +10024,7 @@ HRESULT CordbEval::NewStringWithLength(LPCWSTR wszString, UINT iLength) // Note: no function or module here... event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = mdTypeDefNil; - event.FuncEval.vmDomainFile = VMPTR_DomainFile::NullPtr(); + event.FuncEval.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = 0; event.FuncEval.genericArgsNodeCount = 0; @@ -10157,7 +10141,7 @@ HRESULT CordbEval::NewParameterizedArray(ICorDebugType * pElementType, // Note: no function or module here... event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = mdTypeDefNil; - event.FuncEval.vmDomainFile = VMPTR_DomainFile::NullPtr(); + event.FuncEval.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = 1; diff --git a/src/coreclr/debug/di/rstype.cpp b/src/coreclr/debug/di/rstype.cpp index 3d807bb2434f5..af6a8f5e14a58 100644 --- a/src/coreclr/debug/di/rstype.cpp +++ b/src/coreclr/debug/di/rstype.cpp @@ -1191,7 +1191,7 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Basic DebuggerIPCE_ExpandedTypeData e; e.elementType = et; e.ClassTypeData.metadataToken = data->metadataToken; - e.ClassTypeData.vmDomainFile = data->vmDomainFile; + e.ClassTypeData.vmDomainAssembly = data->vmDomainAssembly; e.ClassTypeData.vmModule = data->vmModule; e.ClassTypeData.typeHandle = data->vmTypeHandle; return CordbType::TypeDataToType(pAppDomain, &e, pRes); @@ -1254,7 +1254,7 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Expan CordbModule * pClassModule = NULL; EX_TRY { - pClassModule = pAppDomain->LookupOrCreateModule(data->ClassTypeData.vmModule, data->ClassTypeData.vmDomainFile); + pClassModule = pAppDomain->LookupOrCreateModule(data->ClassTypeData.vmModule, data->ClassTypeData.vmDomainAssembly); } EX_CATCH_HRESULT(hr); if( pClassModule == NULL ) @@ -1611,7 +1611,7 @@ HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit) // CordbProcess *pProcess = GetProcess(); mdTypeDef metadataToken; - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); VMPTR_Module vmModule = VMPTR_Module::NullPtr(); { @@ -1620,13 +1620,13 @@ HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit) m_elementType, &metadataToken, &vmModule, - &vmDomainFile); + &vmDomainAssembly); } // // Step 2) Lookup CordbClass based off token + Module. // - CordbModule * pTypeModule = m_appdomain->LookupOrCreateModule(vmModule, vmDomainFile); + CordbModule * pTypeModule = m_appdomain->LookupOrCreateModule(vmModule, vmDomainAssembly); _ASSERTE(pTypeModule != NULL); IfFailThrow(pTypeModule->LookupOrCreateClass(metadataToken, &m_pClass)); @@ -1704,7 +1704,7 @@ HRESULT CordbType::InitInstantiationFieldInfo(BOOL fForceInit) // this may be called multiple times. Each call will discard previous values in m_fieldList and reinitialize // the list with updated information RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainFile(), + pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainAssembly(), m_typeHandleExact, typeHandleApprox, &m_fieldList, @@ -1876,23 +1876,23 @@ CordbType::GetUnboxedObjectSize(ULONG32 *pObjectSize) } } -VMPTR_DomainFile CordbType::GetDomainFile() +VMPTR_DomainAssembly CordbType::GetDomainAssembly() { if (m_pClass != NULL) { CordbModule * pModule = m_pClass->GetModule(); if (pModule) { - return pModule->m_vmDomainFile; + return pModule->m_vmDomainAssembly; } else { - return VMPTR_DomainFile::NullPtr(); + return VMPTR_DomainAssembly::NullPtr(); } } else { - return VMPTR_DomainFile::NullPtr(); + return VMPTR_DomainAssembly::NullPtr(); } } @@ -1937,7 +1937,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) case ELEMENT_TYPE_PTR: data->elementType = m_elementType; data->metadataToken = mdTokenNil; - data->vmDomainFile = VMPTR_DomainFile::NullPtr(); + data->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); data->vmTypeHandle = m_typeHandleExact; if (data->vmTypeHandle.IsNull()) { @@ -1950,7 +1950,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) _ASSERTE(m_pClass != NULL); data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS; data->metadataToken = m_pClass->MDToken(); - data->vmDomainFile = GetDomainFile(); + data->vmDomainAssembly = GetDomainAssembly(); data->vmTypeHandle = m_typeHandleExact; if (m_pClass->HasTypeParams() && data->vmTypeHandle.IsNull()) { @@ -1961,7 +1961,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) // This includes all the "primitive" types, in which CorElementType is a sufficient description. data->elementType = m_elementType; data->metadataToken = mdTokenNil; - data->vmDomainFile = VMPTR_DomainFile::NullPtr(); + data->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); data->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); break; } @@ -2001,7 +2001,7 @@ void CordbType::TypeToExpandedTypeData(DebuggerIPCE_ExpandedTypeData *data) { data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS; data->ClassTypeData.metadataToken = m_pClass->GetToken(); - data->ClassTypeData.vmDomainFile = GetDomainFile(); + data->ClassTypeData.vmDomainAssembly = GetDomainAssembly(); data->ClassTypeData.vmModule = GetModule(); data->ClassTypeData.typeHandle = VMPTR_TypeHandle::NullPtr(); @@ -2339,14 +2339,14 @@ HRESULT CordbType::GetTypeID(COR_TYPEID *pId) { mdTypeDef mdToken; VMPTR_Module vmModule = VMPTR_Module::NullPtr(); - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); // get module and token of the simple type GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), et, &mdToken, &vmModule, - &vmDomainFile); + &vmDomainAssembly); vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); } diff --git a/src/coreclr/debug/di/shimpriv.h b/src/coreclr/debug/di/shimpriv.h index 26a939ee8a3a8..15efec5647349 100644 --- a/src/coreclr/debug/di/shimpriv.h +++ b/src/coreclr/debug/di/shimpriv.h @@ -426,9 +426,6 @@ class ShimProcess // Helper to queue fake assembly and mdule events void QueueFakeAssemblyAndModuleEvent(ICorDebugAssembly * pAssembly); - // Queue fake thread-create events on attach. Order via native threads. - HRESULT QueueFakeThreadAttachEventsNativeOrder(); - // Queue fake thread-create events on attach. No ordering. HRESULT QueueFakeThreadAttachEventsNoOrder(); @@ -491,9 +488,6 @@ class ShimProcess // dispatching an event. void PreDispatchEvent(bool fRealCreateProcessEvent = false); - // Look for a CLR in the process and if found, return it's instance ID - HRESULT FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId); - // Retrieve the IP address and the port number of the debugger proxy. MachineInfo GetMachineInfo(); @@ -526,9 +520,6 @@ class ShimProcess HANDLE m_markAttachPendingEvent; HANDLE m_terminatingEvent; - // Finds the base address of [core]clr.dll - CORDB_ADDRESS GetCLRInstanceBaseAddress(); - // // Event Queues // diff --git a/src/coreclr/debug/di/shimprocess.cpp b/src/coreclr/debug/di/shimprocess.cpp index 72da6068e8235..8d60f954b4a71 100644 --- a/src/coreclr/debug/di/shimprocess.cpp +++ b/src/coreclr/debug/di/shimprocess.cpp @@ -17,10 +17,6 @@ #include #include "shimpriv.h" -#if !defined(FEATURE_CORESYSTEM) -#include -#endif - //--------------------------------------------------------------------------------------- // // Ctor for a ShimProcess @@ -871,8 +867,6 @@ HRESULT ShimProcess::HandleWin32DebugEvent(const DEBUG_EVENT * pEvent) if (!fSkipResume) { ::Sleep(500); - hrIgnore = GetNativePipeline()->EnsureThreadsRunning(); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hrIgnore); } } } @@ -1020,9 +1014,6 @@ void ShimProcess::QueueFakeAttachEventsIfNeeded(bool fRealCreateProcessEvent) // same order that V2 used. So without using platform-specific thread-enumeration, // we can't get the V2 ordering. // -// Compare to code:ShimProcess::QueueFakeThreadAttachEventsNativeOrder, -// which sends threads in the OS native thread create order. -// HRESULT ShimProcess::QueueFakeThreadAttachEventsNoOrder() { ICorDebugProcess * pProcess = GetProcess(); @@ -1061,136 +1052,6 @@ HRESULT ShimProcess::QueueFakeThreadAttachEventsNoOrder() return S_OK; } -//--------------------------------------------------------------------------------------- -// Send fake Thread-create events for attach, using the order of the OS native -// thread list. -// -// Returns: -// S_OK on success, else error. -// -// Notes: -// This sends fake thread-create events, ala V2 attach. -// See code:ShimProcess::QueueFakeAttachEvents for details -// The order of the thread creates matches the OS's native thread list. -// This is important because the debugger can use the order of thread-create -// callbacks to associate logical thread-ids (0,1,2...) with threads. Users -// may rely on thread 0 always being the main thread. -// In contrast, the order from ICorDebugProcess::EnumerateThreads is random. -// -// Compare to code:ShimProcess::QueueFakeThreadAttachEventsNoOrder, which -// sends the threads in an arbitrary order. -HRESULT ShimProcess::QueueFakeThreadAttachEventsNativeOrder() -{ -#ifdef FEATURE_CORESYSTEM - _ASSERTE("NYI"); - return E_FAIL; -#else - ICorDebugProcess * pProcess = GetProcess(); - - DWORD dwProcessId; - HRESULT hr = pProcess->GetID(&dwProcessId); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - if (FAILED(hr)) - { - return hr; - } - - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - { - hr = HRESULT_FROM_GetLastError(); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - return hr; - } - // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. - HandleHolder hSnapshotHolder(hThreadSnap); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - { - hr = HRESULT_FROM_GetLastError(); - return hr; - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwProcessId) - { - RSExtSmartPtr pThread; - pProcess->GetThread(te32.th32ThreadID, &pThread); - if (pThread != NULL) - { - // If we fail to get the appdomain for some reason, then then - // we can't dispatch this thread callback. But we can still - // finish enumerating. - RSExtSmartPtr pAppDomain; - HRESULT hrGetAppDomain = pThread->GetAppDomain(&pAppDomain); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hrGetAppDomain); - if (pAppDomain != NULL) - { - GetShimCallback()->CreateThread(pAppDomain, pThread); - AddDuplicateCreationEvent(pThread); - - //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications - // mark that this thread has queued a create event - CordbThread* pThreadInternal = static_cast(pThread.GetValue()); - pThreadInternal->SetCreateEventQueued(); - } - } - } - } while(Thread32Next(hThreadSnap, &te32)); - - - //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications - // - - - // Threads which were switched out won't be present in the native thread order enumeration above. - // In order to not miss them we will enumerate all the managed thread objects and for any that we haven't - // already queued a notification for, we will queue a notification now. - RSExtSmartPtr pThreadEnum; - RSExtSmartPtr pThread; - hr = pProcess->EnumerateThreads(&pThreadEnum); - if (FAILED(hr)) - { - return hr; - } - - ULONG cDummy; - - while(SUCCEEDED(pThreadEnum->Next(1, &pThread, &cDummy)) && (pThread != NULL)) - { - RSExtSmartPtr pAppDomain; - hr = pThread->GetAppDomain(&pAppDomain); - CordbThread* pThreadInternal = static_cast(pThread.GetValue()); - - // Getting the appdomain shouldn't fail. If it does, we can't dispatch - // this callback, but we can still dispatch the other thread creates. - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - if (pAppDomain != NULL && !pThreadInternal->CreateEventWasQueued()) - { - GetShimCallback()->CreateThread(pAppDomain, pThread); - AddDuplicateCreationEvent(pThread); - pThreadInternal->SetCreateEventQueued(); - } - pThread.Clear(); - } - - - return S_OK; -#endif -} - //--------------------------------------------------------------------------------------- // Queues the fake Assembly and Module load events // @@ -1476,15 +1337,9 @@ void ShimProcess::QueueFakeAttachEvents() // // Third, Queue all Threads // -#if !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - // Use OS thread enumeration facilities to ensure that the managed thread - // thread order is the same as the corresponding native thread order. - QueueFakeThreadAttachEventsNativeOrder(); -#else // Use ICorDebug to enumerate threads. The order of managed threads may // not match the order the threads were created in. QueueFakeThreadAttachEventsNoOrder(); -#endif // Forth, Queue all Connections. // Enumerate connections is not exposed through ICorDebug, so we need to go use a private hook on CordbProcess. @@ -1730,86 +1585,6 @@ void ShimProcess::PreDispatchEvent(bool fRealCreateProcessEvent /*= false*/) } -// ---------------------------------------------------------------------------- -// ShimProcess::GetCLRInstanceBaseAddress -// Finds the base address of [core]clr.dll -// Arguments: none -// Return value: returns the base address of [core]clr.dll if possible or NULL otherwise -// -CORDB_ADDRESS ShimProcess::GetCLRInstanceBaseAddress() -{ - CORDB_ADDRESS baseAddress = CORDB_ADDRESS(NULL); - DWORD dwPid = m_pLiveDataTarget->GetPid(); - -#if defined(FEATURE_CORESYSTEM) - // Debugger attaching to CoreCLR via CoreCLRCreateCordbObject should have already specified CLR module address. - // Code that help to find it now lives in dbgshim. -#else - // get a "snapshot" of all modules in the target - HandleHolder hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid); - MODULEENTRY32 moduleEntry = { 0 }; - - if (hSnapshot == INVALID_HANDLE_VALUE) - { - // we haven't got a loaded CLR yet - baseAddress = CORDB_ADDRESS(NULL); - } - else - { - // we need to loop through the modules until we find mscorwks.dll - moduleEntry.dwSize = sizeof(MODULEENTRY32); - - if (!Module32First(hSnapshot, &moduleEntry)) - { - baseAddress = CORDB_ADDRESS(NULL); - } - else - { - - do - { - if (!_wcsicmp(moduleEntry.szModule, MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W))) - { - // we found it, so save the base address - baseAddress = PTR_TO_CORDB_ADDRESS(moduleEntry.modBaseAddr); - } - } while (Module32Next(hSnapshot, &moduleEntry)); - } - } -#endif - return baseAddress; -} // ShimProcess::GetCLRInstanceBaseAddress - -// ---------------------------------------------------------------------------- -// ShimProcess::FindLoadedCLR -// -// Description: -// Look for any CLR loaded into the process. If found, return the instance ID for it. -// -// Arguments: -// * pClrInstanceId - out parameter for the instance ID of the CLR -// -// Return Value: -// Returns S_OK if a CLR was found, and stores its instance ID in pClrInstanceId. -// Otherwise returns an error code. -// -// Notes: -// If there are multiple CLRs loaded in the process, the one chosen for the returned -// instance ID is unspecified. -// -HRESULT ShimProcess::FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId) -{ - *pClrInstanceId = GetCLRInstanceBaseAddress(); - - if (*pClrInstanceId == 0) - { - return E_UNEXPECTED; - } - - return S_OK; -} - - //--------------------------------------------------------------------------------------- // // Locates DAC by finding mscordac{wks|core} next to DBI diff --git a/src/coreclr/debug/di/windowspipeline.cpp b/src/coreclr/debug/di/windowspipeline.cpp index cea89e7387400..68ac4a216c660 100644 --- a/src/coreclr/debug/di/windowspipeline.cpp +++ b/src/coreclr/debug/di/windowspipeline.cpp @@ -92,14 +92,7 @@ class WindowsNativePipeline : // Terminate the debuggee process. virtual BOOL TerminateProcess(UINT32 exitCode); - // Resume any suspended threads - virtual HRESULT EnsureThreadsRunning(); - protected: - void UpdateDebugSetProcessKillOnExit(); - - HRESULT IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent); - // Cached value from DebugSetProcessKillOnExit. // This is thread-local, and impacts all debuggees on the thread. bool m_fKillOnExit; @@ -125,46 +118,10 @@ BOOL WindowsNativePipeline::DebugSetProcessKillOnExit(bool fKillOnExit) { // Can't call kernel32!DebugSetProcessKillOnExit until after the event thread // has spawned a debuggee. So cache the value now and call it later. - // This bit is enforced in code:WindowsNativePipeline::UpdateDebugSetProcessKillOnExit m_fKillOnExit = fKillOnExit; return TRUE; } -// Enforces the bit set in code:WindowsNativePipeline::DebugSetProcessKillOnExit -void WindowsNativePipeline::UpdateDebugSetProcessKillOnExit() -{ -#if !defined(FEATURE_CORESYSTEM) - // Late bind to DebugSetProcessKillOnExit - WinXP and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - SIMPLIFYING_ASSUMPTION(hKernel32 != NULL); - if (hKernel32 == NULL) - return; - - typedef BOOL (*DebugSetProcessKillOnExitSig) (BOOL); - DebugSetProcessKillOnExitSig pDebugSetProcessKillOnExit = - reinterpret_cast(GetProcAddress(hKernel32, "DebugSetProcessKillOnExit")); - - // If the API doesn't exist (eg. Win2k) - there isn't anything we can do, just - // silently ignore the request. - if (pDebugSetProcessKillOnExit == NULL) - return; - - BOOL ret = pDebugSetProcessKillOnExit(m_fKillOnExit); - - // Not a good failure path here. - // 1) This shouldn't fail. - // 2) Even if it does, this is likely called after the debuggee - // has already been created, and if this API fails, most scenarios will - // be unaffected, so we don't want to fail the overall debugging session. - SIMPLIFYING_ASSUMPTION(ret); - -#else - // The API doesn't exit on CoreSystem, just return - return; -#endif -} - // Create an process under the debugger. HRESULT WindowsNativePipeline::CreateProcessUnderDebugger( MachineInfo machineInfo, @@ -199,7 +156,6 @@ HRESULT WindowsNativePipeline::CreateProcessUnderDebugger( } m_dwProcessId = lpProcessInformation->dwProcessId; - UpdateDebugSetProcessKillOnExit(); return S_OK; } @@ -213,104 +169,23 @@ HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, const { hr = S_OK; m_dwProcessId = processDescriptor.m_Pid; - UpdateDebugSetProcessKillOnExit(); } else { hr = HRESULT_FROM_GetLastError(); - - // There are at least two scenarios in which DebugActiveProcess() returns E_INVALIDARG: - // 1) if the specified process doesn't exist, or - // 2) if the specified process already has a debugger atttached - // We need to distinguish these two cases in order to return the correct HR. - if (hr == E_INVALIDARG) - { - // Check whether a debugger is known to be already attached. - // Note that this API won't work on some OSes, in which case we err on the side of returning E_INVALIDARG - // even though a debugger may be attached. Another approach could be to assume that if - // OpenProcess succeeded, then DebugActiveProcess must only have failed because a debugger is - // attached. But I think it's better to only return the specific error code if we know for sure - // the case is true. - BOOL fIsDebuggerPresent = FALSE; - if (SUCCEEDED(IsRemoteDebuggerPresent(processDescriptor.m_Pid, &fIsDebuggerPresent))) - { - if (fIsDebuggerPresent) - { - hr = CORDBG_E_DEBUGGER_ALREADY_ATTACHED; - } - } - } } return hr; } -// Determine (if possible) whether a debugger is attached to the target process -HRESULT WindowsNativePipeline::IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent) -{ -#if !defined(FEATURE_CORESYSTEM) - - // Get a process handle for the process ID. - HandleHolder hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); - if (hProc == NULL) - return HRESULT_FROM_GetLastError(); - - // Delay-bind to CheckRemoteDebuggerPresent - WinXP SP1 and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - - typedef BOOL (*CheckRemoteDebuggerPresentSig) (HANDLE, PBOOL); - CheckRemoteDebuggerPresentSig pCheckRemoteDebuggerPresent = - reinterpret_cast(GetProcAddress(hKernel32, "CheckRemoteDebuggerPresent")); - if (pCheckRemoteDebuggerPresent == NULL) - return HRESULT_FROM_GetLastError(); - - // API exists - call it - if (!pCheckRemoteDebuggerPresent(hProc, pfDebuggerPresent)) - return HRESULT_FROM_GetLastError(); - - return S_OK; -#else - - //CoreSystem doesn't have this API - return E_FAIL; -#endif -} - // Detach HRESULT WindowsNativePipeline::DebugActiveProcessStop(DWORD processId) { -#if !defined(FEATURE_CORESYSTEM) - // Late-bind to DebugActiveProcessStop since it's WinXP and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - - typedef BOOL (*DebugActiveProcessStopSig) (DWORD); - DebugActiveProcessStopSig pDebugActiveProcessStop = - reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); - - // Win2K will fail here - can't find DebugActiveProcessStop - if (pDebugActiveProcessStop == NULL) - return HRESULT_FROM_GetLastError(); - - // Ok, the API exists, call it - if (!pDebugActiveProcessStop(processId)) - { - // Detach itself failed - return HRESULT_FROM_GetLastError(); - } -#else - // The API exists, call it if (!::DebugActiveProcessStop(processId)) { // Detach itself failed return HRESULT_FROM_GetLastError(); } -#endif return S_OK; } @@ -359,60 +234,3 @@ BOOL WindowsNativePipeline::TerminateProcess(UINT32 exitCode) return ::TerminateProcess(hProc, exitCode); } - -// Resume any suspended threads (but just once) -HRESULT WindowsNativePipeline::EnsureThreadsRunning() -{ -#ifdef FEATURE_CORESYSTEM - _ASSERTE("NYI"); - return E_FAIL; -#else - _ASSERTE(m_dwProcessId != 0); - - // Take a snapshot of all running threads (similar to ShimProcess::QueueFakeThreadAttachEventsNativeOrder) - // Alternately we could return thread creation/exit in WaitForDebugEvent. But we expect this to be used - // very rarely, so no need to complicate more common codepaths. - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return HRESULT_FROM_GetLastError(); - - // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. - HandleHolder hSnapshotHolder(hThreadSnap); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - return HRESULT_FROM_GetLastError(); - - // Now walk the thread list of the system and attempt to resume any that are part of this process - // Ignore errors - this is a best effort (but ASSERT in CHK builds since we don't expect errors - // in practice - we expect the process to be frozen at a debug event, so no races etc.) - - HRESULT hr = S_FALSE; // no thread was resumed - do - { - if (te32.th32OwnerProcessID == m_dwProcessId) - { - HandleHolder hThread = ::OpenThread(THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID); - _ASSERTE(hThread != NULL); - if (hThread != NULL) - { - // Resume each thread exactly once (if they were suspended multiple times, - // then EnsureThreadsRunning would need to be called multiple times until it - // returned S_FALSE. - DWORD prevCount = ::ResumeThread(hThread); - _ASSERTE(prevCount >= 0); - if (prevCount >= 1) - hr = S_OK; // some thread was resumed - } - } - } while(Thread32Next(hThreadSnap, &te32)); - - return hr; -#endif -} diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 1e326e724250b..bd96c50fc59d3 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -1347,7 +1347,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval // could get unloaded between now and when the funceval actually starts. So we stash an // AppDomain ID which is safe to use after the AD is unloaded. It's only safe to // use the DebuggerModule* after we've verified the ADID is still valid (i.e. by entering that domain). - m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainFile); + m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainAssembly); m_funcEvalKey = pEvalInfo->funcEvalKey; m_argCount = pEvalInfo->argCount; m_targetCodeAddr = NULL; @@ -5187,10 +5187,10 @@ void Debugger::SendSyncCompleteIPCEvent(bool isEESuspendedForGC) } // -// Lookup or create a DebuggerModule for the given pDomainFile. +// Lookup or create a DebuggerModule for the given pDomainAssembly. // // Arguments: -// pDomainFile - non-null domain file. +// pDomainAssembly - non-null domain file. // // Returns: // DebuggerModule instance for the given domain file. May be lazily created. @@ -5199,36 +5199,36 @@ void Debugger::SendSyncCompleteIPCEvent(bool isEESuspendedForGC) // @dbgtodo JMC - this should go away when we get rid of DebuggerModule. // -DebuggerModule * Debugger::LookupOrCreateModule(DomainFile * pDomainFile) +DebuggerModule * Debugger::LookupOrCreateModule(DomainAssembly * pDomainAssembly) { - _ASSERTE(pDomainFile != NULL); - LOG((LF_CORDB, LL_INFO1000, "D::LOCM df=0x%x\n", pDomainFile)); - DebuggerModule * pDModule = LookupOrCreateModule(pDomainFile->GetModule(), pDomainFile->GetAppDomain()); - LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pDomainFile->GetModule(), pDomainFile->GetAppDomain(), pDModule)); + _ASSERTE(pDomainAssembly != NULL); + LOG((LF_CORDB, LL_INFO1000, "D::LOCM df=0x%x\n", pDomainAssembly)); + DebuggerModule * pDModule = LookupOrCreateModule(pDomainAssembly->GetModule(), pDomainAssembly->GetAppDomain()); + LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pDomainAssembly->GetModule(), pDomainAssembly->GetAppDomain(), pDModule)); _ASSERTE(pDModule != NULL); - _ASSERTE(pDModule->GetDomainFile() == pDomainFile); + _ASSERTE(pDModule->GetDomainAssembly() == pDomainAssembly); return pDModule; } -// Overloaded Wrapper around for VMPTR_DomainFile-->DomainFile* +// Overloaded Wrapper around for VMPTR_DomainAssembly-->DomainAssembly* // // Arguments: -// vmDomainFile - VMPTR cookie for a domain file. This can be NullPtr(). +// vmDomainAssembly - VMPTR cookie for a domain file. This can be NullPtr(). // // Returns: // Debugger Module instance for the given domain file. May be lazily created. // // Notes: // VMPTR comes from IPC events -DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { - DomainFile * pDomainFile = vmDomainFile.GetRawPtr(); - if (pDomainFile == NULL) + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetRawPtr(); + if (pDomainAssembly == NULL) { return NULL; } - return LookupOrCreateModule(pDomainFile); + return LookupOrCreateModule(pDomainAssembly); } // Lookup or create a DebuggerModule for the given (Module, AppDomain) pair. @@ -5281,9 +5281,9 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD HRESULT hr = S_OK; EX_TRY { - DomainFile * pDomainFile = pModule->GetDomainFile(); - SIMPLIFYING_ASSUMPTION(pDomainFile != NULL); - dmod = AddDebuggerModule(pDomainFile); // throws + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); + SIMPLIFYING_ASSUMPTION(pDomainAssembly != NULL); + dmod = AddDebuggerModule(pDomainAssembly); // throws } EX_CATCH_HRESULT(hr); SIMPLIFYING_ASSUMPTION(dmod != NULL); // may not be true in OOM cases; but LS doesn't handle OOM. @@ -5293,19 +5293,19 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD _ASSERTE( (dmod == NULL) || (dmod->GetAppDomain() == pAppDomain) ); LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x(Mod=0x%x, DomFile=0x%x, AD=0x%x)\n", - pModule, pAppDomain, dmod, dmod->GetRuntimeModule(), dmod->GetDomainFile(), dmod->GetAppDomain())); + pModule, pAppDomain, dmod, dmod->GetRuntimeModule(), dmod->GetDomainAssembly(), dmod->GetAppDomain())); return dmod; } // Create a new DebuggerModule object // // Arguments: -// pDomainFile- runtime domain file to create debugger module object around +// pDomainAssembly- runtime domain file to create debugger module object around // // Returns: // New instnace of a DebuggerModule. Throws on failure. // -DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) +DebuggerModule* Debugger::AddDebuggerModule(DomainAssembly * pDomainAssembly) { CONTRACTL { @@ -5314,16 +5314,16 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) } CONTRACTL_END; - LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainFile)); + LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainAssembly)); DebuggerDataLockHolder chInfo(this); - Module * pRuntimeModule = pDomainFile->GetCurrentModule(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + Module * pRuntimeModule = pDomainAssembly->GetModule(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); HRESULT hr = CheckInitModuleTable(); IfFailThrow(hr); - DebuggerModule* pModule = new (interopsafe) DebuggerModule(pRuntimeModule, pDomainFile, pAppDomain); + DebuggerModule* pModule = new (interopsafe) DebuggerModule(pRuntimeModule, pDomainAssembly, pAppDomain); _ASSERTE(pModule != NULL); // throws on oom TRACE_ALLOC(pModule); @@ -5332,7 +5332,7 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) // @dbgtodo inspection/exceptions - this may leak module in OOM case. LS is not OOM resilient; and we // expect to get rid of DebuggerModule anyways. - LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x -> dm=0x%x\n", pDomainFile, pModule)); + LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x -> dm=0x%x\n", pDomainAssembly, pModule)); return pModule; } @@ -6246,7 +6246,7 @@ void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, Module *pRuntimeModule = pFD->GetModule(); DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); - ipce->EnCRemap.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + ipce->EnCRemap.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: %s::%s " "dmod:0x%x, methodDef:0x%x \n", @@ -6315,7 +6315,7 @@ void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pFD) Module *pRuntimeModule = pFD->GetModule(); DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); - ipce->EnCRemapComplete.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + ipce->EnCRemapComplete.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRC: %s::%s " @@ -6381,7 +6381,7 @@ void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType, _ASSERTE(pModule->GetDomain()->IsAppDomain()); DebuggerModule * pDModule = LookupOrCreateModule(pModule, pModule->GetDomain()->AsAppDomain()); - event->EnCUpdate.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + event->EnCUpdate.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); m_pRCThread->SendIPCEvent(); @@ -9426,7 +9426,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, DWORD dwModuleName, // length of pszModuleName in chars, not including null. Assembly *pAssembly, AppDomain *pAppDomain, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching) { @@ -9461,13 +9461,13 @@ void Debugger::LoadModule(Module* pRuntimeModule, { // The loader lookups may throw or togggle GC mode, so do them inside a TRY/Catch and // outside any debugger locks. - Module * pManifestModule = pRuntimeModule->GetAssembly()->GetManifestModule(); + Module * pManifestModule = pRuntimeModule->GetAssembly()->GetModule(); _ASSERTE(pManifestModule != pRuntimeModule); _ASSERTE(pManifestModule->IsManifest()); _ASSERTE(pManifestModule->GetAssembly() == pRuntimeModule->GetAssembly()); - DomainFile * pManifestDomainFile = pManifestModule->GetDomainFile(); + DomainAssembly * pManifestDomainAssembly = pManifestModule->GetDomainAssembly(); DebuggerLockHolder dbgLockHolder(this); @@ -9477,7 +9477,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, DebuggerIPCEvent eventMetadataUpdate; InitIPCEvent(&eventMetadataUpdate, DB_IPCE_METADATA_UPDATE, NULL, pAppDomain); - eventMetadataUpdate.MetadataUpdateData.vmDomainFile.SetRawPtr(pManifestDomainFile); + eventMetadataUpdate.MetadataUpdateData.vmDomainAssembly.SetRawPtr(pManifestDomainAssembly); SendRawEvent(&eventMetadataUpdate); } @@ -9499,7 +9499,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, // The RS has logic to ignore duplicate ModuleLoad events. We have to send what could possibly be a dup, though, // due to some really nasty issues with getting proper assembly and module load events from the loader when dealing // with shared assemblies. - module = LookupOrCreateModule(pDomainFile); + module = LookupOrCreateModule(pDomainAssembly); _ASSERTE(module != NULL); @@ -9509,18 +9509,18 @@ void Debugger::LoadModule(Module* pRuntimeModule, module->SetCanChangeJitFlags(true); - // @dbgtodo inspection - Check whether the DomainFile we get is consistent with the Module and AppDomain we get. + // @dbgtodo inspection - Check whether the DomainAssembly we get is consistent with the Module and AppDomain we get. // We should simply things when we actually get rid of DebuggerModule, possibly by just passing the - // DomainFile around. - _ASSERTE(module->GetDomainFile() == pDomainFile); - _ASSERTE(module->GetAppDomain() == pDomainFile->GetAppDomain()); - _ASSERTE(module->GetRuntimeModule() == pDomainFile->GetModule()); + // DomainAssembly around. + _ASSERTE(module->GetDomainAssembly() == pDomainAssembly); + _ASSERTE(module->GetAppDomain() == pDomainAssembly->GetAppDomain()); + _ASSERTE(module->GetRuntimeModule() == pDomainAssembly->GetModule()); // Send a load module event to the Right Side. ipce = m_pRCThread->GetIPCEventSendBuffer(); InitIPCEvent(ipce,DB_IPCE_LOAD_MODULE, pThread, pAppDomain); - ipce->LoadModuleData.vmDomainFile.SetRawPtr(pDomainFile); + ipce->LoadModuleData.vmDomainAssembly.SetRawPtr(pDomainAssembly); m_pRCThread->SendIPCEvent(); @@ -9588,7 +9588,7 @@ void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *p g_pEEInterface->GetThread(), pAppDomain); - ipce->UpdateModuleSymsData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL)); + ipce->UpdateModuleSymsData.vmDomainAssembly.SetRawPtr((module ? module->GetDomainAssembly() : NULL)); m_pRCThread->SendIPCEvent(); } @@ -9695,8 +9695,8 @@ void Debugger::UnloadModule(Module* pRuntimeModule, STRESS_LOG6(LF_CORDB, LL_INFO10000, "D::UM: Unloading RTMod:%#08x (DomFile: %#08x, IsISStream:%#08x); DMod:%#08x(RTMod:%#08x DomFile: %#08x)\n", - pRuntimeModule, pRuntimeModule->GetDomainFile(), false, - module, module->GetRuntimeModule(), module->GetDomainFile()); + pRuntimeModule, pRuntimeModule->GetDomainAssembly(), false, + module, module->GetRuntimeModule(), module->GetDomainAssembly()); // Note: the appdomain the module was loaded in must match the appdomain we're unloading it from. If it doesn't, // then we've either found the wrong DebuggerModule in LookupModule or we were passed bad data. @@ -9705,7 +9705,7 @@ void Debugger::UnloadModule(Module* pRuntimeModule, // Send the unload module event to the Right Side. DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer(); InitIPCEvent(ipce, DB_IPCE_UNLOAD_MODULE, thread, pAppDomain); - ipce->UnloadModuleData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL)); + ipce->UnloadModuleData.vmDomainAssembly.SetRawPtr((module ? module->GetDomainAssembly() : NULL)); ipce->UnloadModuleData.debuggerAssemblyToken.Set(pRuntimeModule->GetClassLoader()->GetAssembly()); m_pRCThread->SendIPCEvent(); @@ -9877,7 +9877,7 @@ void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken, InitIPCEvent(pEvent, DB_IPCE_LOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain); pEvent->LoadClass.classMetadataToken = classMetadataToken; - pEvent->LoadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL)); + pEvent->LoadClass.vmDomainAssembly.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainAssembly() : NULL)); pEvent->LoadClass.classDebuggerAssemblyToken.Set(pAssembly); @@ -9889,7 +9889,7 @@ void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken, InitIPCEvent(pEvent, DB_IPCE_UNLOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain); pEvent->UnloadClass.classMetadataToken = classMetadataToken; - pEvent->UnloadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL)); + pEvent->UnloadClass.vmDomainAssembly.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainAssembly() : NULL)); pEvent->UnloadClass.classDebuggerAssemblyToken.Set(pAssembly); } @@ -9940,10 +9940,10 @@ BOOL Debugger::SendSystemClassLoadUnloadEvent(mdTypeDef classMetadataToken, // Only notify for app domains where the module has been fully loaded already // We used to make a different check here domain->ContainsAssembly() but that - // triggers too early in the loading process. FindDomainFile will not become + // triggers too early in the loading process. FindDomainAssembly will not become // non-NULL until the module is fully loaded into the domain which is what we // want. - if (classModule->GetDomainFile() != NULL ) + if (classModule->GetDomainAssembly() != NULL ) { // Find the Left Side module that this class belongs in. DebuggerModule* pModule = LookupOrCreateModule(classModule, pAppDomain); @@ -10528,7 +10528,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) _ASSERTE(hr == S_OK); DebuggerBreakpoint * pDebuggerBP = NULL; - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->BreakpointData.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->BreakpointData.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->BreakpointData.funcMetadataToken); MethodDesc * pMethodDesc = pEvent->BreakpointData.nativeCodeMethodDescToken.UnWrap(); @@ -10847,7 +10847,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) { LOG((LF_ENC, LL_INFO100, "D::HIPCE: DB_IPCE_APPLY_CHANGES 1\n")); - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->ApplyChanges.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->ApplyChanges.vmDomainAssembly); // // @todo handle error. // @@ -10864,7 +10864,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_CLASS_LOAD_FLAG: { - DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainFile); + DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainAssembly); _ASSERTE(pDebuggerModule != NULL); @@ -10914,7 +10914,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) // unexpected in an OOM situation. Quickly just sanity check them. // Thread * pThread = pEvent->SetIP.vmThreadToken.GetRawPtr(); - Module * pModule = pEvent->SetIP.vmDomainFile.GetRawPtr()->GetModule(); + Module * pModule = pEvent->SetIP.vmDomainAssembly.GetRawPtr()->GetModule(); // Get the DJI for this function DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->SetIP.mdMethod); @@ -11244,7 +11244,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_METHOD_JMC_STATUS: { // Get the info out of the event - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0); @@ -11292,7 +11292,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_GET_METHOD_JMC_STATUS: { // Get the method - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); @@ -11326,7 +11326,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_MODULE_JMC_STATUS: { // Get data out of event - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0); @@ -11818,7 +11818,7 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D case ELEMENT_TYPE_BYREF: res->vmTypeHandle = WrapTypeHandle(th); res->metadataToken = mdTokenNil; - res->vmDomainFile.SetRawPtr(NULL); + res->vmDomainAssembly.SetRawPtr(NULL); break; case ELEMENT_TYPE_CLASS: @@ -11828,14 +11828,14 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D // only set if instantiated res->metadataToken = th.GetCl(); DebuggerModule * pDModule = LookupOrCreateModule(th.GetModule(), pAppDomain); - res->vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + res->vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); break; } default: res->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); res->metadataToken = mdTokenNil; - res->vmDomainFile.SetRawPtr(NULL); + res->vmDomainAssembly.SetRawPtr(NULL); break; } return; @@ -11907,8 +11907,8 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, res->ClassTypeData.typeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); // only set if instantiated res->ClassTypeData.metadataToken = th.GetCl(); DebuggerModule * pModule = LookupOrCreateModule(th.GetModule(), pAppDomain); - res->ClassTypeData.vmDomainFile.SetRawPtr((pModule ? pModule->GetDomainFile() : NULL)); - _ASSERTE(!res->ClassTypeData.vmDomainFile.IsNull()); + res->ClassTypeData.vmDomainAssembly.SetRawPtr((pModule ? pModule->GetDomainAssembly() : NULL)); + _ASSERTE(!res->ClassTypeData.vmDomainAssembly.IsNull()); break; } @@ -11968,7 +11968,7 @@ HRESULT Debugger::BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData *data, Ty } else { - DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->vmDomainFile); + DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->vmDomainAssembly); th = g_pEEInterface->FindLoadedClass(pDebuggerModule->GetRuntimeModule(), data->metadataToken); if (th.IsNull()) @@ -12070,7 +12070,7 @@ TypeHandle Debugger::TypeDataWalk::ReadTypeHandle() case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_VALUETYPE: { - DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->data.ClassTypeData.vmDomainFile); + DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->data.ClassTypeData.vmDomainAssembly); th = ReadInstantiation(pDebuggerModule->GetRuntimeModule(), data->data.ClassTypeData.metadataToken, data->numTypeArgs); break; } @@ -14403,7 +14403,7 @@ void Debugger::SendLogSwitchSetting(int iLevel, // pDomain - domain file for the domain in which the notification occurred // classToken - metadata token for the type of the notification object void Debugger::SendCustomDebuggerNotification(Thread * pThread, - DomainFile * pDomain, + DomainAssembly * pDomain, mdTypeDef classToken) { CONTRACTL @@ -14434,10 +14434,10 @@ void Debugger::SendCustomDebuggerNotification(Thread * pThread, curThread, curThread->GetDomain()); - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::MakePtr(pDomain); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::MakePtr(pDomain); ipce->CustomNotification.classToken = classToken; - ipce->CustomNotification.vmDomainFile = vmDomainFile; + ipce->CustomNotification.vmDomainAssembly = vmDomainAssembly; m_pRCThread->SendIPCEvent(); @@ -14725,16 +14725,6 @@ HRESULT Debugger::IterateAppDomainsForPdbs() if (!pDomainAssembly->IsVisibleToDebugger()) continue; - DomainAssembly::ModuleIterator j = pDomainAssembly->IterateModules(kModIterIncludeLoading); - while (j.Next()) - { - DomainFile * pDomainFile = j.GetDomainFile(); - if (!pDomainFile->ShouldNotifyDebugger()) - continue; - - Module* pRuntimeModule = pDomainFile->GetModule(); - CopyModulePdb(pRuntimeModule); - } if (pDomainAssembly->ShouldNotifyDebugger()) { CopyModulePdb(pDomainAssembly->GetModule()); diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 084f1da6a5c93..9703354ec4235 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -472,7 +472,7 @@ typedef DPTR(class DebuggerModule) PTR_DebuggerModule; class DebuggerModule { public: - DebuggerModule(Module * pRuntimeModule, DomainFile * pDomainFile, AppDomain * pAppDomain); + DebuggerModule(Module * pRuntimeModule, DomainAssembly * pDomainAssembly, AppDomain * pAppDomain); // Do we have any optimized code in the module? // JMC-probes aren't emitted in optimized code, @@ -504,16 +504,16 @@ class DebuggerModule // If the Runtime module is shared, then this gives a common DM. // If the runtime module is not shared, then this is an identity function. // - // The runtime has the notion of "DomainFile", which is 1:1 with DebuggerModule + // The runtime has the notion of "DomainAssembly", which is 1:1 with DebuggerModule // and thus 1:1 with CordbModule. The CordbModule hash table on the RS now uses - // the DomainFile as the key instead of DebuggerModule. This is a temporary + // the DomainAssembly as the key instead of DebuggerModule. This is a temporary // workaround to facilitate the removal of DebuggerModule. // DebuggerModule * GetPrimaryModule(); - DomainFile * GetDomainFile() + DomainAssembly * GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return m_pRuntimeDomainFile; + return m_pRuntimeDomainAssembly; } // Called by DebuggerModuleTable to set our primary module @@ -528,7 +528,7 @@ class DebuggerModule DebuggerModule* m_pPrimaryModule; PTR_Module m_pRuntimeModule; - PTR_DomainFile m_pRuntimeDomainFile; + PTR_DomainAssembly m_pRuntimeDomainAssembly; AppDomain* m_pAppDomain; @@ -1893,9 +1893,9 @@ class Debugger : public DebugInterface DWORD dwModuleName, Assembly *pAssembly, AppDomain *pAppDomain, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching); - DebuggerModule * AddDebuggerModule(DomainFile * pDomainFile); + DebuggerModule * AddDebuggerModule(DomainAssembly * pDomainAssembly); void UnloadModule(Module* pRuntimeModule, @@ -2068,8 +2068,8 @@ class Debugger : public DebugInterface bool HandleIPCEvent(DebuggerIPCEvent* event); - DebuggerModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFile); - DebuggerModule * LookupOrCreateModule(DomainFile * pDomainFile); + DebuggerModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly); + DebuggerModule * LookupOrCreateModule(DomainAssembly * pDomainAssembly); DebuggerModule * LookupOrCreateModule(Module * pModule, AppDomain * pAppDomain); HRESULT GetAndSendInterceptCommand(DebuggerIPCEvent *event); @@ -2437,7 +2437,7 @@ class Debugger : public DebugInterface } // send a custom debugger notification to the RS - void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomain, mdTypeDef classToken); + void SendCustomDebuggerNotification(Thread * pThread, DomainAssembly * pDomain, mdTypeDef classToken); // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side. void SendMDANotification( diff --git a/src/coreclr/debug/ee/debugger.inl b/src/coreclr/debug/ee/debugger.inl index 0eba7edccf87d..be4e3f67c4daf 100644 --- a/src/coreclr/debug/ee/debugger.inl +++ b/src/coreclr/debug/ee/debugger.inl @@ -52,16 +52,16 @@ inline DebuggerModuleTable * Debugger::GetModuleTable() // @dbgtodo inspection - get rid of this entire class as we move things out-of-proc. //----------------------------------------------------------------------------- inline DebuggerModule::DebuggerModule(Module * pRuntimeModule, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, AppDomain * pAppDomain) : m_enableClassLoadCallbacks(FALSE), m_pPrimaryModule(NULL), m_pRuntimeModule(pRuntimeModule), - m_pRuntimeDomainFile(pDomainFile), + m_pRuntimeDomainAssembly(pDomainAssembly), m_pAppDomain(pAppDomain) { LOG((LF_CORDB,LL_INFO10000, "DM::DM this:0x%x Module:0x%x DF:0x%x AD:0x%x\n", - this, pRuntimeModule, pDomainFile, pAppDomain)); + this, pRuntimeModule, pDomainAssembly, pAppDomain)); // Pick a primary module. // Arguably, this could be in DebuggerModuleTable::AddModule diff --git a/src/coreclr/debug/ee/debuggermodule.cpp b/src/coreclr/debug/ee/debuggermodule.cpp index fb6fa53652fbe..633567f0dd85f 100644 --- a/src/coreclr/debug/ee/debuggermodule.cpp +++ b/src/coreclr/debug/ee/debuggermodule.cpp @@ -253,7 +253,7 @@ void DebuggerModuleTable::RemoveModule(Module* pModule, AppDomain *pAppDomain) if ((pRuntimeModule == pModule) && (pDM->GetAppDomain() == pAppDomain)) { LOG((LF_CORDB, LL_INFO1000, "DMT::RM Removing DebuggerMod:0x%x - Module:0x%x DF:0x%x AD:0x%x\n", - pDM, pModule, pDM->GetDomainFile(), pAppDomain)); + pDM, pModule, pDM->GetDomainAssembly(), pAppDomain)); TRACE_FREE(pDM); DeleteInteropSafe(pDM); Delete(HASH(pRuntimeModule), (HASHENTRY *) pDME); diff --git a/src/coreclr/debug/ee/rcthread.cpp b/src/coreclr/debug/ee/rcthread.cpp index 0f48eb2c95e18..961b06c879f95 100644 --- a/src/coreclr/debug/ee/rcthread.cpp +++ b/src/coreclr/debug/ee/rcthread.cpp @@ -513,19 +513,6 @@ HRESULT DebuggerRCThread::SetupRuntimeOffsets(DebuggerIPCControlBlock * pDebugge pDebuggerRuntimeOffsets->m_excepNotForRuntimeBPAddr = (void*) ExceptionNotForRuntimeFlare; pDebuggerRuntimeOffsets->m_notifyRSOfSyncCompleteBPAddr = (void*) NotifyRightSideOfSyncCompleteFlare; pDebuggerRuntimeOffsets->m_debuggerWordTLSIndex = g_debuggerWordTLSIndex; - -#if !defined(FEATURE_CORESYSTEM) - // Grab the address of RaiseException in kernel32 because we have to play some games with exceptions - // that are generated there (just another reason why mixed mode debugging is shady). See bug 476768. - HMODULE hModule = WszGetModuleHandle(W("kernel32.dll")); - _ASSERTE(hModule != NULL); - PREFAST_ASSUME(hModule != NULL); - pDebuggerRuntimeOffsets->m_raiseExceptionAddr = GetProcAddress(hModule, "RaiseException"); - _ASSERTE(pDebuggerRuntimeOffsets->m_raiseExceptionAddr != NULL); - hModule = NULL; -#else - pDebuggerRuntimeOffsets->m_raiseExceptionAddr = NULL; -#endif #endif // FEATURE_INTEROP_DEBUGGING pDebuggerRuntimeOffsets->m_pPatches = DebuggerController::GetPatchTable(); @@ -575,14 +562,14 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; -#if defined(_DEBUG) || !defined(FEATURE_CORESYSTEM) +#if defined(_DEBUG) DebuggerIPCEvent *event = ((DebugFilterParam *)pv)->event; DWORD pid = GetCurrentProcessId(); DWORD tid = GetCurrentThreadId(); DebuggerIPCEventType type = (DebuggerIPCEventType) (event->type & DB_IPCE_TYPE_MASK); -#endif // _DEBUG || !FEATURE_CORESYSTEM +#endif // _DEBUG // We should never AV here. In a debug build, throw up an assert w/ lots of useful (private) info. #ifdef _DEBUG @@ -613,18 +600,6 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) } #endif -// this message box doesn't work well on coresystem... we actually get in a recursive exception handling loop -#ifndef FEATURE_CORESYSTEM - // We took an AV on the helper thread. This is a catastrophic situation so we can - // simply call the EE's catastrophic message box to display the error. - EEMessageBoxCatastrophic( - IDS_DEBUG_UNHANDLEDEXCEPTION_IPC, IDS_DEBUG_SERVICE_CAPTION, - type, - ep->ExceptionRecord->ExceptionCode, - GetIP(ep->ContextRecord), - pid, pid, tid, tid); -#endif - // For debugging, we can change the behavior by manually setting eax. // EXCEPTION_EXECUTE_HANDLER=1, EXCEPTION_CONTINUE_SEARCH=0, EXCEPTION_CONTINUE_EXECUTION=-1 return EXCEPTION_CONTINUE_SEARCH; diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 0bda865bd0f59..82d5c4d1e465a 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -588,27 +588,27 @@ class IDacDbiInterface // pData - required out parameter which will be filled out with module properties // // Notes: - // See definition of DomainFileInfo for more details about what properties + // See definition of DomainAssemblyInfo for more details about what properties // this gives back. virtual void GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData) = 0; // - // Get properties for a DomainFile + // Get properties for a DomainAssembly // // Arguments: - // vmDomainFile - vm handle to a DomainFile + // vmDomainAssembly - vm handle to a DomainAssembly // pData - required out parameter which will be filled out with module properties // // Notes: - // See definition of DomainFileInfo for more details about what properties + // See definition of DomainAssemblyInfo for more details about what properties // this gives back. virtual - void GetDomainFileData(VMPTR_DomainFile vmDomainFile, OUT DomainFileInfo * pData) = 0; + void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData) = 0; virtual - void GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule) = 0; + void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) = 0; //......................................................................... // These methods were the methods that DBI was calling from IXClrData in V2. @@ -672,7 +672,7 @@ class IDacDbiInterface // Get the values of the JIT Optimization and EnC flags. // // Arguments: - // vmDomainFile - (input) VM DomainFile (module) for which we are retrieving flags + // vmDomainAssembly - (input) VM DomainAssembly (module) for which we are retrieving flags // pfAllowJITOpts - (mandatory output) true iff this is not compiled for debug, // i.e., without optimization // pfEnableEnc - (mandatory output) true iff this module has EnC enabled @@ -687,7 +687,7 @@ class IDacDbiInterface virtual void GetCompilerFlags( - VMPTR_DomainFile vmDomainFile, + VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pfAllowJITOpts, OUT BOOL * pfEnableEnC) = 0; @@ -695,7 +695,7 @@ class IDacDbiInterface // Set the values of the JIT optimization and EnC flags. // // Arguments: - // vmDomainFile - (input) VM DomainFile (module) for which we are retrieving flags + // vmDomainAssembly - (input) VM DomainAssembly (module) for which we are retrieving flags // pfAllowJITOpts - (input) true iff this should not be compiled for debug, // i.e., without optimization // pfEnableEnc - (input) true iff this module should have EnC enabled. If this is @@ -717,7 +717,7 @@ class IDacDbiInterface //......................................................................... virtual - HRESULT SetCompilerFlags(VMPTR_DomainFile vmDomainFile, + HRESULT SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC) = 0; @@ -784,7 +784,7 @@ class IDacDbiInterface // Arguments: // vmModule - new module from the enumeration // pUserData - user data passed to EnumerateModulesInAssembly - typedef void (*FP_MODULE_ENUMERATION_CALLBACK)(VMPTR_DomainFile vmModule, CALLBACK_DATA pUserData); + typedef void (*FP_MODULE_ENUMERATION_CALLBACK)(VMPTR_DomainAssembly vmModule, CALLBACK_DATA pUserData); // // Enumerates all the code Modules in an assembly. @@ -1277,7 +1277,7 @@ class IDacDbiInterface // The debugger can't duplicate this policy with 100% accuracy, and // so we need DAC to lookup the assembly that was actually loaded. virtual - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainFile vmScope, mdToken tkAssemblyRef) = 0; + VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef) = 0; //----------------------------------------------------------------------------- // Interface for initializing the native/IL sequence points and native var info @@ -1707,13 +1707,13 @@ class IDacDbiInterface // // Arguments: // Input: - // vmDomainFile - module containing metadata for the method + // vmDomainAssembly - module containing metadata for the method // functionToken - metadata token for the function // Output (required): // codeInfo - start address and size of the IL // pLocalSigToken - signature token for the method virtual - void GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, + void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT TargetBuffer * pCodeInfo, OUT mdToken * pLocalSigToken) = 0; @@ -1723,7 +1723,7 @@ class IDacDbiInterface // and hot and cold region information. // Arguments: // Input: - // vmDomainFile - module containing metadata for the method + // vmDomainAssembly - module containing metadata for the method // functionToken - token for the function for which we need code info // Output (required): // pCodeInfo - data structure describing the native code regions. @@ -1733,7 +1733,7 @@ class IDacDbiInterface // invalid (i.e., pCodeInfo->IsValid is false). virtual - void GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, + void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT NativeCodeFunctionData * pCodeInfo) = 0; @@ -1798,7 +1798,7 @@ class IDacDbiInterface // get field information and object size for an instantiated generic // // Arguments: - // input: vmDomainFile - module containing metadata for the type + // input: vmDomainAssembly - module containing metadata for the type // thExact - exact type handle for type (may be NULL) // thApprox - approximate type handle for the type // output: @@ -1807,7 +1807,7 @@ class IDacDbiInterface // pObjectSize - size of the instantiated object // virtual - void GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, + void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, OUT DacDbiArrayList * pFieldList, @@ -1992,12 +1992,12 @@ class IDacDbiInterface // input: vmAppDomain - Appdomain in which simpleType resides // simpleType - CorElementType value corresponding to a simple type // output: pMetadataToken - the metadata token corresponding to simpleType, - // in the scope of vmDomainFile. - // vmDomainFile - the domainFile for simpleType + // in the scope of vmDomainAssembly. + // vmDomainAssembly - the domainAssembly for simpleType // Notes: // This is inspection-only. If the type is not yet loaded, it will throw CORDBG_E_CLASS_NOT_LOADED. // It will not try to load a type. - // If the type has been loaded, vmDomainFile will be non-null unless the target is somehow corrupted. + // If the type has been loaded, vmDomainAssembly will be non-null unless the target is somehow corrupted. // In that case, we will throw CORDBG_E_TARGET_INCONSISTENT. virtual @@ -2005,7 +2005,7 @@ class IDacDbiInterface CorElementType simpleType, OUT mdTypeDef * pMetadataToken, OUT VMPTR_Module * pVmModule, - OUT VMPTR_DomainFile * pVmDomainFile) = 0; + OUT VMPTR_DomainAssembly * pVmDomainAssembly) = 0; // for the specified object returns TRUE if the object derives from System.Exception virtual @@ -2459,7 +2459,7 @@ class IDacDbiInterface virtual bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module * pModule, - OUT VMPTR_DomainFile * pDomainFile) = 0; + OUT VMPTR_DomainAssembly * pDomainAssembly) = 0; // Reference Walking. @@ -2731,7 +2731,7 @@ class IDacDbiInterface HRESULT GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef) = 0; virtual diff --git a/src/coreclr/debug/inc/dacdbistructures.h b/src/coreclr/debug/inc/dacdbistructures.h index 5e02a68a792c9..aca5c668de42b 100644 --- a/src/coreclr/debug/inc/dacdbistructures.h +++ b/src/coreclr/debug/inc/dacdbistructures.h @@ -162,15 +162,15 @@ struct MSLAYOUT TargetBuffer //=================================================================================== // Module properties, retrieved by DAC. -// Describes a VMPTR_DomainFile representing a module. +// Describes a VMPTR_DomainAssembly representing a module. // In the VM, a raw Module may be domain neutral and shared by many appdomains. -// Whereas a DomainFile is like a { AppDomain, Module} pair. DomainFile corresponds +// Whereas a DomainAssembly is like a { AppDomain, Module} pair. DomainAssembly corresponds // much more to ICorDebugModule (which also has appdomain affinity). //=================================================================================== -struct MSLAYOUT DomainFileInfo +struct MSLAYOUT DomainAssemblyInfo { - // The appdomain that the DomainFile is associated with. - // Although VMPTR_Module may be shared across multiple domains, a DomainFile has appdomain affinity. + // The appdomain that the DomainAssembly is associated with. + // Although VMPTR_Module may be shared across multiple domains, a DomainAssembly has appdomain affinity. VMPTR_AppDomain vmAppDomain; // The assembly this module belongs to. All modules live in an assembly. @@ -624,7 +624,7 @@ class MSLAYOUT EnCHangingFieldInfo mdFieldDef fieldToken, CorElementType elementType, mdTypeDef metadataToken, - VMPTR_DomainFile vmDomainFile); + VMPTR_DomainAssembly vmDomainAssembly); DebuggerIPCE_BasicTypeData GetObjectTypeData() const { return m_objectTypeData; }; mdFieldDef GetFieldToken() const { return m_fldToken; }; @@ -660,7 +660,7 @@ enum AreValueTypesBoxed { NoValueTypeBoxing, OnlyPrimitivesUnboxed, AllBoxed }; typedef struct MSLAYOUT { // domain file for the type - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; // metadata token for the type. This may be a typeRef (for requests) or a typeDef (for responses). mdToken typeToken; } TypeRefData; @@ -746,7 +746,7 @@ struct MSLAYOUT DacGcReference struct MSLAYOUT DacExceptionCallStackData { VMPTR_AppDomain vmAppDomain; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; CORDB_ADDRESS ip; mdMethodDef methodDef; BOOL isLastForeignExceptionFrame; diff --git a/src/coreclr/debug/inc/dacdbistructures.inl b/src/coreclr/debug/inc/dacdbistructures.inl index f9c0404b659c4..84dd234319863 100644 --- a/src/coreclr/debug/inc/dacdbistructures.inl +++ b/src/coreclr/debug/inc/dacdbistructures.inl @@ -712,14 +712,14 @@ void EnCHangingFieldInfo::Init(VMPTR_Object pObject, mdFieldDef fieldToken, CorElementType elementType, mdTypeDef metadataToken, - VMPTR_DomainFile vmDomainFile) + VMPTR_DomainAssembly vmDomainAssembly) { m_vmObject = pObject; m_offsetToVars = offset; m_fldToken = fieldToken; m_objectTypeData.elementType = elementType; m_objectTypeData.metadataToken = metadataToken; - m_objectTypeData.vmDomainFile = vmDomainFile; + m_objectTypeData.vmDomainAssembly = vmDomainAssembly; } diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index ddef09554cf80..e433532c29a16 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -126,7 +126,6 @@ struct MSLAYOUT DebuggerIPCRuntimeOffsets void *m_signalHijackCompleteBPAddr; void *m_excepNotForRuntimeBPAddr; void *m_notifyRSOfSyncCompleteBPAddr; - void *m_raiseExceptionAddr; // The address of kernel32!RaiseException in the debuggee DWORD m_debuggerWordTLSIndex; // The TLS slot for the debugger word used in the debugger hijack functions #endif // FEATURE_INTEROP_DEBUGGING SIZE_T m_TLSIndex; // The TLS index of the thread-local storage for coreclr.dll @@ -364,30 +363,6 @@ struct MSLAYOUT DebuggerIPCControlBlockTransport #include "dbgtransportsession.h" #endif // defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI) -#if defined(TARGET_X86) && !defined(FEATURE_CORESYSTEM) -// We have an versioning requirement. -// Certain portions of the v1.0 and v1.1 IPC block are shared. This is b/c a v1.1 debugger needs to be able -// to look at a v2.0 app enough to recognize the version mismatch. -// This check is only necessary for platforms that ran on v1.1 (Win32-x86) - -// Just to catch any potential illegal change in the IPC block, we assert the offsets against the offsets from v1.1. -// The constants here are pulled from v1.1. -// The RS will look at these versioning fields, so they absolutely must line up. -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolCurrent) == 0x10); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolMinSupported) == 0x14); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolCurrent) == 0x18); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolMinSupported) == 0x1c); - -// Unfortunately, on detecting such failure, v1.1 will also null out LSEA, LSER and RSPH. -// If these get adjusted, a version-mismatch attach will effectively null out random fields. -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSEA) == 0x30); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSER) == 0x34); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProcessHandle) == 0x38); - - - -#endif - #define INITIAL_APP_DOMAIN_INFO_LIST_SIZE 16 @@ -847,15 +822,13 @@ typedef VMPTR_Base VMPTR_CONTEXT; typedef VMPTR_Base VMPTR_CONTEXT; #endif -// DomainFile is a base-class for a CLR module, with app-domain affinity. -// For domain-neutral modules (like CoreLib), there is a DomainFile instance +// DomainAssembly is a base-class for a CLR module, with app-domain affinity. +// For domain-neutral modules (like CoreLib), there is a DomainAssembly instance // for each appdomain the module lives in. // This is the canonical handle ICorDebug uses to a CLR module. -DEFINE_VMPTR(class DomainFile, PTR_DomainFile, VMPTR_DomainFile); +DEFINE_VMPTR(class DomainAssembly, PTR_DomainAssembly, VMPTR_DomainAssembly); DEFINE_VMPTR(class Module, PTR_Module, VMPTR_Module); -// DomainAssembly derives from DomainFile and represents a manifest module. -DEFINE_VMPTR(class DomainAssembly, PTR_DomainAssembly, VMPTR_DomainAssembly); DEFINE_VMPTR(class Assembly, PTR_Assembly, VMPTR_Assembly); DEFINE_VMPTR(class PEAssembly, PTR_PEAssembly, VMPTR_PEAssembly); @@ -1285,7 +1258,7 @@ inline bool IsEqualOrCloserToRoot(FramePointer fp1, FramePointer fp2) struct MSLAYOUT DebuggerIPCE_FuncData { mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdTypeDef classMetadataToken; @@ -1425,7 +1398,7 @@ struct MSLAYOUT DebuggerIPCE_STRData struct MSLAYOUT { mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_MethodDesc vmMethodDesc; CorDebugInternalFrameType frameType; } stubFrame; @@ -1469,7 +1442,7 @@ struct MSLAYOUT DebuggerIPCE_BasicTypeData CorElementType elementType; mdTypeDef metadataToken; VMPTR_Module vmModule; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_TypeHandle vmTypeHandle; }; @@ -1505,7 +1478,7 @@ struct MSLAYOUT DebuggerIPCE_ExpandedTypeData { mdTypeDef metadataToken; VMPTR_Module vmModule; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_TypeHandle typeHandle; // if non-null then further fetches will be needed to get type arguments } ClassTypeData; @@ -1679,7 +1652,7 @@ struct MSLAYOUT DebuggerIPCE_FuncEvalInfo DebuggerIPCE_FuncEvalType funcEvalType; mdMethodDef funcMetadataToken; mdTypeDef funcClassMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; RSPTR_CORDBEVAL funcEvalKey; bool evalDuringException; @@ -1917,7 +1890,7 @@ struct MSLAYOUT DebuggerIPCEvent { // Module whos metadata is being updated // This tells the RS that the metadata for that module has become invalid. - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; } MetadataUpdateData; @@ -1960,13 +1933,13 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { // Module that was just loaded. - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; }LoadModuleData; struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY debuggerAssemblyToken; } UnloadModuleData; @@ -1975,7 +1948,7 @@ struct MSLAYOUT DebuggerIPCEvent // Queury PDB from OOP struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; } UpdateModuleSymsData; DebuggerMDANotification MDANotification; @@ -1984,7 +1957,7 @@ struct MSLAYOUT DebuggerIPCEvent { LSPTR_BREAKPOINT breakpointToken; mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; bool isIL; SIZE_T offset; SIZE_T encVersion; @@ -2064,7 +2037,7 @@ struct MSLAYOUT DebuggerIPCEvent // Apply an EnC edit struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; // Module to edit + VMPTR_DomainAssembly vmDomainAssembly; // Module to edit DWORD cbDeltaMetadata; // size of blob pointed to by pDeltaMetadata CORDB_ADDRESS pDeltaMetadata; // pointer to delta metadata in debuggee // it's the RS's responsibility to allocate and free @@ -2081,20 +2054,20 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY classDebuggerAssemblyToken; } LoadClass; struct MSLAYOUT { mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY classDebuggerAssemblyToken; } UnloadClass; struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; bool flag; } SetClassLoad; @@ -2125,7 +2098,7 @@ struct MSLAYOUT DebuggerIPCEvent CORDB_ADDRESS startAddress; bool fCanSetIPOnly; VMPTR_Thread vmThreadToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef mdMethod; VMPTR_MethodDesc vmMethodDesc; SIZE_T offset; @@ -2154,7 +2127,7 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { // Domain file for the domain in which the notification occurred - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; // metadata token for the type of the CustomNotification object's type mdTypeDef classToken; @@ -2219,7 +2192,7 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; BOOL fAllowJitOpts; BOOL fEnableEnC; } JitDebugInfo; @@ -2227,7 +2200,7 @@ struct MSLAYOUT DebuggerIPCEvent // EnC Remap opportunity struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken ; // methodDef of function with remap opportunity SIZE_T currentVersionNumber; // version currently executing SIZE_T resumeVersionNumber; // latest version @@ -2239,7 +2212,7 @@ struct MSLAYOUT DebuggerIPCEvent // EnC Remap has taken place struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken; // methodDef of function that was remapped } EnCRemapComplete; @@ -2247,7 +2220,7 @@ struct MSLAYOUT DebuggerIPCEvent // specific edit made by EnC (function add/update or field add). struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdToken memberMetadataToken; // Either a methodDef token indicating the function that // was updated/added, or a fieldDef token indicating the // field which was added. @@ -2268,7 +2241,7 @@ struct MSLAYOUT DebuggerIPCEvent // @todo - Perhaps we can bundle these up so we can set multiple funcs w/ 1 event? struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken; DWORD dwStatus; } SetJMCFunctionStatus; diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp index 6d3ed5b345cf7..3ff580717e72a 100644 --- a/src/coreclr/debug/shared/dbgtransportsession.cpp +++ b/src/coreclr/debug/shared/dbgtransportsession.cpp @@ -2696,11 +2696,6 @@ bool DbgTransportSession::DbgTransportShouldInjectFault(DbgTransportFaultOp eOp, if (dwChance < (s_dwFaultInjection & DBG_TRANSPORT_FAULT_RATE_MASK)) { DbgTransportLog(LC_FaultInject, "Injected fault for %s operation", szOpName); -#if defined(FEATURE_CORESYSTEM) - // not supported -#else - WSASetLastError(WSAEFAULT); -#endif // defined(FEATURE_CORESYSTEM) return true; } } diff --git a/src/coreclr/dlls/dbgshim/dbgshim.cpp b/src/coreclr/dlls/dbgshim/dbgshim.cpp index 40e4d7dea4bf2..c82625487cfe8 100644 --- a/src/coreclr/dlls/dbgshim/dbgshim.cpp +++ b/src/coreclr/dlls/dbgshim/dbgshim.cpp @@ -1956,9 +1956,7 @@ GetContinueStartupEvent( #endif // !TARGET_UNIX -#if defined(FEATURE_CORESYSTEM) #include "debugshim.h" -#endif //----------------------------------------------------------------------------- // Public API. @@ -1980,26 +1978,17 @@ CLRCreateInstance( { PUBLIC_CONTRACT; -#if defined(FEATURE_CORESYSTEM) - if (ppInterface == NULL) return E_POINTER; if (clsid != CLSID_CLRDebugging || riid != IID_ICLRDebugging) return E_NOINTERFACE; -#if defined(FEATURE_CORESYSTEM) GUID skuId = CLR_ID_ONECORE_CLR; -#else - GUID skuId = CLR_ID_CORECLR; -#endif CLRDebuggingImpl *pDebuggingImpl = new (nothrow) CLRDebuggingImpl(skuId); if (NULL == pDebuggingImpl) return E_OUTOFMEMORY; return pDebuggingImpl->QueryInterface(riid, ppInterface); -#else - return E_NOTIMPL; -#endif } diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index 2a529b2f4a779..334d1b90c9308 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -65,7 +65,6 @@ nativeStringResourceTable_mscorrc #PAL_wcsrchr #PAL_wcscmp #PAL_wcschr -#PAL_wcscspn #PAL_wcscat #PAL_wcsstr #PAL__open @@ -140,8 +139,6 @@ nativeStringResourceTable_mscorrc #LoadLibraryA #LoadLibraryW #LoadLibraryExW -#LocalAlloc -#LocalFree #MapViewOfFile #MapViewOfFileEx #MoveFileExW diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 0e78c99f38d5d..d2c7bff988cc8 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -194,6 +194,10 @@ BEGIN IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL "Unable to find an entry point named '%1' in DLL." IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO "Unable to find an entry point named '%1' in shared library." IDS_EE_NDIRECT_GETPROCADDRESS_NONAME "A library name must be specified in a DllImport attribute applied to non-IJW methods." + IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR "Setting SetLastError to 'true' is not supported when runtime marshalling is disabled." + IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID "The LCIDConversionAttribute is not supported when runtime marshalling is disabled." + IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG "Setting PreserveSig to false for a P/Invoke is not supported when runtime marshalling is disabled." + IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS "Using a variable argument list in a P/Invoke is not supported when runtime marshalling is disabled." IDS_EE_CLASS_CONSTRAINTS_VIOLATION "GenericArguments[%1], '%2', on '%3' violates the constraint of type parameter '%4'." IDS_EE_METHOD_CONSTRAINTS_VIOLATION "Method %1.%2: type argument '%3' violates the constraint of type parameter '%4'." IDS_EE_NOSYNCHRONIZED "Synchronized attribute cannot be used with this method type." @@ -297,6 +301,7 @@ BEGIN IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled." IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled." IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute." + IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled." IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)." IDS_EE_BADMARSHALPARAM_NO_LPTSTR "Invalid managed/unmanaged type combination (Strings cannot be paired with LPTStr for parameters and return types of methods in interfaces exposed to COM)." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 05b31799ec5c4..7a8f148456a83 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -588,3 +588,8 @@ #define IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE 0x2649 #define IDS_EE_THREAD_APARTMENT_NOT_SUPPORTED 0x264A #define IDS_EE_NO_IINSPECTABLE 0x264B +#define IDS_EE_BADMARSHAL_MARSHAL_DISABLED 0x264C +#define IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR 0x264D +#define IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID 0x264E +#define IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG 0x264F +#define IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS 0x2650 diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 5a2a9c2c2c20e..c15f926fa756b 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2444,8 +2444,6 @@ heap_segment* gc_heap::reserved_free_regions_sip[max_generation]; int gc_heap::num_sip_regions = 0; -size_t gc_heap::committed_in_free = 0; - size_t gc_heap::end_gen0_region_space = 0; size_t gc_heap::gen0_pinned_free_space = 0; @@ -9404,7 +9402,7 @@ void gc_heap::remove_ro_segment (heap_segment* seg) enter_spin_lock (&gc_heap::gc_lock); - seg_table->remove ((uint8_t*)seg); + seg_table->remove (heap_segment_mem (seg)); seg_mapping_table_remove_ro_segment (seg); // Locate segment (and previous segment) in the list. @@ -10892,7 +10890,7 @@ void gc_heap::seg_clear_mark_array_bits_soh (heap_segment* seg) } } -void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end) +void gc_heap::bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end) { if ((start < background_saved_highest_address) && (end > background_saved_lowest_address)) @@ -10916,8 +10914,15 @@ void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end) if (startwrd == endwrd) { - unsigned int wrd = firstwrd | lastwrd; - mark_array[startwrd] &= wrd; + if (startbit != endbit) + { + unsigned int wrd = firstwrd | lastwrd; + mark_array[startwrd] &= wrd; + } + else + { + assert (start == end); + } return; } @@ -10940,18 +10945,6 @@ void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end) } } } - -void gc_heap::bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end) -{ - if ((start < background_saved_highest_address) && - (end > background_saved_lowest_address)) - { - start = max (start, background_saved_lowest_address); - end = min (end, background_saved_highest_address); - - clear_batch_mark_array_bits (start, end); - } -} #endif //BACKGROUND_GC inline @@ -11144,9 +11137,6 @@ heap_segment* gc_heap::get_free_region (int gen_number, size_t size) { heap_segment* region = 0; - // TODO: the update to committed_in_free is incorrect - we'd need synchorization 'cause a thread - // could be getting a small and another one could be getting a large region at the same time. - // This is only used for recording. if (gen_number <= max_generation) { assert (size == 0); @@ -11548,6 +11538,8 @@ void gc_heap::decommit_heap_segment_pages (heap_segment* seg, if (use_large_pages_p) return; uint8_t* page_start = align_on_page (heap_segment_allocated(seg)); + assert (heap_segment_committed (seg) >= page_start); + size_t size = heap_segment_committed (seg) - page_start; extra_space = align_on_page (extra_space); if (size >= max ((extra_space + 2*OS_PAGE_SIZE), MIN_DECOMMIT_SIZE)) @@ -11568,10 +11560,10 @@ size_t gc_heap::decommit_heap_segment_pages_worker (heap_segment* seg, #endif assert (!use_large_pages_p); uint8_t* page_start = align_on_page (new_committed); - size_t size = heap_segment_committed (seg) - page_start; + ptrdiff_t size = heap_segment_committed (seg) - page_start; if (size > 0) { - bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); + bool decommit_succeeded_p = virtual_decommit (page_start, (size_t)size, heap_segment_oh (seg), heap_number); if (decommit_succeeded_p) { dprintf (3, ("Decommitting heap segment [%Ix, %Ix[(%d)", @@ -11606,10 +11598,11 @@ void gc_heap::decommit_heap_segment (heap_segment* seg) dprintf (3, ("Decommitting heap segment %Ix(%Ix)", (size_t)seg, heap_segment_mem (seg))); -#ifdef BACKGROUND_GC +#if defined(BACKGROUND_GC) && !defined(USE_REGIONS) page_start += OS_PAGE_SIZE; -#endif //BACKGROUND_GC +#endif //BACKGROUND_GC && !USE_REGIONS + assert (heap_segment_committed (seg) >= page_start); size_t size = heap_segment_committed (seg) - page_start; bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); @@ -13568,7 +13561,6 @@ gc_heap::init_gc_heap (int h_number) sip_seg_maxgen_interval = 3; num_condemned_regions = 0; #endif //STRESS_REGIONS - committed_in_free = 0; end_gen0_region_space = 0; gen0_pinned_free_space = 0; gen0_large_chunk_found = false; @@ -20428,23 +20420,33 @@ void gc_heap::gc1() if (n < max_generation) { - compute_promoted_allocation (1 + n); + int highest_gen_number = +#ifdef USE_REGIONS + max_generation; +#else //USE_REGIONS + 1 + n; +#endif //USE_REGIONS + + for (int older_gen_idx = (1 + n); older_gen_idx <= highest_gen_number; older_gen_idx++) + { + compute_promoted_allocation (older_gen_idx); - dynamic_data* dd = dynamic_data_of (1 + n); - size_t new_fragmentation = generation_free_list_space (generation_of (1 + n)) + - generation_free_obj_space (generation_of (1 + n)); + dynamic_data* dd = dynamic_data_of (older_gen_idx); + size_t new_fragmentation = generation_free_list_space (generation_of (older_gen_idx)) + + generation_free_obj_space (generation_of (older_gen_idx)); #ifdef BACKGROUND_GC - if (current_c_gc_state != c_gc_state_planning) + if (current_c_gc_state != c_gc_state_planning) #endif //BACKGROUND_GC - { - if (settings.promotion) - { - dd_fragmentation (dd) = new_fragmentation; - } - else { - //assert (dd_fragmentation (dd) == new_fragmentation); + if (settings.promotion) + { + dd_fragmentation (dd) = new_fragmentation; + } + else + { + //assert (dd_fragmentation (dd) == new_fragmentation); + } } } } @@ -24364,8 +24366,17 @@ size_t gc_heap::committed_size() } #ifdef USE_REGIONS + size_t committed_in_free = 0; + + for (int kind = basic_free_region; kind < count_free_region_kinds; kind++) + { + committed_in_free += free_regions[kind].get_size_committed_in_free(); + } + + dprintf (3, ("h%d committed in free %Id", heap_number, committed_in_free)); + total_committed += committed_in_free; -#endif //USE_REGIO +#endif //USE_REGIONS return total_committed; } @@ -27453,7 +27464,7 @@ void gc_heap::plan_phase (int condemned_gen_number) _sort (&mark_list[0], mark_list_index - 1, 0); #endif //USE_VXSORT - dprintf (3, ("using mark list at GC #%d", settings.gc_index)); + dprintf (3, ("using mark list at GC #%Id", (size_t)settings.gc_index)); //verify_qsort_array (&mark_list[0], mark_list_index-1); #endif //!MULTIPLE_HEAPS use_mark_list = TRUE; @@ -29741,7 +29752,7 @@ void gc_heap::thread_final_regions (bool compact_p) } } - verify_regions (true); + verify_regions (true, false); } void gc_heap::thread_start_region (generation* gen, heap_segment* region) @@ -29792,7 +29803,7 @@ heap_segment* gc_heap::get_new_region (int gen_number, size_t size) heap_segment_next (generation_tail_region (gen)) = new_region; generation_tail_region (gen) = new_region; - verify_regions (gen_number, false); + verify_regions (gen_number, false, settings.concurrent); } return new_region; @@ -29861,7 +29872,7 @@ void gc_heap::update_start_tail_regions (generation* gen, (size_t)prev_region, heap_segment_mem (prev_region))); } - verify_regions (false); + verify_regions (false, settings.concurrent); } // There's one complication with deciding whether we can make a region SIP or not - if the plan_gen_num of @@ -30130,12 +30141,19 @@ void gc_heap::sweep_region_in_plan (heap_segment* region, heap_segment_saved_allocated (region) = heap_segment_allocated (region); heap_segment_allocated (region) = last_marked_obj_end; heap_segment_plan_allocated (region) = heap_segment_allocated (region); + + int plan_gen_num = heap_segment_plan_gen_num (region); + generation_allocation_size (generation_of (plan_gen_num)) += heap_segment_survived (region); + dprintf (REGIONS_LOG, ("sip: g%d alloc size is now %Id", plan_gen_num, + generation_allocation_size (generation_of (plan_gen_num)))); } inline void gc_heap::check_demotion_helper_sip (uint8_t** pval, int parent_gen_num, uint8_t* parent_loc) { uint8_t* child_object = *pval; + if (!is_in_heap_range (child_object)) + return; if (!child_object) return; int child_object_plan_gen = get_region_plan_gen_num (child_object); @@ -36653,7 +36671,7 @@ void gc_heap::mark_through_cards_for_segments (card_fn fn, BOOL relocating CARD_ hpt->heap_number, heap_number, n_eph, n_gen, n_card_set, total_cards_cleared, (n_eph ? (int)(((float)n_gen / (float)n_eph) * 100) : 0))); dprintf (3, ("h%d marking h%d Msoh: total cross %Id, useful: %Id, running ratio: %d", - hpt->heap_number, heap_number, n_eph_soh, n_gen_soh, + hpt->heap_number, heap_number, (size_t)n_eph_soh, (size_t)n_gen_soh, (n_eph_soh ? (int)(((float)n_gen_soh / (float)n_eph_soh) * 100) : 0))); #else generation_skip_ratio = ((n_eph > MIN_SOH_CROSS_GEN_REFS) ? (int)(((float)n_gen / (float)n_eph) * 100) : 100); @@ -41401,7 +41419,7 @@ void gc_heap::mark_through_cards_for_uoh_objects (card_fn fn, hpt->heap_number, heap_number, n_eph, n_gen, n_card_set, total_cards_cleared, (n_eph ? (int)(((float)n_gen / (float)n_eph) * 100) : 0))); dprintf (3, ("h%d marking h%d Mloh: total cross %Id, useful: %Id, running ratio: %d", - hpt->heap_number, heap_number, n_eph_loh, n_gen_loh, + hpt->heap_number, heap_number, (size_t)n_eph_loh, (size_t)n_gen_loh, (n_eph_loh ? (int)(((float)n_gen_loh / (float)n_eph_loh) * 100) : 0))); #else generation_skip_ratio = min (((n_eph > MIN_LOH_CROSS_GEN_REFS) ? @@ -42157,7 +42175,7 @@ gc_heap::verify_free_lists () } } -void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num) +void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail) { #ifdef USE_REGIONS // For the given generation, verify that @@ -42220,7 +42238,7 @@ void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num) FATAL_GC_ERROR(); } - if (tail_region != prev_region_in_gen) + if (can_verify_tail && (tail_region != prev_region_in_gen)) { dprintf (REGIONS_LOG, ("h%d gen%d tail region is %Ix(%Ix), diff from last region %Ix(%Ix)!!", heap_number, gen_number, @@ -42231,12 +42249,18 @@ void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num) #endif //USE_REGIONS } -void gc_heap::verify_regions (bool can_verify_gen_num) +inline bool is_user_alloc_gen (int gen_number) +{ + return ((gen_number == soh_gen0) || (gen_number == loh_generation) || (gen_number == poh_generation)); +} + +void gc_heap::verify_regions (bool can_verify_gen_num, bool concurrent_p) { #ifdef USE_REGIONS for (int i = 0; i < total_generation_count; i++) { - verify_regions (i, can_verify_gen_num); + bool can_verify_tail = (concurrent_p ? !is_user_alloc_gen (i) : true); + verify_regions (i, can_verify_gen_num, can_verify_tail); } #endif //USE_REGIONS } @@ -42367,7 +42391,7 @@ void gc_heap::verify_heap (BOOL begin_gc_p) //verify that the generation structures makes sense { #ifdef USE_REGIONS - verify_regions (true); + verify_regions (true, settings.concurrent); #else //USE_REGIONS generation* gen = generation_of (max_generation); @@ -43428,8 +43452,15 @@ void GCHeap::SetYieldProcessorScalingFactor (float scalingFactor) unsigned int GCHeap::WhichGeneration (Object* object) { - gc_heap* hp = gc_heap::heap_of ((uint8_t*)object); - unsigned int g = hp->object_gennum ((uint8_t*)object); + uint8_t* o = (uint8_t*)object; +#ifdef FEATURE_BASICFREEZE + if (!((o < g_gc_highest_address) && (o >= g_gc_lowest_address))) + { + return max_generation; + } +#endif //FEATURE_BASICFREEZE + gc_heap* hp = gc_heap::heap_of (o); + unsigned int g = hp->object_gennum (o); dprintf (3, ("%Ix is in gen %d", (size_t)object, g)); return g; } @@ -44071,12 +44102,8 @@ GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_ } CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(newAlloc, size, flags & GC_ALLOC_FINALIZE); - #ifdef USE_REGIONS - if (!IsHeapPointer (newAlloc)) - { - GCToOSInterface::DebugBreak(); - } + assert (IsHeapPointer (newAlloc)); #endif //USE_REGIONS return newAlloc; diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 886ea17743880..d727a4685c527 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -87,8 +87,8 @@ class GCConfigStringHolder INT_CONFIG (SegmentSize, "GCSegmentSize", NULL, 0, "Specifies the managed heap segment size") \ INT_CONFIG (LatencyMode, "GCLatencyMode", NULL, -1, "Specifies the GC latency mode - batch, interactive or low latency (note that the same " \ "thing can be specified via API which is the supported way") \ - INT_CONFIG (LatencyLevel, "GCLatencyLevel", NULL, 1, "Specifies the GC latency level that you want to optimize for. Must be a number from 0" \ - "3. See documentation for more details on each level.") \ + INT_CONFIG (LatencyLevel, "GCLatencyLevel", NULL, 1, "Specifies the GC latency level that you want to optimize for. Must be a number from 0 " \ + "to 3. See documentation for more details on each level.") \ INT_CONFIG (LogFileSize, "GCLogFileSize", NULL, 0, "Specifies the GC log file size") \ INT_CONFIG (CompactRatio, "GCCompactRatio", NULL, 0, "Specifies the ratio compacting GCs vs sweeping") \ INT_CONFIG (GCHeapAffinitizeMask, "GCHeapAffinitizeMask", "System.GC.HeapAffinitizeMask", 0, "Specifies processor mask for Server GC threads") \ @@ -117,7 +117,7 @@ class GCConfigStringHolder INT_CONFIG (BGCFLkd, "BGCFLkd", NULL, 11, "Specifies kd for above goal tuning") \ INT_CONFIG (BGCFLff, "BGCFLff", NULL, 100, "Specifies ff ratio") \ INT_CONFIG (BGCFLSmoothFactor, "BGCFLSmoothFactor", NULL, 150, "Smoothing over these") \ - INT_CONFIG (BGCFLGradualD, "BGCFLGradualD", NULL, 0, "Enable gradual D instead of cutting of at the value") \ + INT_CONFIG (BGCFLGradualD, "BGCFLGradualD", NULL, 0, "Enable gradual D instead of cutting off at the value") \ INT_CONFIG (BGCMLkp, "BGCMLkp", NULL, 1000, "Specifies kp for ML tuning") \ INT_CONFIG (BGCMLki, "BGCMLki", NULL, 16, "Specifies ki for ML tuning") \ INT_CONFIG (BGCFLEnableKi, "BGCFLEnableKi", NULL, 1, "Enables ki for above goal tuning") \ diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index cfffcf1221a81..c7d72c7145baf 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -111,7 +111,7 @@ enum oom_reason /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ /* If you modify failure_get_memory and */ /* oom_reason be sure to make the corresponding */ -/* changes in toolbox\sos\strike\strike.cpp. */ +/* changes in tools\sos\strike\strike.cpp. */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ enum failure_get_memory { diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 14bf3ef290889..567e7c1bd69ca 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -51,8 +51,8 @@ inline void FATAL_GC_ERROR() // // This means any empty regions can be freely used for any generation. For // Server GC we will balance regions between heaps. -// For now disable regions StandAlone GC builds -#if defined (HOST_64BIT) && !defined (BUILD_AS_STANDALONE) +// For now disable regions outside of StandAlone GC builds +#if defined (HOST_64BIT) && defined (BUILD_AS_STANDALONE) #define USE_REGIONS #endif //HOST_64BIT && BUILD_AS_STANDALONE @@ -1175,6 +1175,7 @@ class region_free_list heap_segment* unlink_region_front(); heap_segment* unlink_smallest_region (size_t size); size_t get_num_free_regions(); + size_t get_size_committed_in_free() { return size_committed_in_free_regions; } size_t get_size_free_regions() { return size_free_regions; } heap_segment* get_first_free_region() { return head_free_region; } static void unlink_region (heap_segment* region); @@ -1286,9 +1287,9 @@ class gc_heap PER_HEAP void verify_free_lists(); PER_HEAP - void verify_regions (int gen_number, bool can_verify_gen_num); + void verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail); PER_HEAP - void verify_regions (bool can_verify_gen_num); + void verify_regions (bool can_verify_gen_num, bool concurrent_p); PER_HEAP_ISOLATED void enter_gc_lock_for_verify_heap(); PER_HEAP_ISOLATED @@ -2156,8 +2157,6 @@ class gc_heap PER_HEAP void seg_clear_mark_array_bits_soh (heap_segment* seg); PER_HEAP - void clear_batch_mark_array_bits (uint8_t* start, uint8_t* end); - PER_HEAP void bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end); #ifdef VERIFY_HEAP PER_HEAP @@ -3596,9 +3595,6 @@ class gc_heap PER_HEAP int num_sip_regions; - PER_HEAP - size_t committed_in_free; - PER_HEAP // After plan we calculate this as the planned end gen0 space; // but if we end up sweeping, we recalculate it at the end of diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 431421afc87e4..2d979c395610e 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -28,6 +28,10 @@ #undef min #undef max +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) (0) +#endif + #if __has_cpp_attribute(fallthrough) #define FALLTHROUGH [[fallthrough]] #else diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 345a18ef6bc62..67a43e28b20d1 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -291,9 +291,9 @@ static int run(const configuration& config) } // Construct CoreCLR properties. - pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(std::move(tpa_list)); - pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(std::move(app_path)); - pal::string_utf8_t native_search_dirs_utf8 = pal::convert_to_utf8(native_search_dirs.str()); + pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(tpa_list.c_str()); + pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(app_path.c_str()); + pal::string_utf8_t native_search_dirs_utf8 = pal::convert_to_utf8(native_search_dirs.str().c_str()); std::vector user_defined_keys_utf8; std::vector user_defined_values_utf8; @@ -334,7 +334,7 @@ static int run(const configuration& config) int propertyCount = (int)propertyKeys.size(); // Construct arguments - pal::string_utf8_t exe_path_utf8 = pal::convert_to_utf8(std::move(exe_path)); + pal::string_utf8_t exe_path_utf8 = pal::convert_to_utf8(exe_path.c_str()); std::vector argv_lifetime; pal::malloc_ptr argv_utf8{ pal::convert_argv_to_utf8(config.entry_assembly_argc, config.entry_assembly_argv, argv_lifetime) }; pal::string_utf8_t entry_assembly_utf8 = pal::convert_to_utf8(config.entry_assembly_fullpath.c_str()); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 9781299c8049e..14cb9ec6580e1 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -88,11 +88,28 @@ namespace pal assert(wrote < needed); return { buffer.get() }; } + inline string_utf8_t getenvA(const char* var) + { + DWORD needed = ::GetEnvironmentVariableA(var, nullptr, 0); + if (needed == 0) + return {}; + + malloc_ptr buffer{ (char*)::malloc(needed * sizeof(char)) }; + assert(buffer != nullptr); + DWORD wrote = ::GetEnvironmentVariableA(var, buffer.get(), needed); + assert(wrote < needed); + return { buffer.get() }; + } inline void setenv(const char_t* var, string_t value) { BOOL success = ::SetEnvironmentVariableW(var, value.c_str()); assert(success); } + inline void setenvA(const char* var, string_utf8_t value) + { + BOOL success = ::SetEnvironmentVariableA(var, value.c_str()); + assert(success); + } inline string_t get_exe_path() { char_t file_name[1024]; @@ -177,31 +194,17 @@ namespace pal inline string_utf8_t convert_to_utf8(const char_t* str) { - // Compute the needed buffer - int bytes_req = ::WideCharToMultiByte( - CP_UTF8, 0, // Conversion args - str, -1, // Input string - nullptr, 0, // Null to request side - nullptr, nullptr); + int bytes_req = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr); malloc_ptr buffer{ (char*)::malloc(bytes_req) }; assert(buffer != nullptr); - int written = ::WideCharToMultiByte( - CP_UTF8, 0, // Conversion args - str, -1, // Input string - buffer.get(), bytes_req, // Output buffer - nullptr, nullptr); + int written = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.get(), bytes_req, nullptr, nullptr); assert(bytes_req == written); return { buffer.get() }; } - inline string_utf8_t convert_to_utf8(string_t&& str) - { - return convert_to_utf8(str.c_str()); - } - inline bool try_load_hostpolicy(pal::string_t mock_hostpolicy_value) { const char_t* hostpolicyName = W("hostpolicy.dll"); @@ -360,11 +363,19 @@ namespace pal return {}; return { val }; } + inline string_utf8_t getenvA(const char* var) + { + return getenv(var); + } inline void setenv(const char_t* var, string_t value) { int error = ::setenv(var, value.c_str(), /* overwrite */ 1); assert(error == 0); } + inline void setenvA(const char* var, string_utf8_t value) + { + setenv(var, value.c_str()); + } inline string_t get_exe_path() { return minipal_getexepath(); } @@ -567,11 +578,6 @@ namespace pal return { str }; } - inline string_utf8_t convert_to_utf8(string_t&& str) - { - return std::move(str); - } - inline bool try_load_hostpolicy(pal::string_t mock_hostpolicy_value) { if (!string_ends_with(mock_hostpolicy_value, pal::nativelib_ext)) diff --git a/src/coreclr/hosts/corerun/dotenv.cpp b/src/coreclr/hosts/corerun/dotenv.cpp index 0e0e37c7919b0..8792d63151f56 100644 --- a/src/coreclr/hosts/corerun/dotenv.cpp +++ b/src/coreclr/hosts/corerun/dotenv.cpp @@ -7,22 +7,8 @@ #include #include -#ifdef TARGET_WINDOWS -#include -#endif - namespace { - pal::string_t convert_to_string_t(std::string str) - { -#ifdef TARGET_WINDOWS - std::wstring_convert> converter; - return converter.from_bytes(str); -#else - return str; -#endif - } - bool read_var_name(std::istream& file, std::string& var_name_out) { std::string var_name; @@ -326,8 +312,7 @@ dotenv::dotenv(pal::string_t dotEnvFilePath, std::istream& contents) { return dot_env_entry->second; } - pal::string_t env_var_name = convert_to_string_t(name); - return pal::convert_to_utf8(pal::getenv(env_var_name.c_str())); + return pal::getenvA(name.c_str()); }, temp_value)) { _environmentVariables = {}; @@ -341,9 +326,9 @@ void dotenv::load_into_current_process() const { for (std::pair env_vars : _environmentVariables) { - pal::string_t name_string = convert_to_string_t(env_vars.first); - pal::string_t value_string = convert_to_string_t(env_vars.second); - pal::setenv(name_string.c_str(), std::move(value_string)); + pal::string_utf8_t name_string = env_vars.first; + pal::string_utf8_t value_string = env_vars.second; + pal::setenvA(name_string.c_str(), std::move(value_string)); } } diff --git a/src/coreclr/inc/bbsweep.h b/src/coreclr/inc/bbsweep.h index eda1e11d2f2e1..64855ed939ddd 100644 --- a/src/coreclr/inc/bbsweep.h +++ b/src/coreclr/inc/bbsweep.h @@ -31,11 +31,9 @@ #pragma push_macro("SetEvent") #pragma push_macro("ResetEvent") #pragma push_macro("ReleaseSemaphore") -#pragma push_macro("LocalFree") #undef SetEvent #undef ResetEvent #undef ReleaseSemaphore -#undef LocalFree // MAX_COUNT is the maximal number of runtime processes that can run at a given time #define MAX_COUNT 20 @@ -184,97 +182,6 @@ class BBSweep if (!bInitialized) { SECURITY_ATTRIBUTES * pSecurityAttributes = NULL; - -#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO - PSECURITY_DESCRIPTOR pSD = NULL; - PSID pAdminSid = NULL; - HANDLE hToken = NULL; - PACL pACL = NULL; - LPVOID buffer = NULL; - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - goto cleanup; - - // don't set pSecurityAttributes for AppContainer processes - if(!IsAppContainerProcess(hToken)) - { - SECURITY_ATTRIBUTES securityAttributes; - PSID pUserSid = NULL; - SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; - DWORD retLength; - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:6211) // PREfast warning: Leaking memory 'pSD' due to an exception. -#endif /*_PREFAST_ */ - pSD = (PSECURITY_DESCRIPTOR) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]; - if (!pSD) - goto cleanup; - - if (GetTokenInformation(hToken, TokenOwner, NULL, 0, &retLength)) - goto cleanup; - - buffer = (LPVOID) new char[retLength]; - if (!buffer) - goto cleanup; -#ifdef _PREFAST_ -#pragma warning(pop) -#endif /*_PREFAST_*/ - - // Get the SID for the current user - if (!GetTokenInformation(hToken, TokenOwner, (LPVOID) buffer, retLength, &retLength)) - goto cleanup; - - pUserSid = ((TOKEN_OWNER *) buffer)->Owner; - - // Get the SID for the admin group - // Create a SID for the BUILTIN\Administrators group. - if(! AllocateAndInitializeSid(&SIDAuthNT, 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &pAdminSid)) - goto cleanup; - - EXPLICIT_ACCESS ea[2]; - ZeroMemory(ea, 2 * sizeof(EXPLICIT_ACCESS)); - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow the current user full access - ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; // KEY_ALL_ACCESS; - ea[0].grfAccessMode = SET_ACCESS; - ea[0].grfInheritance= NO_INHERITANCE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; - ea[0].Trustee.ptstrName = (LPTSTR) pUserSid; - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow admins full access - ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; //KEY_ALL_ACCESS; - ea[1].grfAccessMode = SET_ACCESS; - ea[1].grfInheritance= NO_INHERITANCE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea[1].Trustee.ptstrName = (LPTSTR) pAdminSid; - - if (SetEntriesInAcl(2, ea, NULL, &pACL) != ERROR_SUCCESS) - goto cleanup; - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) - goto cleanup; - - if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) - goto cleanup; - - memset((void *) &securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); - securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - securityAttributes.lpSecurityDescriptor = pSD; - securityAttributes.bInheritHandle = FALSE; - - pSecurityAttributes = &securityAttributes; - } -#endif // !FEATURE_CORESYSTEM - WCHAR objectName[MAX_LONGPATH] = {0}; WCHAR objectNamePrefix[MAX_LONGPATH] = {0}; GetObjectNamePrefix(processID, fromRuntime, objectNamePrefix); @@ -293,15 +200,6 @@ class BBSweep hTerminationEvent = ::WszCreateEvent(pSecurityAttributes, true, false, NULL); swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hProfWriterSemaphore"), objectNamePrefix); hProfWriterSemaphore = ::WszCreateSemaphore(pSecurityAttributes, MAX_COUNT, MAX_COUNT, objectName); - -#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO -cleanup: - if (pSD) delete [] ((char *) pSD); - if (pAdminSid) FreeSid(pAdminSid); - if (hToken) CloseHandle(hToken); - if (pACL) LocalFree(pACL); - if (buffer) delete [] ((char *) buffer); -#endif } bInitialized = hSweepMutex && @@ -381,7 +279,7 @@ class BBSweep } else { -#if defined (FEATURE_CORESYSTEM) && !defined(DACCESS_COMPILE) +#if !defined(DACCESS_COMPILE) #define MODULE_NAME W("api-ms-win-security-appcontainer-l1-1-0.dll") #else #define MODULE_NAME W("kernel32.dll") @@ -416,7 +314,6 @@ class BBSweep HANDLE hBBSweepThread; // a handle to the CLR sweeper thread (that calls watch for sweep events) }; -#pragma pop_macro("LocalFree") #pragma pop_macro("ReleaseSemaphore") #pragma pop_macro("ResetEvent") #pragma pop_macro("SetEvent") diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 28b1010666369..e544430fa587b 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -176,7 +176,6 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls" CONFIG_DWORD_INFO(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "") CONFIG_DWORD_INFO(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgEnableMixedModeDebugging, W("DbgEnableMixedModeDebuggingInternalOnly"), 0, "") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing") @@ -562,21 +561,36 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, /// Tiered Compilation /// #ifdef FEATURE_TIERED_COMPILATION +#ifdef _DEBUG +// Use lower values to exercise more paths sooner +#define TC_BackgroundWorkerTimeoutMs (100) +#define TC_CallCountThreshold (2) +#define TC_CallCountingDelayMs (1) +#define TC_DelaySingleProcMultiplier (2) +#define TC_DeleteCallCountingStubsAfter (1) +#else // !_DEBUG +#define TC_BackgroundWorkerTimeoutMs (4000) +#define TC_CallCountThreshold (30) +#define TC_CallCountingDelayMs (100) +#define TC_DelaySingleProcMultiplier (10) +#define TC_DeleteCallCountingStubsAfter (4096) +#endif // _DEBUG RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), 4000, "How long in milliseconds the background worker thread may remain idle before exiting.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), 30, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), 10, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), TC_BackgroundWorkerTimeoutMs, "How long in milliseconds the background worker thread may remain idle before exiting.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), TC_CallCountingDelayMs, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), TC_DelaySingleProcMultiplier, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_UseCallCountingStubs, W("TC_UseCallCountingStubs"), 1, "Uses call counting stubs for faster call counting.") -#ifdef _DEBUG -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 1, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") -#else -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 4096, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") -#endif +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), TC_DeleteCallCountingStubsAfter, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") +#undef TC_BackgroundWorkerTimeoutMs +#undef TC_CallCountThreshold +#undef TC_CallCountingDelayMs +#undef TC_DelaySingleProcMultiplier +#undef TC_DeleteCallCountingStubsAfter #endif // FEATURE_TIERED_COMPILATION /// diff --git a/src/coreclr/inc/clrtypes.h b/src/coreclr/inc/clrtypes.h index 6050936814e6f..5e83573e7aa94 100644 --- a/src/coreclr/inc/clrtypes.h +++ b/src/coreclr/inc/clrtypes.h @@ -11,7 +11,7 @@ #ifndef CLRTYPES_H_ #define CLRTYPES_H_ -#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) && defined(FEATURE_CORESYSTEM) +#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) // Prefer intsafe.h when available, which defines many of the MAX/MIN // values below (which is why they are in #ifndef blocks). #include diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h index fdae380a90cb4..686c77217395e 100644 --- a/src/coreclr/inc/dacvars.h +++ b/src/coreclr/inc/dacvars.h @@ -5,7 +5,7 @@ // 1. in daccess.h to build the table of DAC globals // 2. in enummem.cpp to dump out the related memory of static and globals // in a mini dump or heap dump -// 3. in DacUpdateDll and toolbox\DacTablenGen\main.cs +// 3. in DacUpdateDll and tools\DacTablenGen\main.cs // // To use this functionality for other tools or purposes, define the // DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or diff --git a/src/coreclr/inc/holder.h b/src/coreclr/inc/holder.h index 448610634a612..4ec7b106cc0e8 100644 --- a/src/coreclr/inc/holder.h +++ b/src/coreclr/inc/holder.h @@ -1152,7 +1152,14 @@ FORCEINLINE void HolderFreeLibrary(HMODULE h) { FreeLibrary(h); } typedef Wrapper, HolderFreeLibrary, NULL> HModuleHolder; template FORCEINLINE -void DoLocalFree(T* pMem) { (LocalFree)((HLOCAL)pMem); } +void DoLocalFree(T* pMem) +{ +#ifdef HOST_WINDOWS + (LocalFree)((void*)pMem); +#else + (free)((void*)pMem); +#endif +} template using LocalAllocHolder = SpecializedWrapper<_TYPE, DoLocalFree<_TYPE>>; diff --git a/src/coreclr/inc/ostype.h b/src/coreclr/inc/ostype.h index ddb0ec5d01b8e..78494c71c2b66 100644 --- a/src/coreclr/inc/ostype.h +++ b/src/coreclr/inc/ostype.h @@ -31,20 +31,6 @@ extern RunningOnStatusEnum gRunningOnStatus; void InitRunningOnVersionStatus(); -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -typedef enum -{ - WINRT_STATUS_UNINITED = 0, - WINRT_STATUS_UNSUPPORTED, - WINRT_STATUS_SUPPORTED -} -WinRTStatusEnum; - -extern WinRTStatusEnum gWinRTStatus; - -void InitWinRTStatus(); -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM - //***************************************************************************** // Returns true if you are running on Windows 8 or newer. //***************************************************************************** @@ -65,28 +51,10 @@ inline BOOL RunningOnWin8() #ifdef FEATURE_COMINTEROP -#ifdef FEATURE_CORESYSTEM - inline BOOL WinRTSupported() { return RunningOnWin8(); } -#else -inline BOOL WinRTSupported() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - - if (gWinRTStatus == WINRT_STATUS_UNINITED) - { - InitWinRTStatus(); - } - - return gWinRTStatus == WINRT_STATUS_SUPPORTED; -} -#endif // FEATURE_CORESYSTEM #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/inc/sigparser.h b/src/coreclr/inc/sigparser.h index 1e861c4cd3edf..b9b79e951e40b 100644 --- a/src/coreclr/inc/sigparser.h +++ b/src/coreclr/inc/sigparser.h @@ -864,6 +864,21 @@ class CorTypeInfo return (GetGCType_NoThrow(type) == TYPE_GC_REF); } + static BOOL IsByRef(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType(type) == TYPE_GC_BYREF); + } + static BOOL IsByRef_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType_NoThrow(type) == TYPE_GC_BYREF); + } + FORCEINLINE static BOOL IsGenericVariable(CorElementType type) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 65cda94ed9900..081299e7bfdbc 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -165,9 +165,7 @@ #define FEATURE_DOUBLE_ALIGNMENT_HINT #endif -#if defined(FEATURE_CORESYSTEM) #define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -#endif // defined(FEATURE_CORESYSTEM) // If defined, support interpretation. diff --git a/src/coreclr/inc/volatile.h b/src/coreclr/inc/volatile.h index 610a408f39fb6..e127fe25f99b1 100644 --- a/src/coreclr/inc/volatile.h +++ b/src/coreclr/inc/volatile.h @@ -73,7 +73,10 @@ #endif #if defined(__GNUC__) -#if defined(HOST_ARM) || defined(HOST_ARM64) +#if defined(HOST_ARMV6) +// DMB ISH not valid on ARMv6 +#define VOLATILE_MEMORY_BARRIER() asm volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory") +#elif defined(HOST_ARM) || defined(HOST_ARM64) // This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows. #define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb ish" : : : "memory") #else diff --git a/src/coreclr/inc/vptr_list.h b/src/coreclr/inc/vptr_list.h index 0fde8090d0699..d8e6cd42bd7c3 100644 --- a/src/coreclr/inc/vptr_list.h +++ b/src/coreclr/inc/vptr_list.h @@ -23,7 +23,6 @@ VPTR_CLASS(ReflectionModule) VPTR_CLASS(AppDomain) VPTR_CLASS(SystemDomain) -VPTR_CLASS(DomainAssembly) VPTR_CLASS(PrecodeStubManager) VPTR_CLASS(StubLinkStubManager) VPTR_CLASS(ThePreStubManager) @@ -39,7 +38,6 @@ VPTR_CLASS(DelegateInvokeStubManager) VPTR_CLASS(TailCallStubManager) #endif VPTR_CLASS(CallCountingStubManager) -VPTR_CLASS(PEAssembly) VPTR_CLASS(PEImageLayout) VPTR_CLASS(ConvertedImageLayout) @@ -85,9 +83,6 @@ VPTR_CLASS(ExternalMethodFrame) #ifdef FEATURE_READYTORUN VPTR_CLASS(DynamicHelperFrame) #endif -#if defined(TARGET_X86) -VPTR_CLASS(UMThkCallFrame) -#endif #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) VPTR_CLASS(TailCallFrame) #endif diff --git a/src/coreclr/inc/winwrap.h b/src/coreclr/inc/winwrap.h index 3bf11baea318b..0c1b7c22459ce 100644 --- a/src/coreclr/inc/winwrap.h +++ b/src/coreclr/inc/winwrap.h @@ -188,16 +188,11 @@ #define WszWideCharToMultiByte WideCharToMultiByte #define WszCreateSemaphore(_secattr, _count, _maxcount, _name) CreateSemaphoreExW((_secattr), (_count), (_maxcount), (_name), 0, MAXIMUM_ALLOWED | SYNCHRONIZE | SEMAPHORE_MODIFY_STATE) -#ifdef FEATURE_CORESYSTEM - -// CoreSystem has GetFileVersionInfo{Size}Ex but not GetFileVersionInfoSize{Size} #undef GetFileVersionInfo #define GetFileVersionInfo(_filename, _handle, _len, _data) GetFileVersionInfoEx(0, (_filename), (_handle), (_len), (_data)) #undef GetFileVersionInfoSize #define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle)) -#endif // FEATURE_CORESYSTEM - #ifndef _T #define _T(str) W(str) #endif @@ -259,12 +254,6 @@ inline DWORD GetMaxDBCSCharByteSize() #endif // HOST_UNIX } -#ifndef HOST_UNIX -BOOL RunningInteractive(); -#else // !HOST_UNIX -#define RunningInteractive() FALSE -#endif // !HOST_UNIX - #ifndef Wsz_mbstowcs #define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize) #endif @@ -481,11 +470,7 @@ inline int LateboundMessageBoxA(HWND hWnd, return LateboundMessageBoxW(hWnd, wszText, wszCaption, uType); } -#if defined(FEATURE_CORESYSTEM) - #define MessageBoxW LateboundMessageBoxW #define MessageBoxA LateboundMessageBoxA -#endif // FEATURE_CORESYSTEM - #endif // __WIN_WRAP_H__ diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index c46cdd18a164e..ebca7e65daaac 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -32,6 +32,9 @@ function(create_standalone_jit) elseif((TARGETDETAILS_ARCH STREQUAL "arm") OR (TARGETDETAILS_ARCH STREQUAL "armel")) set(JIT_ARCH_SOURCES ${JIT_ARM_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_ARM_HEADERS}) + elseif((TARGETDETAILS_ARCH STREQUAL "armv6") OR (TARGETDETAILS_ARCH STREQUAL "armv6l")) + set(JIT_ARCH_SOURCES ${JIT_ARMV6_SOURCES}) + set(JIT_ARCH_HEADERS ${JIT_ARMV6_HEADERS}) elseif(TARGETDETAILS_ARCH STREQUAL "x86") set(JIT_ARCH_SOURCES ${JIT_I386_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_I386_HEADERS}) @@ -220,6 +223,10 @@ set( JIT_ARM64_SOURCES hwintrinsiccodegenarm64.cpp ) +set( JIT_ARMV6_SOURCES + # Not supported as JIT target +) + set( JIT_S390X_SOURCES # Not supported as JIT target ) @@ -362,6 +369,10 @@ set( JIT_ARM_HEADERS registerarm.h ) +set ( JIT_ARMV6_HEADERS + # Not supported as JIT target +) + set ( JIT_S390X_HEADERS # Not supported as JIT target ) @@ -380,6 +391,8 @@ convert_to_absolute_path(JIT_I386_SOURCES ${JIT_I386_SOURCES}) convert_to_absolute_path(JIT_I386_HEADERS ${JIT_I386_HEADERS}) convert_to_absolute_path(JIT_ARM64_SOURCES ${JIT_ARM64_SOURCES}) convert_to_absolute_path(JIT_ARM64_HEADERS ${JIT_ARM64_HEADERS}) +convert_to_absolute_path(JIT_ARMV6_SOURCES ${JIT_ARMV6_SOURCES}) +convert_to_absolute_path(JIT_ARMV6_HEADERS ${JIT_ARMV6_HEADERS}) convert_to_absolute_path(JIT_S390X_SOURCES ${JIT_S390X_SOURCES}) convert_to_absolute_path(JIT_S390X_HEADERS ${JIT_S390X_HEADERS}) @@ -389,6 +402,9 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64) elseif(CLR_CMAKE_TARGET_ARCH_ARM) set(JIT_ARCH_SOURCES ${JIT_ARM_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_ARM_HEADERS}) +elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + set(JIT_ARCH_SOURCES ${JIT_ARMV6_SOURCES}) + set(JIT_ARCH_HEADERS ${JIT_ARMV6_HEADERS}) elseif(CLR_CMAKE_TARGET_ARCH_I386) set(JIT_ARCH_SOURCES ${JIT_I386_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_I386_HEADERS}) @@ -550,13 +566,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) + 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) + 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/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 51fad24772b47..4e0e708be326c 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2576,7 +2576,6 @@ void Compiler::optAssertionGen(GenTree* tree) case GT_OBJ: case GT_BLK: - case GT_DYN_BLK: case GT_IND: // R-value indirections create non-null assertions, but not all indirections are R-values. // Those under ADDR nodes or on the LHS of ASGs are "locations", and will not end up @@ -4626,9 +4625,9 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, case GT_OBJ: case GT_BLK: - case GT_DYN_BLK: case GT_IND: case GT_NULLCHECK: + case GT_STORE_DYN_BLK: return optAssertionProp_Ind(assertions, tree, stmt); case GT_BOUNDS_CHECK: diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index c5996ac8239d7..81a511f4bceed 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -825,6 +825,17 @@ struct BasicBlock : private LIR::Range BBswtDesc* bbJumpSwt; // switch descriptor }; + bool KindIs(BBjumpKinds kind) const + { + return bbJumpKind == kind; + } + + template + bool KindIs(BBjumpKinds kind, T... rest) const + { + return KindIs(kind) || KindIs(rest...); + } + // NumSucc() gives the number of successors, and GetSucc() returns a given numbered successor. // // There are two versions of these functions: ones that take a Compiler* and ones that don't. You must diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 9dd13cdc12533..18cb59068bab3 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -82,7 +82,7 @@ bool CodeGen::genInstrWithConstant( // generate two or more instructions // first we load the immediate into tmpReg - instGen_Set_Reg_To_Imm(attr, tmpReg, imm); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, imm); // generate the instruction using a three register encoding with the immediate in tmpReg GetEmitter()->emitIns_R_R_R(ins, attr, reg1, reg2, tmpReg); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 250a23904944a..595e2a232e541 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -120,7 +120,7 @@ bool CodeGen::genInstrWithConstant(instruction ins, // generate two or more instructions // first we load the immediate into tmpReg - instGen_Set_Reg_To_Imm(size, tmpReg, imm); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, imm); regSet.verifyRegUsed(tmpReg); // when we are in an unwind code region @@ -6922,9 +6922,12 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // R_R fmov/fcmp/fcvt + // R_R cmeq/fmov/fcmp/fcvt // + // cmeq scalar + theEmitter->emitIns_R_R(INS_cmeq, EA_8BYTE, REG_V0, REG_V1); + // fmov to vector to vector theEmitter->emitIns_Mov(INS_fmov, EA_8BYTE, REG_V0, REG_V2, /* canSkip */ false); theEmitter->emitIns_Mov(INS_fmov, EA_4BYTE, REG_V1, REG_V3, /* canSkip */ false); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 227de58aedc97..24c57d110b7ba 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -2416,7 +2416,7 @@ class CopyBlockUnrollHelper const int dstOffsetAligned = AlignUp((UINT)dstOffset, storePairRegsAlignment); - if (endDstOffset - dstOffsetAligned >= storePairRegsWritesBytes) + if (byteCount >= (unsigned)storePairRegsWritesBytes) { const int dstBytesToAlign = dstOffsetAligned - dstOffset; @@ -2840,8 +2840,8 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) // When both addresses are not 16-byte aligned the CopyBlock instruction sequence starts with padding // str instruction. For example, when both addresses are 8-byte aligned the instruction sequence looks like // - // ldr D_simdReg1, [srcReg, #srcOffset] - // str D_simdReg1, [dstReg, #dstOffset] + // ldr X_intReg1, [srcReg, #srcOffset] + // str X_intReg1, [dstReg, #dstOffset] // ldp Q_simdReg1, Q_simdReg2, [srcReg, #srcOffset+8] // stp Q_simdReg1, Q_simdReg2, [dstReg, #dstOffset+8] // ldp Q_simdReg1, Q_simdReg2, [srcReg, #srcOffset+40] @@ -2853,7 +2853,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) // be profitable). const bool canUse16ByteWideInstrs = isSrcRegAddrAlignmentKnown && isDstRegAddrAlignmentKnown && - (size >= FP_REGSIZE_BYTES) && (srcRegAddrAlignment == dstRegAddrAlignment); + (size >= 2 * FP_REGSIZE_BYTES) && (srcRegAddrAlignment == dstRegAddrAlignment); bool shouldUse16ByteWideInstrs = false; @@ -2876,8 +2876,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) { // In order to use 16-byte instructions the JIT needs to adjust either srcOffset or dstOffset. // The JIT should use 16-byte loads and stores when the resulting sequence (incl. an additional add - // instruction) - // has fewer number of instructions. + // instruction) has fewer number of instructions. if (helper.InstructionCount(FP_REGSIZE_BYTES) + 1 < helper.InstructionCount(REGSIZE_BYTES)) { @@ -2937,51 +2936,31 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) const unsigned intRegCount = node->AvailableTempRegCount(RBM_ALLINT); - switch (intRegCount) + if (intRegCount >= 2) { - case 1: - intReg1 = node->GetSingleTempReg(RBM_ALLINT); - break; - case 2: - intReg1 = node->ExtractTempReg(RBM_ALLINT); - intReg2 = node->GetSingleTempReg(RBM_ALLINT); - break; - default: - break; + intReg1 = node->ExtractTempReg(RBM_ALLINT); + intReg2 = node->ExtractTempReg(RBM_ALLINT); } - - regNumber simdReg1 = REG_NA; - regNumber simdReg2 = REG_NA; - - const unsigned simdRegCount = node->AvailableTempRegCount(RBM_ALLFLOAT); - - switch (simdRegCount) + else if (intRegCount == 1) { - case 1: - simdReg1 = node->GetSingleTempReg(RBM_ALLFLOAT); - break; - case 2: - simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT); - simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT); - break; - default: - break; + intReg1 = node->GetSingleTempReg(RBM_ALLINT); + intReg2 = rsGetRsvdReg(); + } + else + { + intReg1 = rsGetRsvdReg(); } if (shouldUse16ByteWideInstrs) { + const regNumber simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT); + const regNumber simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT); + helper.Unroll(FP_REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter()); } else { - if (intReg2 == REG_NA) - { - helper.Unroll(REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter()); - } - else - { - helper.UnrollBaseInstrs(intReg1, intReg2, srcReg, dstReg, GetEmitter()); - } + helper.UnrollBaseInstrs(intReg1, intReg2, srcReg, dstReg, GetEmitter()); } #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 7072e4fd66b0a..fe8b2d82dcaec 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -6236,15 +6236,9 @@ void CodeGen::genEnregisterOSRArgsAndLocals() // This local was part of the live tier0 state and is enregistered in the // OSR method. Initialize the register from the right frame slot. // - // We currently don't expect to see enregistered multi-reg args in OSR methods, - // as struct promotion is disabled. So any struct arg just uses the location - // on the tier0 frame. - // // If we ever enable promotion we'll need to generalize what follows to copy each // field from the tier0 frame to its OSR home. // - assert(!varDsc->lvIsMultiRegArg); - if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)) { // This arg or local is not live at entry to the OSR method. @@ -6391,16 +6385,31 @@ void CodeGen::genEnregisterOSRArgsAndLocals() void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed) { - // For OSR the original method has set this up for us. + assert(compiler->compGeneratingProlog); + + const bool reportArg = compiler->lvaReportParamTypeArg(); + if (compiler->opts.IsOSR()) { + PatchpointInfo* const ppInfo = compiler->info.compPatchpointInfo; + if (reportArg) + { + // OSR method will use Tier0 slot to report context arg. + // + assert(ppInfo->HasGenericContextArgOffset()); + JITDUMP("OSR method will use Tier0 frame slot for generics context arg.\n"); + } + else if (compiler->lvaKeepAliveAndReportThis()) + { + // OSR method will use Tier0 slot to report `this` as context. + // + assert(ppInfo->HasKeptAliveThis()); + JITDUMP("OSR method will use Tier0 frame slot for generics context `this`.\n"); + } + return; } - assert(compiler->compGeneratingProlog); - - bool reportArg = compiler->lvaReportParamTypeArg(); - // We should report either generic context arg or "this" when used so. if (!reportArg) { @@ -7543,6 +7552,16 @@ void CodeGen::genFnProlog() #endif // PROFILING_SUPPORTED + // For OSR we may have a zero-length prolog. That's not supported + // when the method must report a generics context,/ so add a nop if so. + // + if (compiler->opts.IsOSR() && (GetEmitter()->emitGetPrologOffsetEstimate() == 0) && + (compiler->lvaReportParamTypeArg() || compiler->lvaKeepAliveAndReportThis())) + { + JITDUMP("OSR: prolog was zero length and has generic context to report: adding nop to pad prolog.\n"); + instGen(INS_nop); + } + if (!GetInterruptible()) { // The 'real' prolog ends here for non-interruptible methods. diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 51e9afc074398..009c0d9ad41dd 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1657,7 +1657,7 @@ void CodeGen::genConsumeRegs(GenTree* tree) #ifdef FEATURE_SIMD // (In)Equality operation that produces bool result, when compared // against Vector zero, marks its Vector Zero operand as contained. - assert(tree->OperIsLeaf() || tree->IsSIMDZero()); + assert(tree->OperIsLeaf() || tree->IsSIMDZero() || tree->IsVectorZero()); #else assert(tree->OperIsLeaf()); #endif @@ -1912,7 +1912,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) } else { - GenTree* sizeNode = blkNode->AsDynBlk()->gtDynamicSize; + GenTree* sizeNode = blkNode->AsStoreDynBlk()->gtDynamicSize; inst_Mov(sizeNode->TypeGet(), sizeReg, sizeNode->GetRegNum(), /* canSkip */ true); } } @@ -2022,7 +2022,7 @@ void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber // in the case where the size is a constant (i.e. it is not GT_STORE_DYN_BLK). if (blkNode->OperGet() == GT_STORE_DYN_BLK) { - genConsumeReg(blkNode->AsDynBlk()->gtDynamicSize); + genConsumeReg(blkNode->AsStoreDynBlk()->gtDynamicSize); } // Next, perform any necessary moves. diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 7da0bd7285625..cfc97dc6b1370 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1972,6 +1972,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) inst_Mov(TYP_FLOAT, tempXmm, reg1, /* canSkip */ false); GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm); } + genProduceReg(lclNode); } #elif defined(TARGET_AMD64) assert(!TargetOS::IsWindows || !"Multireg store to SIMD reg not supported on Windows x64"); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index b8775857bb659..cf87223f71760 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2644,15 +2644,19 @@ void Compiler::compInitOptions(JitFlags* jitFlags) verboseDump = (JitConfig.JitDumpTier0() > 0); } - // Optionally suppress dumping some OSR jit requests. + // Optionally suppress dumping except for a specific OSR jit request. // - if (verboseDump && jitFlags->IsSet(JitFlags::JIT_FLAG_OSR)) - { - const int desiredOffset = JitConfig.JitDumpAtOSROffset(); + const int dumpAtOSROffset = JitConfig.JitDumpAtOSROffset(); - if (desiredOffset != -1) + if (verboseDump && (dumpAtOSROffset != -1)) + { + if (jitFlags->IsSet(JitFlags::JIT_FLAG_OSR)) + { + verboseDump = (((IL_OFFSET)dumpAtOSROffset) == info.compILEntry); + } + else { - verboseDump = (((IL_OFFSET)desiredOffset) == info.compILEntry); + verboseDump = false; } } @@ -4632,7 +4636,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Run an early flow graph simplification pass // auto earlyUpdateFlowGraphPhase = [this]() { - const bool doTailDup = false; + constexpr bool doTailDup = false; fgUpdateFlowGraph(doTailDup); }; DoPhase(this, PHASE_EARLY_UPDATE_FLOW_GRAPH, earlyUpdateFlowGraphPhase); @@ -4772,6 +4776,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Unroll loops // DoPhase(this, PHASE_UNROLL_LOOPS, &Compiler::optUnrollLoops); + + // Clear loop table info that is not used after this point, and might become invalid. + // + DoPhase(this, PHASE_CLEAR_LOOP_INFO, &Compiler::optClearLoopIterInfo); } #ifdef DEBUG @@ -4905,7 +4913,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // update the flowgraph if we modified it during the optimization phase // auto optUpdateFlowGraphPhase = [this]() { - const bool doTailDup = false; + constexpr bool doTailDup = false; fgUpdateFlowGraph(doTailDup); }; DoPhase(this, PHASE_OPT_UPDATE_FLOW_GRAPH, optUpdateFlowGraphPhase); @@ -4962,11 +4970,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_SIMPLE_LOWERING, &Compiler::fgSimpleLowering); -#ifdef DEBUG - fgDebugCheckBBlist(); - fgDebugCheckLinks(); -#endif - // Enable this to gather statistical data such as // call and register argument info, flowgraph and loop info, etc. compJitStats(); @@ -5017,10 +5020,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Copied from rpPredictRegUse() SetFullPtrRegMapRequired(codeGen->GetInterruptible() || !codeGen->isFramePointerUsed()); -#ifdef DEBUG - fgDebugCheckLinks(); -#endif - #if FEATURE_LOOP_ALIGN // Place loop alignment instructions DoPhase(this, PHASE_ALIGN_LOOPS, &Compiler::placeLoopAlignInstructions); @@ -5626,11 +5625,8 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr, // Set this before the first 'BADCODE' // Skip verification where possible - //.tiVerificationNeeded = !compileFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION); assert(compileFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION)); - assert(!compIsForInlining() || !tiVerificationNeeded); // Inlinees must have been verified. - /* Setup an error trap */ struct Param @@ -6157,17 +6153,9 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, eeGetMethodFullName(info.compMethodHnd), dspPtr(impTokenLookupContextHandle))); } - if (tiVerificationNeeded) - { - JITLOG((LL_INFO10000, "tiVerificationNeeded initially set to true for %s\n", info.compFullName)); - } #endif // DEBUG - /* Since tiVerificationNeeded can be turned off in the middle of - compiling a method, and it might have caused blocks to be queued up - for reimporting, impCanReimport can be used to check for reimporting. */ - - impCanReimport = (tiVerificationNeeded || compStressCompile(STRESS_CHK_REIMPORT, 15)); + impCanReimport = compStressCompile(STRESS_CHK_REIMPORT, 15); /* Initialize set a bunch of global values */ @@ -6397,9 +6385,10 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, // Honor the config setting that tells the jit to // always optimize methods with loops. // - // If that's not set, and OSR is enabled, the jit may still + // If neither of those apply, and OSR is enabled, the jit may still // decide to optimize, if there's something in the method that - // OSR currently cannot handle. + // OSR currently cannot handle, or we're optionally suppressing + // OSR by method hash. // const char* reason = nullptr; @@ -6407,35 +6396,42 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, { reason = "tail.call and not BBINSTR"; } - else if ((info.compFlags & CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS) != 0) + else if (compHasBackwardJump && ((info.compFlags & CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS) != 0)) { - if (compHasBackwardJump) - { - reason = "loop"; - } + reason = "loop"; } - else if (JitConfig.TC_OnStackReplacement() > 0) + + if (compHasBackwardJump && (reason == nullptr) && (JitConfig.TC_OnStackReplacement() > 0)) { - const bool patchpointsOK = compCanHavePatchpoints(&reason); - assert(patchpointsOK || (reason != nullptr)); + const char* noPatchpointReason = nullptr; + bool canEscapeViaOSR = compCanHavePatchpoints(&reason); #ifdef DEBUG - // Optionally disable OSR by method hash. - // - if (patchpointsOK && compHasBackwardJump) + if (canEscapeViaOSR) { + // Optionally disable OSR by method hash. This will force any + // method that might otherwise get trapped in Tier0 to be optimized. + // static ConfigMethodRange JitEnableOsrRange; JitEnableOsrRange.EnsureInit(JitConfig.JitEnableOsrRange()); const unsigned hash = impInlineRoot()->info.compMethodHash(); if (!JitEnableOsrRange.Contains(hash)) { - JITDUMP("Disabling OSR -- Method hash 0x%08x not within range ", hash); - JITDUMPEXEC(JitEnableOsrRange.Dump()); - JITDUMP("\n"); - reason = "OSR disabled by JitEnableOsrRange"; + canEscapeViaOSR = false; + reason = "OSR disabled by JitEnableOsrRange"; } } #endif + + if (canEscapeViaOSR) + { + JITDUMP("\nOSR enabled for this method\n"); + } + else + { + JITDUMP("\nOSR disabled for this method: %s\n", noPatchpointReason); + assert(reason != nullptr); + } } if (reason != nullptr) @@ -9385,7 +9381,6 @@ void cTreeFlags(Compiler* comp, GenTree* tree) FALLTHROUGH; case GT_BLK: - case GT_DYN_BLK: case GT_STORE_BLK: case GT_STORE_DYN_BLK: @@ -9738,7 +9733,7 @@ bool Compiler::lvaIsOSRLocal(unsigned varNum) // void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block) { - assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK)); + assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK)); tree->ChangeOper(GT_NULLCHECK); tree->ChangeType(TYP_INT); block->bbFlags |= BBF_HAS_NULLCHECK; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 5a16ac8a58bf8..967d27eac4703 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -1735,7 +1735,7 @@ struct fgArgTabEntry // In this case, it must be removed by GenTreeCall::ResetArgInfo. bool isNonStandardArgAddedLate() const { - switch (nonStandardArgKind) + switch (static_cast(nonStandardArgKind)) { case NonStandardArgKind::None: case NonStandardArgKind::PInvokeFrame: @@ -4844,7 +4844,7 @@ class Compiler static LONG jitNestingLevel; #endif // DEBUG - static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut); + static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut = nullptr); void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult); @@ -5432,7 +5432,7 @@ class Compiler // Requires that "tree" is a GT_IND marked as an array index, and that its address argument // has been parsed to yield the other input arguments. If evaluation of the address - // can raise exceptions, those should be captured in the exception set "excVN." + // can raise exceptions, those should be captured in the exception set "addrXvnp". // Assumes that "elemTypeEq" is the (equivalence class rep) of the array element type. // Marks "tree" with the VN for H[elemTypeEq][arrVN][inx][fldSeq] (for the liberal VN; a new unique // VN for the conservative VN.) Also marks the tree's argument as the address of an array element. @@ -5443,14 +5443,14 @@ class Compiler CORINFO_CLASS_HANDLE elemTypeEq, ValueNum arrVN, ValueNum inxVN, - ValueNum excVN, + ValueNumPair addrXvnp, FieldSeqNode* fldSeq); - // Requires "funcApp" to be a VNF_PtrToArrElem, and "addrXvn" to represent the exception set thrown + // Requires "funcApp" to be a VNF_PtrToArrElem, and "addrXvnp" to represent the exception set thrown // by evaluating the array index expression "tree". Returns the value number resulting from // dereferencing the array in the current GcHeap state. If "tree" is non-null, it must be the // "GT_IND" that does the dereference, and it is given the returned value number. - ValueNum fgValueNumberArrIndexVal(GenTree* tree, struct VNFuncApp* funcApp, ValueNum addrXvn); + ValueNum fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* funcApp, ValueNumPair addrXvnp); // Compute the value number for a byref-exposed load of the given type via the given pointerVN. ValueNum fgValueNumberByrefExposedLoad(var_types type, ValueNum pointerVN); @@ -5560,6 +5560,10 @@ class Compiler // Adds the exception sets for the current tree node void fgValueNumberAddExceptionSet(GenTree* tree); +#ifdef DEBUG + void fgDebugCheckExceptionSets(); +#endif + // These are the current value number for the memory implicit variables while // doing value numbering. These are the value numbers under the "liberal" interpretation // of memory values; the "conservative" interpretation needs no VN, since every access of @@ -5941,7 +5945,7 @@ class Compiler bool fgReorderBlocks(); - void fgDetermineFirstColdBlock(); + PhaseStatus fgDetermineFirstColdBlock(); bool fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc = nullptr); @@ -6400,11 +6404,16 @@ class Compiler GenTree* fgMorphGetStructAddr(GenTree** pTree, CORINFO_CLASS_HANDLE clsHnd, bool isRValue = false); GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigned blockWidth, bool isBlkReqd); GenTree* fgMorphCopyBlock(GenTree* tree); + GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree); GenTree* fgMorphForRegisterFP(GenTree* tree); GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr); GenTree* fgOptimizeCast(GenTreeCast* cast); GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp); GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp); + GenTree* fgOptimizeCommutativeArithmetic(GenTreeOp* tree); + GenTree* fgOptimizeAddition(GenTreeOp* add); + GenTree* fgOptimizeMultiply(GenTreeOp* mul); + GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp); GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects); GenTree* fgMorphRetInd(GenTreeUnOp* tree); GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree); @@ -6415,7 +6424,7 @@ class Compiler bool fgMorphCanUseLclFldForCopy(unsigned lclNum1, unsigned lclNum2); GenTreeLclVar* fgMorphTryFoldObjAsLclVar(GenTreeObj* obj); - GenTree* fgMorphCommutative(GenTreeOp* tree); + GenTreeOp* fgMorphCommutative(GenTreeOp* tree); GenTree* fgMorphCastedBitwiseOp(GenTreeOp* tree); GenTree* fgMorphReduceAddOps(GenTree* tree); @@ -6731,6 +6740,12 @@ class Compiler CALLINT_ALL, // kills everything (normal method call) }; + enum class FieldKindForVN + { + SimpleStatic, + WithBaseAddr + }; + public: // A "LoopDsc" describes a ("natural") loop. We (currently) require the body of a loop to be a contiguous (in // bbNext order) sequence of basic blocks. (At times, we may require the blocks in a loop to be "properly numbered" @@ -6785,9 +6800,9 @@ class Compiler int lpLoopVarFPCount; // The register count for the FP LclVars that are read/written inside this loop int lpVarInOutFPCount; // The register count for the FP LclVars that are alive inside or across this loop - typedef JitHashTable, bool> FieldHandleSet; - FieldHandleSet* lpFieldsModified; // This has entries (mappings to "true") for all static field and object - // instance fields modified + typedef JitHashTable, FieldKindForVN> + FieldHandleSet; + FieldHandleSet* lpFieldsModified; // This has entries for all static field and object instance fields modified // in the loop. typedef JitHashTable, bool> ClassHandleSet; @@ -6798,7 +6813,7 @@ class Compiler // Adds the variable liveness information for 'blk' to 'this' LoopDsc void AddVariableLiveness(Compiler* comp, BasicBlock* blk); - inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd); + inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind); // This doesn't *always* take a class handle -- it can also take primitive types, encoded as class handles // (shifted left, with a low-order bit set to distinguish.) // Use the {Encode/Decode}ElemType methods to construct/destruct these. @@ -6916,7 +6931,7 @@ class Compiler } #ifdef DEBUG - void lpValidatePreHeader() + void lpValidatePreHeader() const { // If this is called, we expect there to be a pre-header. assert(lpFlags & LPFLG_HAS_PREHEAD); @@ -6977,6 +6992,8 @@ class Compiler BasicBlock* exit, unsigned char exitCnt); + void optClearLoopIterInfo(); + #ifdef DEBUG void optPrintLoopInfo(unsigned lnum, bool printVerbose = false); void optPrintLoopInfo(const LoopDsc* loop, bool printVerbose = false); @@ -7045,7 +7062,7 @@ class Compiler void AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock* blk); // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops. - void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd); + void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind); // Adds "elemType" to the set of modified array element types of "lnum" and any parent loops. void AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemType); @@ -7105,12 +7122,6 @@ class Compiler bool optNarrowTree(GenTree* tree, var_types srct, var_types dstt, ValueNumPair vnpNarrow, bool doit); - /************************************************************************** - * Optimization conditions - *************************************************************************/ - - bool optAvoidIntMult(void); - protected: // The following is the upper limit on how many expressions we'll keep track // of for the CSE analysis. @@ -7370,14 +7381,11 @@ class Compiler typedef ArrayStack GenTreePtrStack; typedef JitHashTable, GenTreePtrStack*> LclNumToGenTreePtrStack; - // Kill set to track variables with intervening definitions. - VARSET_TP optCopyPropKillSet; - // Copy propagation functions. - void optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName); + void optCopyProp(Statement* stmt, GenTreeLclVarCommon* tree, unsigned lclNum, LclNumToGenTreePtrStack* curSsaName); void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName); void optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName); - unsigned optIsSsaLocal(GenTree* tree); + unsigned optIsSsaLocal(GenTreeLclVarCommon* lclNode); int optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc, bool preferOp2); void optVnCopyProp(); INDEBUG(void optDumpCopyPropStack(LclNumToGenTreePtrStack* curSsaName)); @@ -8070,7 +8078,6 @@ class Compiler CORINFO_RESOLVED_TOKEN* pConstrainedToken, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult); - inline CORINFO_CALLINFO_FLAGS addVerifyFlag(CORINFO_CALLINFO_FLAGS flags); void eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS flags, @@ -10701,12 +10708,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ public: - // Set to true if verification cannot be skipped for this method - // CoreCLR does not ever run IL verification. Compile out the verifier from the JIT by making this a constant. - // TODO: Delete the verifier from the JIT? (https://github.com/dotnet/runtime/issues/32648) - // bool tiVerificationNeeded; - static const bool tiVerificationNeeded = false; - // Returns true if child is equal to or a subtype of parent for merge purposes // This support is necessary to suport attributes that are not described in // for example, signatures. For example, the permanent home byref (byref that @@ -11490,42 +11491,14 @@ class GenTreeVisitor break; } - case GT_DYN_BLK: - { - GenTreeDynBlk* const dynBlock = node->AsDynBlk(); - - GenTree** op1Use = &dynBlock->gtOp1; - GenTree** op2Use = &dynBlock->gtDynamicSize; - - result = WalkTree(op1Use, dynBlock); - if (result == fgWalkResult::WALK_ABORT) - { - return result; - } - result = WalkTree(op2Use, dynBlock); - if (result == fgWalkResult::WALK_ABORT) - { - return result; - } - break; - } - case GT_STORE_DYN_BLK: { - GenTreeDynBlk* const dynBlock = node->AsDynBlk(); + GenTreeStoreDynBlk* const dynBlock = node->AsStoreDynBlk(); GenTree** op1Use = &dynBlock->gtOp1; GenTree** op2Use = &dynBlock->gtOp2; GenTree** op3Use = &dynBlock->gtDynamicSize; - if (TVisitor::UseExecutionOrder) - { - if (dynBlock->IsReverseOp()) - { - std::swap(op1Use, op2Use); - } - } - result = WalkTree(op1Use, dynBlock); if (result == fgWalkResult::WALK_ABORT) { diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index b75828d4cc68a..f03ecd43f7702 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1986,13 +1986,18 @@ inline bool Compiler::lvaKeepAliveAndReportThis() // the VM requires us to keep the generics context alive or it is used in a look-up. // We keep it alive in the lookup scenario, even when the VM didn't ask us to, // because collectible types need the generics context when gc-ing. + // + // Methoods that can inspire OSR methods must always report context as live + // if (genericsContextIsThis) { - const bool mustKeep = (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_KEEP_ALIVE) != 0; + const bool mustKeep = (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_KEEP_ALIVE) != 0; + const bool hasPatchpoint = doesMethodHavePatchpoints() || doesMethodHavePartialCompilationPatchpoints(); - if (lvaGenericsContextInUse || mustKeep) + if (lvaGenericsContextInUse || mustKeep || hasPatchpoint) { - JITDUMP("Reporting this as generic context: %s\n", mustKeep ? "must keep" : "referenced"); + JITDUMP("Reporting this as generic context: %s\n", + mustKeep ? "must keep" : (hasPatchpoint ? "patchpoints" : "referenced")); return true; } } @@ -2024,6 +2029,13 @@ inline bool Compiler::lvaReportParamTypeArg() { return true; } + + // Methoods that have patchpoints always report context as live + // + if (doesMethodHavePatchpoints() || doesMethodHavePartialCompilationPatchpoints()) + { + return true; + } } // Otherwise, we don't need to report it -- the generics context parameter is unused. @@ -2343,29 +2355,29 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX inline unsigned Compiler::compMapILargNum(unsigned ILargNum) { - assert(ILargNum < info.compILargsCount || tiVerificationNeeded); + assert(ILargNum < info.compILargsCount); // Note that this works because if compRetBuffArg/compTypeCtxtArg/lvVarargsHandleArg are not present // they will be BAD_VAR_NUM (MAX_UINT), which is larger than any variable number. if (ILargNum >= info.compRetBuffArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } if (ILargNum >= (unsigned)info.compTypeCtxtArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } if (ILargNum >= (unsigned)lvaVarargsHandleArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } - assert(ILargNum < info.compArgsCount || tiVerificationNeeded); + assert(ILargNum < info.compArgsCount); return (ILargNum); } @@ -3346,14 +3358,14 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) } } -inline void Compiler::LoopDsc::AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd) +inline void Compiler::LoopDsc::AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind) { if (lpFieldsModified == nullptr) { lpFieldsModified = new (comp->getAllocatorLoopHoist()) Compiler::LoopDsc::FieldHandleSet(comp->getAllocatorLoopHoist()); } - lpFieldsModified->Set(fldHnd, true, FieldHandleSet::Overwrite); + lpFieldsModified->Set(fldHnd, fieldKind, FieldHandleSet::Overwrite); } inline void Compiler::LoopDsc::AddModifiedElemType(Compiler* comp, CORINFO_CLASS_HANDLE structHnd) @@ -3566,22 +3578,6 @@ inline bool Compiler::LoopDsc::lpArrLenLimit(Compiler* comp, ArrIndex* index) co return false; } -/* -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XX XX -XX Optimization activation rules XX -XX XX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -*/ - -// should we try to replace integer multiplication with lea/add/shift sequences? -inline bool Compiler::optAvoidIntMult(void) -{ - return (compCodeOpt() != SMALL_CODE); -} - /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -4347,20 +4343,9 @@ void GenTree::VisitOperands(TVisitor visitor) return; } - case GT_DYN_BLK: - { - GenTreeDynBlk* const dynBlock = this->AsDynBlk(); - if (visitor(dynBlock->gtOp1) == VisitResult::Abort) - { - return; - } - visitor(dynBlock->gtDynamicSize); - return; - } - case GT_STORE_DYN_BLK: { - GenTreeDynBlk* const dynBlock = this->AsDynBlk(); + GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk(); if (visitor(dynBlock->gtOp1) == VisitResult::Abort) { return; @@ -4516,11 +4501,12 @@ inline static bool StructHasNoPromotionFlagSet(DWORD attribs) return ((attribs & CORINFO_FLG_DONT_PROMOTE) != 0); } -/***************************************************************************** - * This node should not be referenced by anyone now. Set its values to garbage - * to catch extra references - */ - +//------------------------------------------------------------------------------ +// DEBUG_DESTROY_NODE: sets value of tree to garbage to catch extra references +// +// Arguments: +// tree: This node should not be referenced by anyone now +// inline void DEBUG_DESTROY_NODE(GenTree* tree) { #ifdef DEBUG @@ -4541,6 +4527,19 @@ inline void DEBUG_DESTROY_NODE(GenTree* tree) #endif } +//------------------------------------------------------------------------------ +// DEBUG_DESTROY_NODE: sets value of trees to garbage to catch extra references +// +// Arguments: +// tree, ...rest: These nodes should not be referenced by anyone now +// +template +void DEBUG_DESTROY_NODE(GenTree* tree, T... rest) +{ + DEBUG_DESTROY_NODE(tree); + DEBUG_DESTROY_NODE(rest...); +} + //------------------------------------------------------------------------------ // lvRefCnt: access reference count for this local var // diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h index e5c15c1d438a6..8f72dcce2360c 100644 --- a/src/coreclr/jit/compphases.h +++ b/src/coreclr/jit/compphases.h @@ -5,7 +5,7 @@ // // -// Names of x86 JIT phases, in order. Assumes that the caller defines CompPhaseNameMacro +// Names of JIT phases, in order. Assumes that the caller defines CompPhaseNameMacro // in a useful way before including this file, e.g., to define the phase enumeration and the // corresponding array of string names of those phases. This include file undefines CompPhaseNameMacro // after the last use. @@ -61,6 +61,7 @@ CompPhaseNameMacro(PHASE_ZERO_INITS, "Redundant zero Inits", CompPhaseNameMacro(PHASE_FIND_LOOPS, "Find loops", "LOOP-FND", false, -1, false) CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false) CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1, false) +CompPhaseNameMacro(PHASE_CLEAR_LOOP_INFO, "Clear loop info", "LP-CLEAR", false, -1, false) CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1, false) CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1, false) CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1, false) @@ -86,7 +87,6 @@ CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true) CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false) CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1, false) -CompPhaseNameMacro(PHASE_ALIGN_LOOPS, "Place 'align' instructions", "LOOP-ALIGN", false, -1, false) CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1, false) CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS, false) @@ -100,6 +100,7 @@ CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN, false) CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN, false) CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN, false) +CompPhaseNameMacro(PHASE_ALIGN_LOOPS, "Place 'align' instructions", "LOOP-ALIGN", false, -1, false) CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1, false) CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1, false) CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1, false) diff --git a/src/coreclr/jit/copyprop.cpp b/src/coreclr/jit/copyprop.cpp index 1c80436902f90..52c765a12dc41 100644 --- a/src/coreclr/jit/copyprop.cpp +++ b/src/coreclr/jit/copyprop.cpp @@ -32,17 +32,16 @@ void Compiler::optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrSt { for (GenTree* const tree : stmt->TreeList()) { - if (!tree->IsLocal()) - { - continue; - } - const unsigned lclNum = optIsSsaLocal(tree); - if (lclNum == BAD_VAR_NUM) - { - continue; - } - if (tree->gtFlags & GTF_VAR_DEF) + GenTreeLclVarCommon* lclDefNode = nullptr; + if (tree->OperIs(GT_ASG) && tree->DefinesLocal(this, &lclDefNode)) { + const unsigned lclNum = optIsSsaLocal(lclDefNode); + + if (lclNum == BAD_VAR_NUM) + { + continue; + } + GenTreePtrStack* stack = nullptr; curSsaName->Lookup(lclNum, &stack); stack->Pop(); @@ -123,97 +122,67 @@ int Compiler::optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDs // definitions share the same value number. If so, then we can make the replacement. // // Arguments: -// block - Block the tree belongs to // stmt - Statement the tree belongs to -// tree - The tree to perform copy propagation on +// tree - The local tree to perform copy propagation on +// lclNum - The local number of said tree // curSsaName - The map from lclNum to its recently live definitions as a stack -void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName) +void Compiler::optCopyProp(Statement* stmt, + GenTreeLclVarCommon* tree, + unsigned lclNum, + LclNumToGenTreePtrStack* curSsaName) { - // TODO-Review: EH successor/predecessor iteration seems broken. - if (block->bbCatchTyp == BBCT_FINALLY || block->bbCatchTyp == BBCT_FAULT) - { - return; - } - - // If not local nothing to do. - if (!tree->IsLocal()) - { - return; - } - if (tree->OperGet() == GT_PHI_ARG || tree->OperGet() == GT_LCL_FLD) - { - return; - } - - // Propagate only on uses. - if (tree->gtFlags & GTF_VAR_DEF) - { - return; - } - const unsigned lclNum = optIsSsaLocal(tree); - - // Skip non-SSA variables. - if (lclNum == BAD_VAR_NUM) - { - return; - } - + assert((lclNum != BAD_VAR_NUM) && (optIsSsaLocal(tree) == lclNum) && ((tree->gtFlags & GTF_VAR_DEF) == 0)); assert(tree->gtVNPair.GetConservative() != ValueNumStore::NoVN); for (LclNumToGenTreePtrStack::KeyIterator iter = curSsaName->Begin(); !iter.Equal(curSsaName->End()); ++iter) { unsigned newLclNum = iter.Get(); - GenTree* op = iter.GetValue()->Top(); - // Nothing to do if same. if (lclNum == newLclNum) { continue; } - // Skip variables with assignments embedded in the statement (i.e., with a comma). Because we - // are not currently updating their SSA names as live in the copy-prop pass of the stmt. - if (VarSetOps::IsMember(this, optCopyPropKillSet, lvaTable[newLclNum].lvVarIndex)) - { - continue; - } + LclVarDsc* varDsc = lvaGetDesc(lclNum); + LclVarDsc* newLclVarDsc = lvaGetDesc(newLclNum); + GenTree* newLclDefNode = iter.GetValue()->Top(); // Note that this "def" node can actually be a use (for + // parameters and other use-before-def locals). // Do not copy propagate if the old and new lclVar have different 'doNotEnregister' settings. // This is primarily to avoid copy propagating to IND(ADDR(LCL_VAR)) where the replacement lclVar // is not marked 'lvDoNotEnregister'. // However, in addition, it may not be profitable to propagate a 'doNotEnregister' lclVar to an // existing use of an enregisterable lclVar. - - if (lvaTable[lclNum].lvDoNotEnregister != lvaTable[newLclNum].lvDoNotEnregister) + if (varDsc->lvDoNotEnregister != newLclVarDsc->lvDoNotEnregister) { continue; } - if (op->gtFlags & GTF_VAR_CAST) + if ((gsShadowVarInfo != nullptr) && newLclVarDsc->lvIsParam && + (gsShadowVarInfo[newLclNum].shadowCopy == lclNum)) { continue; } - if (gsShadowVarInfo != nullptr && lvaTable[newLclNum].lvIsParam && - gsShadowVarInfo[newLclNum].shadowCopy == lclNum) - { - continue; - } - ValueNum opVN = GetUseAsgDefVNOrTreeVN(op); - if (opVN == ValueNumStore::NoVN) + + ValueNum newLclDefVN = GetUseAsgDefVNOrTreeVN(newLclDefNode); + if (newLclDefVN == ValueNumStore::NoVN) { continue; } - if (op->TypeGet() != tree->TypeGet()) + + if (newLclDefNode->TypeGet() != tree->TypeGet()) { continue; } - if (opVN != tree->gtVNPair.GetConservative()) + + if (newLclDefVN != tree->gtVNPair.GetConservative()) { continue; } - if (optCopyProp_LclVarScore(lvaGetDesc(lclNum), lvaGetDesc(newLclNum), true) <= 0) + + if (optCopyProp_LclVarScore(varDsc, newLclVarDsc, true) <= 0) { continue; } @@ -230,34 +199,25 @@ void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, Lc // node x2 = phi(x0, x1) which can then be used to substitute 'c' with. But because of pruning // there would be no such phi node. To solve this we'll check if 'x' is live, before replacing // 'c' with 'x.' - if (!lvaTable[newLclNum].lvVerTypeInfo.IsThisPtr()) - { - if (lvaTable[newLclNum].IsAddressExposed()) - { - continue; - } - // We compute liveness only on tracked variables. So skip untracked locals. - if (!lvaTable[newLclNum].lvTracked) - { - continue; - } + // We compute liveness only on tracked variables. And all SSA locals are tracked. + assert(lvaGetDesc(newLclNum)->lvTracked); - // Because of this dependence on live variable analysis, CopyProp phase is immediately - // after Liveness, SSA and VN. - if (!VarSetOps::IsMember(this, compCurLife, lvaTable[newLclNum].lvVarIndex)) - { - continue; - } + // Because of this dependence on live variable analysis, CopyProp phase is immediately + // after Liveness, SSA and VN. + if ((newLclNum != info.compThisArg) && !VarSetOps::IsMember(this, compCurLife, newLclVarDsc->lvVarIndex)) + { + continue; } + unsigned newSsaNum = SsaConfig::RESERVED_SSA_NUM; - if (op->gtFlags & GTF_VAR_DEF) + if (newLclDefNode->gtFlags & GTF_VAR_DEF) { - newSsaNum = GetSsaNumForLocalVarDef(op); + newSsaNum = GetSsaNumForLocalVarDef(newLclDefNode); } else // parameters, this pointer etc. { - newSsaNum = op->AsLclVarCommon()->GetSsaNum(); + newSsaNum = newLclDefNode->AsLclVarCommon()->GetSsaNum(); } if (newSsaNum == SsaConfig::RESERVED_SSA_NUM) @@ -271,48 +231,42 @@ void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, Lc JITDUMP("VN based copy assertion for "); printTreeID(tree); printf(" V%02d " FMT_VN " by ", lclNum, tree->GetVN(VNK_Conservative)); - printTreeID(op); - printf(" V%02d " FMT_VN ".\n", newLclNum, op->GetVN(VNK_Conservative)); - gtDispTree(tree, nullptr, nullptr, true); + printTreeID(newLclDefNode); + printf(" V%02d " FMT_VN ".\n", newLclNum, newLclDefNode->GetVN(VNK_Conservative)); + DISPNODE(tree); } #endif tree->AsLclVarCommon()->SetLclNum(newLclNum); tree->AsLclVarCommon()->SetSsaNum(newSsaNum); gtUpdateSideEffects(stmt, tree); + #ifdef DEBUG if (verbose) { printf("copy propagated to:\n"); - gtDispTree(tree, nullptr, nullptr, true); + DISPNODE(tree); } #endif break; } - return; } //------------------------------------------------------------------------------ // optIsSsaLocal : helper to check if the tree is a local that participates in SSA numbering. // // Arguments: -// tree - The tree to perform the check on; +// lclNode - The local tree to perform the check on; // // Returns: // - lclNum if the local is participating in SSA; // - fieldLclNum if the parent local can be replaced by its only field; // - BAD_VAR_NUM otherwise. // -unsigned Compiler::optIsSsaLocal(GenTree* tree) +unsigned Compiler::optIsSsaLocal(GenTreeLclVarCommon* lclNode) { - if (!tree->IsLocal()) - { - return BAD_VAR_NUM; - } - - GenTreeLclVarCommon* lclNode = tree->AsLclVarCommon(); - unsigned lclNum = lclNode->GetLclNum(); - LclVarDsc* varDsc = lvaGetDesc(lclNum); + unsigned lclNum = lclNode->GetLclNum(); + LclVarDsc* varDsc = lvaGetDesc(lclNum); if (!lvaInSsa(lclNum) && varDsc->CanBeReplacedWithItsField(this)) { @@ -355,68 +309,63 @@ void Compiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curS VarSetOps::Assign(this, compCurLife, block->bbLiveIn); for (Statement* const stmt : block->Statements()) { - VarSetOps::ClearD(this, optCopyPropKillSet); - // Walk the tree to find if any local variable can be replaced with current live definitions. + // Simultaneously, push live definitions on the stack - that logic must be in sync with the + // SSA renaming process. for (GenTree* const tree : stmt->TreeList()) { treeLifeUpdater.UpdateLife(tree); - optCopyProp(block, stmt, tree, curSsaName); - - // TODO-Review: Merge this loop with the following loop to correctly update the - // live SSA num while also propagating copies. - // - // 1. This loop performs copy prop with currently live (on-top-of-stack) SSA num. - // 2. The subsequent loop maintains a stack for each lclNum with - // currently active SSA numbers when definitions are encountered. - // - // If there is an embedded definition using a "comma" in a stmt, then the currently - // live SSA number will get updated only in the next loop (2). However, this new - // definition is now supposed to be live (on tos). If we did not update the stacks - // using (2), copy prop (1) will use a SSA num defined outside the stmt ignoring the - // embedded update. Killing the variable is a simplification to produce 0 ASM diffs - // for an update release. - // - const unsigned lclNum = optIsSsaLocal(tree); - if ((lclNum != BAD_VAR_NUM) && (tree->gtFlags & GTF_VAR_DEF)) + GenTreeLclVarCommon* lclDefNode = nullptr; + if (tree->OperIs(GT_ASG) && tree->DefinesLocal(this, &lclDefNode)) { - VarSetOps::AddElemD(this, optCopyPropKillSet, lvaTable[lclNum].lvVarIndex); - } - } + const unsigned lclNum = optIsSsaLocal(lclDefNode); - // This logic must be in sync with SSA renaming process. - for (GenTree* const tree : stmt->TreeList()) - { - const unsigned lclNum = optIsSsaLocal(tree); - if (lclNum == BAD_VAR_NUM) - { - continue; - } + if (lclNum == BAD_VAR_NUM) + { + continue; + } - // As we encounter a definition add it to the stack as a live definition. - if (tree->gtFlags & GTF_VAR_DEF) - { GenTreePtrStack* stack; if (!curSsaName->Lookup(lclNum, &stack)) { stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator()); } - stack->Push(tree); + stack->Push(lclDefNode); curSsaName->Set(lclNum, stack, LclNumToGenTreePtrStack::Overwrite); } - // If we encounter first use of a param or this pointer add it as a live definition. - // Since they are always live, do it only once. - else if ((tree->gtOper == GT_LCL_VAR) && !(tree->gtFlags & GTF_VAR_USEASG) && - (lvaTable[lclNum].lvIsParam || lvaTable[lclNum].lvVerTypeInfo.IsThisPtr())) + // TODO-CQ: propagate on LCL_FLDs too. + else if (tree->OperIs(GT_LCL_VAR) && ((tree->gtFlags & GTF_VAR_DEF) == 0)) { - GenTreePtrStack* stack; - if (!curSsaName->Lookup(lclNum, &stack)) + const unsigned lclNum = optIsSsaLocal(tree->AsLclVarCommon()); + + if (lclNum == BAD_VAR_NUM) { - stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator()); - stack->Push(tree); - curSsaName->Set(lclNum, stack); + continue; + } + + // If we encounter first use of a param or this pointer add it as a live definition. + // Since they are always live, we'll do it only once. + if (lvaGetDesc(lclNum)->lvIsParam || (lclNum == info.compThisArg)) + { + GenTreePtrStack* stack; + if (!curSsaName->Lookup(lclNum, &stack)) + { + assert(tree->AsLclVarCommon()->GetSsaNum() == SsaConfig::FIRST_SSA_NUM); + + stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator()); + stack->Push(tree); + curSsaName->Set(lclNum, stack); + } } + + // TODO-Review: EH successor/predecessor iteration seems broken. + if ((block->bbCatchTyp == BBCT_FINALLY) || (block->bbCatchTyp == BBCT_FAULT)) + { + continue; + } + + optCopyProp(stmt, tree->AsLclVarCommon(), lclNum, curSsaName); } } } @@ -462,7 +411,6 @@ void Compiler::optVnCopyProp() } VarSetOps::AssignNoCopy(this, compCurLife, VarSetOps::MakeEmpty(this)); - VarSetOps::AssignNoCopy(this, optCopyPropKillSet, VarSetOps::MakeEmpty(this)); class CopyPropDomTreeVisitor : public DomTreeVisitor { diff --git a/src/coreclr/jit/earlyprop.cpp b/src/coreclr/jit/earlyprop.cpp index f00b3f6e3ad6e..283c9c8901ae7 100644 --- a/src/coreclr/jit/earlyprop.cpp +++ b/src/coreclr/jit/earlyprop.cpp @@ -110,7 +110,7 @@ void Compiler::optCheckFlagsAreSet(unsigned methodFlag, if ((basicBlock->bbFlags & bbFlag) == 0) { printf("%s is not set on " FMT_BB " but is required because of the following tree \n", bbFlagStr, - compCurBB->bbNum); + basicBlock->bbNum); gtDispTree(tree); assert(false); } diff --git a/src/coreclr/jit/ee_il_dll.hpp b/src/coreclr/jit/ee_il_dll.hpp index 33d5fab12ac5b..337ca8f147977 100644 --- a/src/coreclr/jit/ee_il_dll.hpp +++ b/src/coreclr/jit/ee_il_dll.hpp @@ -294,11 +294,3 @@ inline CORINFO_CALLINFO_FLAGS combine(CORINFO_CALLINFO_FLAGS flag1, CORINFO_CALL { return (CORINFO_CALLINFO_FLAGS)(flag1 | flag2); } -inline CORINFO_CALLINFO_FLAGS Compiler::addVerifyFlag(CORINFO_CALLINFO_FLAGS flags) -{ - if (tiVerificationNeeded) - { - flags = combine(flags, CORINFO_CALLINFO_VERIFICATION); - } - return flags; -} diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 47daad7798fc2..66706ecaf488e 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -614,6 +614,15 @@ class emitter assert((ins != INS_invalid) && (ins < INS_count)); _idIns = ins; } + bool idInsIs(instruction ins) const + { + return idIns() == ins; + } + template + bool idInsIs(instruction ins, T... rest) const + { + return idInsIs(ins) || idInsIs(rest...); + } insFormat idInsFmt() const { @@ -2874,19 +2883,12 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id) /* static */ emitAttr emitter::emitGetMemOpSize(instrDesc* id) { emitAttr defaultSize = id->idOpSize(); - emitAttr newSize = defaultSize; + switch (id->idIns()) { - case INS_vextractf128: - case INS_vextracti128: - case INS_vinsertf128: - case INS_vinserti128: - { - return EA_16BYTE; - } - case INS_pextrb: case INS_pinsrb: + case INS_vpbroadcastb: { return EA_1BYTE; } @@ -2894,27 +2896,142 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id) case INS_pextrw: case INS_pextrw_sse41: case INS_pinsrw: + case INS_pmovsxbq: + case INS_pmovzxbq: + case INS_vpbroadcastw: { return EA_2BYTE; } + case INS_addss: + case INS_cmpss: + case INS_comiss: + case INS_cvtss2sd: + case INS_cvtss2si: + case INS_cvttss2si: + case INS_divss: case INS_extractps: case INS_insertps: + case INS_maxss: + case INS_minss: + case INS_movss: + case INS_mulss: case INS_pextrd: case INS_pinsrd: + case INS_pmovsxbd: + case INS_pmovsxwq: + case INS_pmovzxbd: + case INS_pmovzxwq: + case INS_rcpss: + case INS_roundss: + case INS_rsqrtss: + case INS_sqrtss: + case INS_subss: + case INS_ucomiss: + case INS_vbroadcastss: + case INS_vfmadd132ss: + case INS_vfmadd213ss: + case INS_vfmadd231ss: + case INS_vfmsub132ss: + case INS_vfmsub213ss: + case INS_vfmsub231ss: + case INS_vfnmadd132ss: + case INS_vfnmadd213ss: + case INS_vfnmadd231ss: + case INS_vfnmsub132ss: + case INS_vfnmsub213ss: + case INS_vfnmsub231ss: + case INS_vpbroadcastd: { return EA_4BYTE; } + case INS_addsd: + case INS_cmpsd: + case INS_comisd: + case INS_cvtsd2si: + case INS_cvtsd2ss: + case INS_cvttsd2si: + case INS_divsd: + case INS_maxsd: + case INS_minsd: + case INS_movhpd: + case INS_movhps: + case INS_movlpd: + case INS_movlps: + case INS_movq: + case INS_movsd: + case INS_mulsd: case INS_pextrq: case INS_pinsrq: + case INS_pmovsxbw: + case INS_pmovsxdq: + case INS_pmovsxwd: + case INS_pmovzxbw: + case INS_pmovzxdq: + case INS_pmovzxwd: + case INS_roundsd: + case INS_sqrtsd: + case INS_subsd: + case INS_ucomisd: + case INS_vbroadcastsd: + case INS_vfmadd132sd: + case INS_vfmadd213sd: + case INS_vfmadd231sd: + case INS_vfmsub132sd: + case INS_vfmsub213sd: + case INS_vfmsub231sd: + case INS_vfnmadd132sd: + case INS_vfnmadd213sd: + case INS_vfnmadd231sd: + case INS_vfnmsub132sd: + case INS_vfnmsub213sd: + case INS_vfnmsub231sd: + case INS_vpbroadcastq: { return EA_8BYTE; } + case INS_cvtdq2pd: + case INS_cvtps2pd: + { + if (defaultSize == 32) + { + return EA_16BYTE; + } + else + { + assert(defaultSize == 16); + return EA_8BYTE; + } + } + + case INS_vbroadcastf128: + case INS_vbroadcasti128: + case INS_vextractf128: + case INS_vextracti128: + case INS_vinsertf128: + case INS_vinserti128: + { + return EA_16BYTE; + } + + case INS_movddup: + { + if (defaultSize == 32) + { + return EA_32BYTE; + } + else + { + assert(defaultSize == 16); + return EA_8BYTE; + } + } + default: { - return id->idOpSize(); + return defaultSize; } } } diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 51e02c5c26895..52f24d4524279 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -4732,19 +4732,19 @@ void emitter::emitIns_R_R( assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); - if (isValidVectorDatasize(size)) + if (insOptsAnyArrangement(opt)) { // Vector operation - assert(insOptsAnyArrangement(opt)); + assert(isValidVectorDatasize(size)); assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); fmt = IF_DV_2M; } else { - NYI("Untested"); // Scalar operation - assert(size == EA_8BYTE); // Only Double supported + assert(size == EA_8BYTE); + assert(insOptsNone(opt)); fmt = IF_DV_2L; } break; @@ -12971,6 +12971,11 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } + if (ins == INS_fcmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) @@ -12990,6 +12995,11 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } + if (ins == INS_cmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar) @@ -13126,6 +13136,11 @@ void emitter::emitDispIns( emitDispReg(id->idReg1(), size, true); emitDispReg(id->idReg2(), size, false); } + if (fmt == IF_DV_2L && ins == INS_cmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general) @@ -15614,6 +15629,11 @@ bool emitter::IsMovInstruction(instruction ins) // mov Rx, Ry # <-- last instruction // mov Ry, Rx # <-- current instruction can be omitted. // +// 4. Move that does zero extension while previous instruction already did it +// +// ldr Wx, [Ry] # <-- ldr will clear upper 4 byte of Wx +// mov Wx, Wx # <-- clears upper 4 byte in Wx +// // Arguments: // ins - The current instruction // size - Operand size of current instruction @@ -15640,6 +15660,8 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN return false; } + const bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); + if (dst == src) { // A mov with a EA_4BYTE has the side-effect of clearing the upper bits @@ -15655,10 +15677,18 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN JITDUMP("\n -- suppressing mov because src and dst is same 16-byte register.\n"); return true; } + else if (isGeneralRegisterOrSP(dst) && (size == EA_4BYTE)) + { + // See if the previous instruction already cleared upper 4 bytes for us unintentionally + if (!isFirstInstrInBlock && (emitLastIns != nullptr) && (emitLastIns->idReg1() == dst) && + (emitLastIns->idOpSize() == size) && emitLastIns->idInsIs(INS_ldr, INS_ldrh, INS_ldrb)) + { + JITDUMP("\n -- suppressing mov because ldr already cleared upper 4 bytes\n"); + return true; + } + } } - bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); - if (!isFirstInstrInBlock && // Don't optimize if instruction is not the first instruction in IG. (emitLastIns != nullptr) && (emitLastIns->idIns() == INS_mov) && // Don't optimize if last instruction was not 'mov'. diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 1075c4ccd97d0..d90c5771ce1a9 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -8965,9 +8965,8 @@ void emitter::emitDispIns( } else { - attr = emitGetMemOpSize(id); - - sstr = codeGen->genSizeStr(attr); + attr = id->idOpSize(); + sstr = codeGen->genSizeStr(emitGetMemOpSize(id)); if (ins == INS_lea) { @@ -11743,17 +11742,6 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) #ifdef DEBUG int byteSize = EA_SIZE_IN_BYTES(emitGetMemOpSize(id)); - // this instruction has a fixed size (4) src. - if (ins == INS_cvttss2si || ins == INS_cvtss2sd || ins == INS_vbroadcastss) - { - byteSize = 4; - } - // This has a fixed size (8) source. - if (ins == INS_vbroadcastsd) - { - byteSize = 8; - } - // Check that the offset is properly aligned (i.e. the ddd in [ddd]) // When SMALL_CODE is set, we only expect 4-byte alignment, otherwise // we expect the same alignment as the size of the constant. diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index d6ed324deb242..5cef7d5aa12f2 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -193,7 +193,7 @@ bool IsDstDstSrcAVXInstruction(instruction ins); bool IsDstSrcSrcAVXInstruction(instruction ins); bool HasRegularWideForm(instruction ins); bool HasRegularWideImmediateForm(instruction ins); -bool DoesWriteZeroFlag(instruction ins); +static bool DoesWriteZeroFlag(instruction ins); bool DoesWriteSignFlag(instruction ins); bool DoesResetOverflowAndCarryFlags(instruction ins); bool IsFlagsAlwaysModified(instrDesc* id); diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index 1845af97b5731..dfb5a859b4300 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -258,11 +258,7 @@ void debugError(const char* msg, const char* file, unsigned line) // If ComPlus_JitRequired is 0 or is not set, we will not assert. if (JitConfig.JitRequired() == 1 || getBreakOnBadCode()) { - // Don't assert if verification is done. - if (!env->compiler->tiVerificationNeeded || getBreakOnBadCode()) - { - assertAbort(msg, file, line); - } + assertAbort(msg, file, line); } BreakIfDebuggerPresent(); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 73695932cb543..7f8bd7b01c6d0 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -321,7 +321,7 @@ bool Compiler::fgFirstBBisScratch() // Normally, the first scratch block is a fall-through block. However, if the block after it was an empty // BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block // a BBJ_ALWAYS block. - assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS)); + assert(fgFirstBBScratch->KindIs(BBJ_NONE, BBJ_ALWAYS)); return true; } @@ -1113,12 +1113,12 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed { ni = lookupNamedIntrinsic(methodHnd); - bool foldableIntrinsc = false; + bool foldableIntrinsic = false; if (IsMathIntrinsic(ni)) { // Most Math(F) intrinsics have single arguments - foldableIntrinsc = FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo); + foldableIntrinsic = FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo); } else { @@ -1131,7 +1131,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case NI_System_GC_KeepAlive: { pushedStack.PushUnknown(); - foldableIntrinsc = true; + foldableIntrinsic = true; break; } @@ -1145,6 +1145,20 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed break; } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: + if (FgStack::IsConstArgument(pushedStack.Top(), impInlineInfo)) + { + compInlineResult->Note(InlineObservation::CALLEE_CONST_ARG_FEEDS_ISCONST); + } + else + { + compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_ISCONST); + } + // RuntimeHelpers.IsKnownConstant is always folded into a const + pushedStack.PushConstant(); + foldableIntrinsic = true; + break; + // These are foldable if the first argument is a constant case NI_System_Type_get_IsValueType: case NI_System_Type_GetTypeFromHandle: @@ -1159,10 +1173,10 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case NI_Vector128_Create: #endif { - // Top() in order to keep it as is in case of foldableIntrinsc + // Top() in order to keep it as is in case of foldableIntrinsic if (FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo)) { - foldableIntrinsc = true; + foldableIntrinsic = true; } break; } @@ -1177,7 +1191,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed if (FgStack::IsConstantOrConstArg(pushedStack.Top(0), impInlineInfo) && FgStack::IsConstantOrConstArg(pushedStack.Top(1), impInlineInfo)) { - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushConstant(); } break; @@ -1186,31 +1200,31 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case NI_IsSupported_True: case NI_IsSupported_False: { - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushConstant(); break; } #if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) case NI_Vector128_get_Count: case NI_Vector256_get_Count: - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushConstant(); // TODO: check if it's a loop condition - we unroll such loops. break; case NI_Vector256_get_Zero: case NI_Vector256_get_AllBitsSet: - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushUnknown(); break; #elif defined(TARGET_ARM64) && defined(FEATURE_HW_INTRINSICS) case NI_Vector64_get_Count: case NI_Vector128_get_Count: - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushConstant(); break; case NI_Vector128_get_Zero: case NI_Vector128_get_AllBitsSet: - foldableIntrinsc = true; + foldableIntrinsic = true; pushedStack.PushUnknown(); break; #endif @@ -1222,7 +1236,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed } } - if (foldableIntrinsc) + if (foldableIntrinsic) { compInlineResult->Note(InlineObservation::CALLSITE_FOLDABLE_INTRINSIC); handled = true; @@ -2215,7 +2229,7 @@ void Compiler::fgAdjustForAddressExposedOrWrittenThis() LclVarDsc* thisVarDsc = lvaGetDesc(info.compThisArg); // Optionally enable adjustment during stress. - if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15)) + if (compStressCompile(STRESS_GENERIC_VARN, 15)) { thisVarDsc->lvHasILStoreOp = true; } @@ -2407,7 +2421,7 @@ void Compiler::fgLinkBasicBlocks() /* Is the next block reachable? */ - if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE) + if (curBBdesc->KindIs(BBJ_ALWAYS, BBJ_LEAVE)) { break; } @@ -3502,9 +3516,6 @@ void Compiler::fgFindBasicBlocks() #endif // !FEATURE_EH_FUNCLETS -#ifndef DEBUG - if (tiVerificationNeeded) -#endif { // always run these checks for a debug build verCheckNestingLevel(initRoot); @@ -3513,7 +3524,7 @@ void Compiler::fgFindBasicBlocks() #ifndef DEBUG // fgNormalizeEH assumes that this test has been passed. And Ssa assumes that fgNormalizeEHTable // has been run. So do this unless we're in minOpts mode (and always in debug). - if (tiVerificationNeeded || !opts.MinOpts()) + if (!opts.MinOpts()) #endif { fgCheckBasicBlockControlFlow(); @@ -4369,7 +4380,7 @@ BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr) BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ) { - assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH || curr->bbJumpKind == BBJ_ALWAYS); + assert(curr->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_ALWAYS)); if (fgComputePredsDone) { @@ -4538,7 +4549,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) BasicBlock* bPrev = block->bbPrev; - JITDUMP("fgRemoveBlock " FMT_BB "\n", block->bbNum); + JITDUMP("fgRemoveBlock " FMT_BB ", unreachable=%s\n", block->bbNum, dspBool(unreachable)); // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the // *unique* successors of the switch block), invalidate that cache, since an entry in one of @@ -4562,12 +4573,6 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) fgUnreachableBlock(block); - /* If this is the last basic block update fgLastBB */ - if (block == fgLastBB) - { - fgLastBB = bPrev; - } - #if defined(FEATURE_EH_FUNCLETS) // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext if (block == fgFirstFuncletBB) @@ -4620,7 +4625,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) leaveBlk->bbRefs = 0; leaveBlk->bbPreds = nullptr; - fgRemoveBlock(leaveBlk, true); + fgRemoveBlock(leaveBlk, /* unreachable */ true); #if defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM) fgClearFinallyTargetBit(leaveBlk->bbJumpDest); @@ -4670,7 +4675,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) } #endif // DEBUG - noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS); + noway_assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS)); /* Who is the "real" successor of this block? */ @@ -5182,7 +5187,7 @@ bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL * { bool result = false; - if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS)) + if (bJump->KindIs(BBJ_COND, BBJ_ALWAYS)) { BasicBlock* bDest = bJump->bbJumpDest; BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc; @@ -5799,7 +5804,7 @@ bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt) noway_assert(bAlt != nullptr); // We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND - if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND)) + if (!bAlt->KindIs(BBJ_ALWAYS, BBJ_COND)) { return false; } diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index 7fd7b5d562563..2df6d000419b9 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -2151,11 +2151,11 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 * { if (block == fgEntryBB) { - printf("original-entry"); + printf(" original-entry"); } if (block == fgOSREntryBB) { - printf("osr-entry"); + printf(" osr-entry"); } } @@ -2503,7 +2503,7 @@ bool BBPredsChecker::CheckEhTryDsc(BasicBlock* block, BasicBlock* blockPred, EHb bool BBPredsChecker::CheckEhHndDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehHndlDsc) { // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region - if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET)) + if (blockPred->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET)) { return true; } @@ -3534,12 +3534,22 @@ void Compiler::fgDebugCheckNodesUniqueness() // - If the method has natural loops, the loop table is not null // - Loop `top` must come before `bottom`. // - Loop `entry` must be between `top` and `bottom`. +// - Children loops of a loop are disjoint. // - All basic blocks with loop numbers set have a corresponding loop in the table // - All basic blocks without a loop number are not in a loop // - All parents of the loop with the block contain that block +// - If the loop has a pre-header, it is valid +// - The loop flags are valid // void Compiler::fgDebugCheckLoopTable() { +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgDebugCheckLoopTable\n"); + } +#endif // DEBUG + if (optLoopCount > 0) { assert(optLoopTable != nullptr); @@ -3655,8 +3665,38 @@ void Compiler::fgDebugCheckLoopTable() assert(loop.lpExit == nullptr); } - if (loop.lpParent != BasicBlock::NOT_IN_LOOP) + if (loop.lpParent == BasicBlock::NOT_IN_LOOP) { + // This is a top-level loop. + + // Verify all top-level loops are disjoint. We don't have a list of just these (such as a + // top-level pseudo-loop entry with a list of all top-level lists), so we have to iterate + // over the entire loop table. + for (unsigned j = 0; j < optLoopCount; j++) + { + if (i == j) + { + // Don't compare against ourselves. + continue; + } + const LoopDsc& otherLoop = optLoopTable[j]; + if (otherLoop.lpFlags & LPFLG_REMOVED) + { + continue; + } + if (otherLoop.lpParent != BasicBlock::NOT_IN_LOOP) + { + // Only consider top-level loops + continue; + } + assert(MappedChecks::lpDisjoint(blockNumMap, &loop, otherLoop)); + } + } + else + { + // This is not a top-level loop + + assert(loop.lpParent != BasicBlock::NOT_IN_LOOP); assert(loop.lpParent < optLoopCount); assert(loop.lpParent < i); // outer loops come before inner loops in the table const LoopDsc& parentLoop = optLoopTable[loop.lpParent]; @@ -3674,10 +3714,12 @@ void Compiler::fgDebugCheckLoopTable() assert(child < optLoopCount); assert(i < child); // outer loops come before inner loops in the table const LoopDsc& childLoop = optLoopTable[child]; - if ((childLoop.lpFlags & LPFLG_REMOVED) == 0) // removed child loop might still be in table + if (childLoop.lpFlags & LPFLG_REMOVED) // removed child loop might still be in table { - assert(MappedChecks::lpContains(blockNumMap, &loop, childLoop)); + continue; } + assert(MappedChecks::lpContains(blockNumMap, &loop, childLoop)); + assert(childLoop.lpParent == i); } // Verify all child loops are disjoint. @@ -3734,6 +3776,43 @@ void Compiler::fgDebugCheckLoopTable() assert(MappedChecks::lpContains(blockNumMap, &loop, predBlock)); } } + + loop.lpValidatePreHeader(); + } + + // Check the flags. + // Note that the various init/limit flags are only used when LPFLG_ITER is set, but they are set first, + // separately, and only if everything works out is LPFLG_ITER set. If LPFLG_ITER is NOT set, the + // individual flags are not un-set (arguably, they should be). + + // Only one of the `init` flags can be set. + assert(genCountBits((unsigned)(loop.lpFlags & (LPFLG_VAR_INIT | LPFLG_CONST_INIT))) <= 1); + + // Only one of the `limit` flags can be set. (Note that LPFLG_SIMD_LIMIT is a "sub-flag" that can be + // set when LPFLG_CONST_LIMIT is set.) + assert(genCountBits((unsigned)(loop.lpFlags & (LPFLG_VAR_LIMIT | LPFLG_CONST_LIMIT | LPFLG_ARRLEN_LIMIT))) <= + 1); + + // LPFLG_SIMD_LIMIT can only be set if LPFLG_CONST_LIMIT is set. + if (loop.lpFlags & LPFLG_SIMD_LIMIT) + { + assert(loop.lpFlags & LPFLG_CONST_LIMIT); + } + + if (loop.lpFlags & (LPFLG_CONST_INIT | LPFLG_VAR_INIT)) + { + assert(loop.lpInitBlock != nullptr); + + if (loop.lpFlags & LPFLG_VAR_INIT) + { + assert(loop.lpVarInit < lvaCount); + } + } + + if (loop.lpFlags & LPFLG_ITER) + { + loop.VERIFY_lpIterTree(); + loop.VERIFY_lpTestTree(); } } diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 4fa511f63dbdd..514b6879a9f6b 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -175,7 +175,7 @@ PhaseStatus Compiler::fgRemoveEmptyFinally() nextBlock = leaveBlock->bbNext; leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS; - fgRemoveBlock(leaveBlock, true); + fgRemoveBlock(leaveBlock, /* unreachable */ true); // Cleanup the postTryFinallyBlock fgCleanupContinuation(postTryFinallyBlock); @@ -194,8 +194,8 @@ PhaseStatus Compiler::fgRemoveEmptyFinally() firstBlock->bbRefs = 0; // Remove the handler block. - const bool unreachable = true; firstBlock->bbFlags &= ~BBF_DONT_REMOVE; + constexpr bool unreachable = true; fgRemoveBlock(firstBlock, unreachable); // Find enclosing try region for the try, if any, and update @@ -1181,7 +1181,7 @@ PhaseStatus Compiler::fgCloneFinally() nextBlock = leaveBlock->bbNext; leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS; - fgRemoveBlock(leaveBlock, true); + fgRemoveBlock(leaveBlock, /* unreachable */ true); // Make sure iteration isn't going off the deep end. assert(leaveBlock != endCallFinallyRangeBlock); diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index aaf40cefbfd13..53566eb17de7b 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -47,7 +47,9 @@ unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo) // This inline candidate has the same IL code buffer as an already // inlined method does. inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE); - break; + + // No need to note CALLSITE_DEPTH we're already rejecting this candidate + return depth; } if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 361ff92ee8099..eebe8a8e8eff5 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -145,16 +145,16 @@ bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2) if (b1->bbNum > fgDomBBcount) { - noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND); + noway_assert(b1->KindIs(BBJ_NONE, BBJ_ALWAYS, BBJ_COND)); - if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2)) + if (b1->KindIs(BBJ_NONE, BBJ_COND) && fgReachable(b1->bbNext, b2)) { return true; } - if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND) + if (b1->KindIs(BBJ_ALWAYS, BBJ_COND) && fgReachable(b1->bbJumpDest, b2)) { - return fgReachable(b1->bbJumpDest, b2); + return true; } return false; @@ -445,8 +445,7 @@ bool Compiler::fgRemoveUnreachableBlocks() else if (block == genReturnBB) { // Don't remove statements for the genReturnBB block, as we might have special hookups there. - // For example, in VSW 364383, - // the profiler hookup needs to have the "void GT_RETURN" statement + // For example, the profiler hookup needs to have the "void GT_RETURN" statement // to properly set the info.compProfilerCallback flag. continue; } @@ -478,10 +477,9 @@ bool Compiler::fgRemoveUnreachableBlocks() if (block->bbFlags & BBF_DONT_REMOVE) { - bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair(); + const bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair(); - /* Unmark the block as removed, */ - /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */ + // Unmark the block as removed, clear BBF_INTERNAL, and set BBJ_IMPORTED // The successors may be unreachable after this change. changed |= block->NumSucc() > 0; @@ -518,7 +516,7 @@ bool Compiler::fgRemoveUnreachableBlocks() if (block->bbFlags & BBF_REMOVED) { - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); // TODO: couldn't we have fgRemoveBlock() return the block after the (last)one removed // so we don't need the code below? @@ -2285,8 +2283,7 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) { // genReturnBB should never be removed, as we might have special hookups there. // Therefore, we should never come here to remove the statements in the genReturnBB block. - // For example, in VSW 364383, - // the profiler hookup needs to have the "void GT_RETURN" statement + // For example, the profiler hookup needs to have the "void GT_RETURN" statement // to properly set the info.compProfilerCallback flag. noway_assert(block != genReturnBB); @@ -2308,10 +2305,7 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) assert(!block->isBBCallAlwaysPairTail()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair #endif - /* First walk the statement trees in this basic block and delete each stmt */ - - /* Make the block publicly available */ - compCurBB = block; + // First, delete all the code in the block. if (block->IsLIR()) { @@ -2343,13 +2337,13 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) noway_assert(block->bbStmtList == nullptr); } - /* Next update the loop table and bbWeights */ + // Next update the loop table and bbWeights optUpdateLoopsBeforeRemoveBlock(block); - /* Mark the block as removed */ + // Mark the block as removed block->bbFlags |= BBF_REMOVED; - /* update bbRefs and bbPreds for the blocks reached by this block */ + // Update bbRefs and bbPreds for the blocks reached by this block fgRemoveBlockAsPred(block); } @@ -2825,7 +2819,7 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) /* Remove the block */ compCurBB = block; - fgRemoveBlock(block, false); + fgRemoveBlock(block, /* unreachable */ false); return true; default: @@ -3549,7 +3543,7 @@ bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* // bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev) { - assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS); + assert(block->KindIs(BBJ_COND, BBJ_ALWAYS)); assert(block->bbJumpDest == bNext); assert(block->bbNext == bNext); assert(block->bbPrev == bPrev); @@ -4604,7 +4598,7 @@ bool Compiler::fgReorderBlocks() bool backwardBranch = false; // Setup bDest - if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS)) + if (bPrev->KindIs(BBJ_COND, BBJ_ALWAYS)) { bDest = bPrev->bbJumpDest; forwardBranch = fgIsForwardBranch(bPrev); @@ -4854,8 +4848,7 @@ bool Compiler::fgReorderBlocks() // to bTmp (which is a higher weighted block) then it is better to keep out current // candidateBlock and have it fall into bTmp // - if ((candidateBlock == nullptr) || - ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) || + if ((candidateBlock == nullptr) || !candidateBlock->KindIs(BBJ_COND, BBJ_ALWAYS) || (candidateBlock->bbJumpDest != bTmp)) { // otherwise we have a new candidateBlock @@ -5796,7 +5789,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) // Remove JUMPS to the following block // and optimize any JUMPS to JUMPS - if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS) + if (block->KindIs(BBJ_COND, BBJ_ALWAYS)) { bDest = block->bbJumpDest; if (bDest == bNext) @@ -5935,7 +5928,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) // Add fall through fixup block, if needed. // - if ((bDest->bbJumpKind == BBJ_NONE) || (bDest->bbJumpKind == BBJ_COND)) + if (bDest->KindIs(BBJ_NONE, BBJ_COND)) { BasicBlock* const bFixup = fgNewBBafter(BBJ_ALWAYS, bDest, true); bFixup->inheritWeight(bDestNext); @@ -6109,7 +6102,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) /* no references -> unreachable - remove it */ /* For now do not update the bbNum, do it at the end */ - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); change = true; modified = true; @@ -6127,7 +6120,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) case BBJ_ALWAYS: if (block->bbJumpDest == block) { - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); change = true; modified = true; diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index f94cb8615be40..34ab390a9b899 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -1721,12 +1721,23 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod() // jitting on PGO. If we ever implement a broader pattern of deferral -- say deferring // based on static PGO -- we will need to reconsider. // + // Under OSR stress we may add patchpoints even without backedges. So we also + // need to change the PGO instrumetation approach if OSR stress is enabled. + // CLANG_FORMAT_COMMENT_ANCHOR; +#if defined(DEBUG) + const bool mayHaveStressPatchpoints = + (JitConfig.JitOffsetOnStackReplacement() >= 0) || (JitConfig.JitRandomOnStackReplacement() > 0); +#else + const bool mayHaveStressPatchpoints = false; +#endif + + const bool mayHavePatchpoints = + (JitConfig.TC_OnStackReplacement() > 0) && (compHasBackwardJump || mayHaveStressPatchpoints); const bool prejit = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT); - const bool tier0WithPatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && - (JitConfig.TC_OnStackReplacement() > 0) && compHasBackwardJump; - const bool osrMethod = opts.IsOSR(); + const bool tier0WithPatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && mayHavePatchpoints; + const bool osrMethod = opts.IsOSR(); const bool useEdgeProfiles = (JitConfig.JitEdgeProfiling() > 0) && !prejit && !tier0WithPatchpoints && !osrMethod; if (useEdgeProfiles) @@ -3417,7 +3428,7 @@ weight_t Compiler::fgComputeMissingBlockWeights() // Sum up the weights of all of the return blocks and throw blocks // This is used when we have a back-edge into block 1 // - if (bDst->hasProfileWeight() && ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW))) + if (bDst->hasProfileWeight() && bDst->KindIs(BBJ_RETURN, BBJ_THROW)) { returnWeight += bDst->bbWeight; } @@ -3988,7 +3999,7 @@ void Compiler::fgDebugCheckProfileData() // Exit blocks // - if ((block->bbJumpKind == BBJ_RETURN) || (block->bbJumpKind == BBJ_THROW)) + if (block->KindIs(BBJ_RETURN, BBJ_THROW)) { exitWeight += blockWeight; exitProfiled = true; @@ -4157,7 +4168,7 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block) // We won't check finally or filter returns (for now). // - if ((block->bbJumpKind == BBJ_EHFINALLYRET) || (block->bbJumpKind == BBJ_EHFILTERRET)) + if (block->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET)) { return true; } diff --git a/src/coreclr/jit/fgstmt.cpp b/src/coreclr/jit/fgstmt.cpp index 24140b3fc52b9..f5f07399a1d37 100644 --- a/src/coreclr/jit/fgstmt.cpp +++ b/src/coreclr/jit/fgstmt.cpp @@ -182,7 +182,7 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt) // This routine can only be used when in tree order. assert(fgOrder == FGOrderTree); - if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN)) + if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN)) { Statement* firstStmt = block->firstStmt(); noway_assert(firstStmt != nullptr); diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 188e44ab7f7f6..e2786ce57d820 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -67,7 +67,6 @@ static bool blockNeedsGCPoll(BasicBlock* block) // Returns: // PhaseStatus indicating what, if anything, was changed. // - PhaseStatus Compiler::fgInsertGCPolls() { PhaseStatus result = PhaseStatus::MODIFIED_NOTHING; @@ -108,23 +107,8 @@ PhaseStatus Compiler::fgInsertGCPolls() // the test. // If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block. - CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef DEBUG - switch (block->bbJumpKind) - { - case BBJ_RETURN: - case BBJ_ALWAYS: - case BBJ_COND: - case BBJ_SWITCH: - case BBJ_NONE: - case BBJ_THROW: - case BBJ_CALLFINALLY: - break; - default: - assert(!"Unexpected block kind"); - } -#endif // DEBUG + assert(block->KindIs(BBJ_RETURN, BBJ_ALWAYS, BBJ_COND, BBJ_SWITCH, BBJ_NONE, BBJ_THROW, BBJ_CALLFINALLY)); GCPollType pollType = GCPOLL_INLINE; @@ -196,13 +180,6 @@ PhaseStatus Compiler::fgInsertGCPolls() constexpr bool computeDoms = false; fgUpdateChangedFlowGraph(computePreds, computeDoms); } -#ifdef DEBUG - if (verbose) - { - printf("*************** After fgInsertGCPolls()\n"); - fgDispBasicBlocks(true); - } -#endif // DEBUG return result; } @@ -245,10 +222,9 @@ BasicBlock* Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block) createdPollBlocks = false; Statement* newStmt = nullptr; - if ((block->bbJumpKind == BBJ_ALWAYS) || (block->bbJumpKind == BBJ_CALLFINALLY) || - (block->bbJumpKind == BBJ_NONE)) + if (block->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_NONE)) { - // For BBJ_ALWAYS, BBJ_CALLFINALLY, and BBJ_NONE and we don't need to insert it before the condition. + // For BBJ_ALWAYS, BBJ_CALLFINALLY, and BBJ_NONE we don't need to insert it before the condition. // Just append it. newStmt = fgNewStmtAtEnd(block, call); } @@ -3109,6 +3085,9 @@ void Compiler::fgSimpleLowering() fgDispHandlerTab(); printf("\n"); } + + fgDebugCheckBBlist(); + fgDebugCheckLinks(); #endif } @@ -3390,7 +3369,7 @@ void Compiler::fgCreateFunclets() * or are rarely executed. */ -void Compiler::fgDetermineFirstColdBlock() +PhaseStatus Compiler::fgDetermineFirstColdBlock() { #ifdef DEBUG if (verbose) @@ -3404,19 +3383,19 @@ void Compiler::fgDetermineFirstColdBlock() // assert(fgSafeBasicBlockCreation); - fgFirstColdBlock = nullptr; + assert(fgFirstColdBlock == nullptr); if (!opts.compProcedureSplitting) { JITDUMP("No procedure splitting will be done for this method\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #ifdef DEBUG if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH) { JITDUMP("No procedure splitting will be done for this method with EH (by request)\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #endif // DEBUG @@ -3427,7 +3406,7 @@ void Compiler::fgDetermineFirstColdBlock() if (compHndBBtabCount > 0) { JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #endif // FEATURE_EH_FUNCLETS @@ -3498,7 +3477,7 @@ void Compiler::fgDetermineFirstColdBlock() if (prevToFirstColdBlock == nullptr) { - return; // To keep Prefast happy + return PhaseStatus::MODIFIED_EVERYTHING; // To keep Prefast happy } // If we only have one cold block @@ -3594,14 +3573,12 @@ EXIT:; { printf("fgFirstColdBlock is NULL.\n"); } - - fgDispBasicBlocks(); } - - fgVerifyHandlerTab(); #endif // DEBUG fgFirstColdBlock = firstColdBlock; + + return PhaseStatus::MODIFIED_EVERYTHING; } /* static */ @@ -3926,33 +3903,6 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR) return; } - // Special handling for dynamic block ops. - if (tree->OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK)) - { - GenTreeDynBlk* dynBlk = tree->AsDynBlk(); - GenTree* sizeNode = dynBlk->gtDynamicSize; - GenTree* dstAddr = dynBlk->Addr(); - GenTree* src = dynBlk->Data(); - bool isReverse = dynBlk->IsReverseOp(); - - // We either have a DYN_BLK or a STORE_DYN_BLK. If the latter, we have a - // src (the Data to be stored), and isReverse tells us whether to evaluate - // that before dstAddr. - if (isReverse && (src != nullptr)) - { - fgSetTreeSeqHelper(src, isLIR); - } - fgSetTreeSeqHelper(dstAddr, isLIR); - if (!isReverse && (src != nullptr)) - { - fgSetTreeSeqHelper(src, isLIR); - } - fgSetTreeSeqHelper(sizeNode, isLIR); - - fgSetTreeSeqFinish(dynBlk, isLIR); - return; - } - /* Is it a 'simple' unary/binary operator? */ if (kind & GTK_SMPOP) @@ -4124,8 +4074,9 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR) break; case GT_STORE_DYN_BLK: - case GT_DYN_BLK: - noway_assert(!"DYN_BLK nodes should be sequenced as a special case"); + fgSetTreeSeqHelper(tree->AsStoreDynBlk()->Addr(), isLIR); + fgSetTreeSeqHelper(tree->AsStoreDynBlk()->Data(), isLIR); + fgSetTreeSeqHelper(tree->AsStoreDynBlk()->gtDynamicSize, isLIR); break; default: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 280c2f7087590..35b9d2d829ca4 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -258,7 +258,6 @@ void GenTree::InitNodeSize() GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE; GenTree::s_gtNodeSizes[GT_CMPXCHG] = TREE_NODE_SZ_LARGE; GenTree::s_gtNodeSizes[GT_QMARK] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_DYN_BLK] = TREE_NODE_SZ_LARGE; GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK] = TREE_NODE_SZ_LARGE; GenTree::s_gtNodeSizes[GT_INTRINSIC] = TREE_NODE_SZ_LARGE; GenTree::s_gtNodeSizes[GT_ALLOCOBJ] = TREE_NODE_SZ_LARGE; @@ -320,7 +319,7 @@ void GenTree::InitNodeSize() static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeObj) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeStoreDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeILOffset) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeClsVar) <= TREE_NODE_SZ_SMALL); @@ -1609,10 +1608,9 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) Compare(op1->AsCmpXchg()->gtOpComparand, op2->AsCmpXchg()->gtOpComparand); case GT_STORE_DYN_BLK: - case GT_DYN_BLK: - return Compare(op1->AsDynBlk()->Addr(), op2->AsDynBlk()->Addr()) && - Compare(op1->AsDynBlk()->Data(), op2->AsDynBlk()->Data()) && - Compare(op1->AsDynBlk()->gtDynamicSize, op2->AsDynBlk()->gtDynamicSize); + return Compare(op1->AsStoreDynBlk()->Addr(), op2->AsStoreDynBlk()->Addr()) && + Compare(op1->AsStoreDynBlk()->Data(), op2->AsStoreDynBlk()->Data()) && + Compare(op1->AsStoreDynBlk()->gtDynamicSize, op2->AsStoreDynBlk()->gtDynamicSize); default: assert(!"unexpected operator"); @@ -2073,11 +2071,9 @@ unsigned Compiler::gtHashValue(GenTree* tree) break; case GT_STORE_DYN_BLK: - hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->Data())); - FALLTHROUGH; - case GT_DYN_BLK: - hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->Addr())); - hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->gtDynamicSize)); + hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Data())); + hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Addr())); + hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->gtDynamicSize)); break; default: @@ -4136,7 +4132,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) case GT_IND: case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: // In an indirection, the destination address is evaluated prior to the source. // If we have any side effects on the target indirection, @@ -4181,6 +4176,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) case GT_LCL_VAR: case GT_LCL_FLD: + case GT_CLS_VAR: // We evaluate op2 before op1 bReverseInAssignment = true; @@ -4645,23 +4641,19 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) break; case GT_STORE_DYN_BLK: - case GT_DYN_BLK: - level = gtSetEvalOrder(tree->AsDynBlk()->Addr()); - costEx = tree->AsDynBlk()->Addr()->GetCostEx(); - costSz = tree->AsDynBlk()->Addr()->GetCostSz(); + level = gtSetEvalOrder(tree->AsStoreDynBlk()->Addr()); + costEx = tree->AsStoreDynBlk()->Addr()->GetCostEx(); + costSz = tree->AsStoreDynBlk()->Addr()->GetCostSz(); - if (oper == GT_STORE_DYN_BLK) - { - lvl2 = gtSetEvalOrder(tree->AsDynBlk()->Data()); - level = max(level, lvl2); - costEx += tree->AsDynBlk()->Data()->GetCostEx(); - costSz += tree->AsDynBlk()->Data()->GetCostSz(); - } + lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->Data()); + level = max(level, lvl2); + costEx += tree->AsStoreDynBlk()->Data()->GetCostEx(); + costSz += tree->AsStoreDynBlk()->Data()->GetCostSz(); - lvl2 = gtSetEvalOrder(tree->AsDynBlk()->gtDynamicSize); + lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->gtDynamicSize); level = max(level, lvl2); - costEx += tree->AsDynBlk()->gtDynamicSize->GetCostEx(); - costSz += tree->AsDynBlk()->gtDynamicSize->GetCostSz(); + costEx += tree->AsStoreDynBlk()->gtDynamicSize->GetCostEx(); + costSz += tree->AsStoreDynBlk()->gtDynamicSize->GetCostSz(); break; default: @@ -4965,25 +4957,9 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse) return false; } - case GT_DYN_BLK: - { - GenTreeDynBlk* const dynBlock = this->AsDynBlk(); - if (operand == dynBlock->gtOp1) - { - *pUse = &dynBlock->gtOp1; - return true; - } - if (operand == dynBlock->gtDynamicSize) - { - *pUse = &dynBlock->gtDynamicSize; - return true; - } - return false; - } - case GT_STORE_DYN_BLK: { - GenTreeDynBlk* const dynBlock = this->AsDynBlk(); + GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk(); if (operand == dynBlock->gtOp1) { *pUse = &dynBlock->gtOp1; @@ -5184,7 +5160,8 @@ GenTree* GenTree::gtRetExprVal(BasicBlockFlags* pbbFlags /* = nullptr */) bool GenTree::OperRequiresAsgFlag() { - if (OperIs(GT_ASG) || OperIs(GT_XADD, GT_XORR, GT_XAND, GT_XCHG, GT_LOCKADD, GT_CMPXCHG, GT_MEMORYBARRIER)) + if (OperIs(GT_ASG, GT_STORE_DYN_BLK) || + OperIs(GT_XADD, GT_XORR, GT_XAND, GT_XCHG, GT_LOCKADD, GT_CMPXCHG, GT_MEMORYBARRIER)) { return true; } @@ -5250,7 +5227,7 @@ bool GenTree::OperRequiresCallFlag(Compiler* comp) // Return Value: // True if the given node contains an implicit indirection // -// Note that for the GT_HWINTRINSIC node we have to examine the +// Note that for the [HW]INTRINSIC nodes we have to examine the // details of the node to determine its result. // @@ -5266,7 +5243,6 @@ bool GenTree::OperIsImplicitIndir() const case GT_CMPXCHG: case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: case GT_STORE_BLK: case GT_STORE_OBJ: case GT_STORE_DYN_BLK: @@ -5275,6 +5251,8 @@ bool GenTree::OperIsImplicitIndir() const case GT_ARR_ELEM: case GT_ARR_OFFSET: return true; + case GT_INTRINSIC: + return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType; #ifdef FEATURE_SIMD case GT_SIMD: { @@ -5331,18 +5309,8 @@ bool GenTree::OperMayThrow(Compiler* comp) case GT_INTRINSIC: // If this is an intrinsic that represents the object.GetType(), it can throw an NullReferenceException. - // Report it as may throw. - // Note: Some of the rest of the existing intrinsics could potentially throw an exception (for example - // the array and string element access ones). They are handled differently than the GetType intrinsic - // and are not marked with GTF_EXCEPT. If these are revisited at some point to be marked as - // GTF_EXCEPT, - // the code below might need to be specialized to handle them properly. - if ((this->gtFlags & GTF_EXCEPT) != 0) - { - return true; - } - - break; + // Currently, this is the only intrinsic that can throw an exception. + return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType; case GT_CALL: @@ -5353,9 +5321,9 @@ bool GenTree::OperMayThrow(Compiler* comp) case GT_IND: case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: - case GT_STORE_BLK: case GT_NULLCHECK: + case GT_STORE_BLK: + case GT_STORE_DYN_BLK: return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsIndir()->Addr())); case GT_ARR_LENGTH: @@ -6827,24 +6795,19 @@ void Compiler::gtBlockOpInit(GenTree* result, GenTree* dst, GenTree* srcOrFillVa // gtNewBlkOpNode: Creates a GenTree for a block (struct) assignment. // // Arguments: -// dst - Destination or target to copy to / initialize the buffer. -// srcOrFillVall - the size of the buffer to copy/initialize or zero, in the case of CpObj. +// dst - The destination node: local var / block node. +// srcOrFillVall - The value to assign for CopyBlk, the integer "fill" for InitBlk // isVolatile - Whether this is a volatile memory operation or not. // isCopyBlock - True if this is a block copy (rather than a block init). // // Return Value: // Returns the newly constructed and initialized block operation. // -// Notes: -// If size is zero, the dst must be a GT_OBJ with the class handle. -// 'dst' must be a block node or lclVar. -// GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVolatile, bool isCopyBlock) { assert(dst->OperIsBlk() || dst->OperIsLocal()); if (isCopyBlock) { - srcOrFillVal->gtFlags |= GTF_DONT_CSE; if (srcOrFillVal->OperIsIndir() && (srcOrFillVal->gtGetOp1()->gtOper == GT_ADDR)) { srcOrFillVal = srcOrFillVal->gtGetOp1()->gtGetOp1(); @@ -7435,10 +7398,6 @@ GenTree* Compiler::gtCloneExpr( GenTreeBlk(GT_BLK, tree->TypeGet(), tree->AsBlk()->Addr(), tree->AsBlk()->GetLayout()); break; - case GT_DYN_BLK: - copy = new (this, GT_DYN_BLK) GenTreeDynBlk(tree->AsOp()->gtGetOp1(), tree->AsDynBlk()->gtDynamicSize); - break; - case GT_FIELD: copy = new (this, GT_FIELD) GenTreeField(tree->TypeGet(), tree->AsField()->GetFldObj(), tree->AsField()->gtFldHnd, tree->AsField()->gtFldOffset); @@ -7666,10 +7625,10 @@ GenTree* Compiler::gtCloneExpr( break; case GT_STORE_DYN_BLK: - case GT_DYN_BLK: copy = new (this, oper) - GenTreeDynBlk(gtCloneExpr(tree->AsDynBlk()->Addr(), addFlags, deepVarNum, deepVarVal), - gtCloneExpr(tree->AsDynBlk()->gtDynamicSize, addFlags, deepVarNum, deepVarVal)); + GenTreeStoreDynBlk(gtCloneExpr(tree->AsStoreDynBlk()->Addr(), addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->AsStoreDynBlk()->Data(), addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->AsStoreDynBlk()->gtDynamicSize, addFlags, deepVarNum, deepVarVal)); break; default: @@ -8353,20 +8312,10 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) m_advance = &GenTreeUseEdgeIterator::AdvanceArrOffset; return; - case GT_DYN_BLK: - m_edge = &m_node->AsDynBlk()->Addr(); - assert(*m_edge != nullptr); - m_advance = &GenTreeUseEdgeIterator::AdvanceDynBlk; - return; - case GT_STORE_DYN_BLK: - { - GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); - m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1; + m_edge = &m_node->AsStoreDynBlk()->Addr(); assert(*m_edge != nullptr); - m_advance = &GenTreeUseEdgeIterator::AdvanceStoreDynBlk; - } return; case GT_CALL: @@ -8444,28 +8393,16 @@ void GenTreeUseEdgeIterator::AdvanceArrOffset() assert(*m_edge != nullptr); } -//------------------------------------------------------------------------ -// GenTreeUseEdgeIterator::AdvanceDynBlk: produces the next operand of a DynBlk node and advances the state. -// -void GenTreeUseEdgeIterator::AdvanceDynBlk() -{ - GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); - - m_edge = &dynBlock->gtDynamicSize; - assert(*m_edge != nullptr); - m_advance = &GenTreeUseEdgeIterator::Terminate; -} - //------------------------------------------------------------------------ // GenTreeUseEdgeIterator::AdvanceStoreDynBlk: produces the next operand of a StoreDynBlk node and advances the state. // void GenTreeUseEdgeIterator::AdvanceStoreDynBlk() { - GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); + GenTreeStoreDynBlk* const dynBlock = m_node->AsStoreDynBlk(); switch (m_state) { case 0: - m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2; + m_edge = &dynBlock->Data(); m_state = 1; break; case 1: @@ -9257,7 +9194,6 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ case GT_LEA: case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: case GT_STORE_BLK: case GT_STORE_OBJ: case GT_STORE_DYN_BLK: @@ -10824,6 +10760,9 @@ void Compiler::gtDispTree(GenTree* tree, case NI_System_Object_GetType: printf(" objGetType"); break; + case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: + printf(" isKnownConst"); + break; default: unreached(); @@ -11073,7 +11012,6 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_STORE_DYN_BLK: - case GT_DYN_BLK: if (tree->OperIsCopyBlkOp()) { printf(" (copy)"); @@ -11086,12 +11024,12 @@ void Compiler::gtDispTree(GenTree* tree, if (!topOnly) { - if (tree->AsDynBlk()->Data() != nullptr) + gtDispChild(tree->AsStoreDynBlk()->Addr(), indentStack, IIArc, nullptr, topOnly); + if (tree->AsStoreDynBlk()->Data() != nullptr) { - gtDispChild(tree->AsDynBlk()->Data(), indentStack, IIArc, nullptr, topOnly); + gtDispChild(tree->AsStoreDynBlk()->Data(), indentStack, IIArc, nullptr, topOnly); } - gtDispChild(tree->AsDynBlk()->Addr(), indentStack, IIArc, nullptr, topOnly); - gtDispChild(tree->AsDynBlk()->gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly); + gtDispChild(tree->AsStoreDynBlk()->gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly); } break; @@ -11484,7 +11422,7 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr * displayOperand(operand, buf, operandArc, indentStack, prefixIndent); } } - else if (node->OperIsDynBlkOp()) + else if (node->OperIs(GT_STORE_DYN_BLK)) { if (operand == node->AsBlk()->Addr()) { @@ -11496,19 +11434,7 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr * } else { - assert(operand == node->AsDynBlk()->gtDynamicSize); - displayOperand(operand, "size", operandArc, indentStack, prefixIndent); - } - } - else if (node->OperGet() == GT_DYN_BLK) - { - if (operand == node->AsBlk()->Addr()) - { - displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent); - } - else - { - assert(operand == node->AsDynBlk()->gtDynamicSize); + assert(operand == node->AsStoreDynBlk()->gtDynamicSize); displayOperand(operand, "size", operandArc, indentStack, prefixIndent); } } @@ -14541,14 +14467,14 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags) { if (flags & GTF_ASG) { - // TODO-Cleanup: This only checks for GT_ASG but according to OperRequiresAsgFlag there - // are many more opers that are considered to have an assignment side effect: atomic ops + // TODO-Bug: This only checks for GT_ASG/GT_STORE_DYN_BLK but according to OperRequiresAsgFlag + // there are many more opers that are considered to have an assignment side effect: atomic ops // (GT_CMPXCHG & co.), GT_MEMORYBARRIER (not classified as an atomic op) and HW intrinsic // memory stores. Atomic ops have special handling in gtExtractSideEffList but the others // will simply be dropped is they are ever subject to an "extract side effects" operation. // It is possible that the reason no bugs have yet been observed in this area is that the // other nodes are likely to always be tree roots. - if (tree->OperIs(GT_ASG)) + if (tree->OperIs(GT_ASG, GT_STORE_DYN_BLK)) { return true; } @@ -15274,33 +15200,21 @@ bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bo GenTree* destAddr = blkNode->Addr(); unsigned width = blkNode->Size(); // Do we care about whether this assigns the entire variable? - if (pIsEntire != nullptr && blkNode->OperIs(GT_DYN_BLK)) + if (pIsEntire != nullptr && blkNode->OperIs(GT_STORE_DYN_BLK)) { - GenTree* blockWidth = blkNode->AsDynBlk()->gtDynamicSize; + GenTree* blockWidth = blkNode->AsStoreDynBlk()->gtDynamicSize; if (blockWidth->IsCnsIntOrI()) { - if (blockWidth->IsIconHandle()) - { - // If it's a handle, it must be a class handle. We only create such block operations - // for initialization of struct types, so the type of the argument(s) will match this - // type, by construction, and be "entire". - assert(blockWidth->IsIconHandle(GTF_ICON_CLASS_HDL)); - width = comp->info.compCompHnd->getClassSize( - CORINFO_CLASS_HANDLE(blockWidth->AsIntConCommon()->IconValue())); - } - else + assert(blockWidth->AsIntConCommon()->FitsInI32()); + width = static_cast(blockWidth->AsIntConCommon()->IconValue()); + + if (width == 0) { - ssize_t swidth = blockWidth->AsIntConCommon()->IconValue(); - assert(swidth >= 0); - // cpblk of size zero exists in the wild (in yacc-generated code in SQL) and is valid IL. - if (swidth == 0) - { - return false; - } - width = unsigned(swidth); + return false; } } } + return destAddr->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire); } // Otherwise... @@ -15930,26 +15844,26 @@ bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp) // this: ADD(CONST FldSeq, baseAddr) // // Arguments: -// comp - the Compiler object -// pObj - [out] parameter for instance fields, the object reference -// pStatic - [out] parameter for static fields, the base address -// pFldSeq - [out] parameter for the field sequence +// comp - the Compiler object +// pBaseAddr - [out] parameter for "the base address" +// pFldSeq - [out] parameter for the field sequence // // Return Value: // If "this" matches patterns denoted above, and the FldSeq found is "full", // i. e. starts with a class field or a static field, and includes all the // struct fields that this tree represents the address of, this method will -// return "true" and set either "pObj" or "pStatic" to some value, which must -// be used by the caller as the key into the "first field map" to obtain the -// actual value for the field. +// return "true" and set either "pBaseAddr" to some value, which must be used +// by the caller as the key into the "first field map" to obtain the actual +// value for the field. For instance fields, "base address" will be the object +// reference, for statics - the address to which the field offset with the +// field sequence is added, see "impImportStaticFieldAccess" and "fgMorphField". // -bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq) +bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeqNode** pFldSeq) { assert(TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF)); - *pObj = nullptr; - *pStatic = nullptr; - *pFldSeq = FieldSeqStore::NotAField(); + *pBaseAddr = nullptr; + *pFldSeq = FieldSeqStore::NotAField(); GenTree* baseAddr = nullptr; FieldSeqNode* fldSeq = nullptr; @@ -16006,8 +15920,8 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, Fie // TODO-VNTypes: we will always return the "baseAddr" here for now, but strictly speaking, // we only need to do that if we have a shared field, to encode the logical "instantiation" // argument. In all other cases, this serves no purpose and just leads to redundant maps. - *pStatic = baseAddr; - *pFldSeq = fldSeq; + *pBaseAddr = baseAddr; + *pFldSeq = fldSeq; return true; } @@ -16015,8 +15929,8 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, Fie { assert(!comp->eeIsValueClass(comp->info.compCompHnd->getFieldClass(fldSeq->GetFieldHandle()))); - *pObj = baseAddr; - *pFldSeq = fldSeq; + *pBaseAddr = baseAddr; + *pFldSeq = fldSeq; return true; } @@ -17732,6 +17646,20 @@ bool GenTree::isContainableHWIntrinsic() const return true; } + default: + { + return false; + } + } +#elif TARGET_ARM64 + switch (AsHWIntrinsic()->GetHWIntrinsicId()) + { + case NI_Vector64_get_Zero: + case NI_Vector128_get_Zero: + { + return true; + } + default: { return false; @@ -17931,7 +17859,7 @@ GenTree* Compiler::gtNewSimdAbsNode( if ((simdBaseType != TYP_LONG) && ((simdSize == 32) || compOpportunisticallyDependsOn(InstructionSet_SSSE3))) { NamedIntrinsic intrinsic = (simdSize == 32) ? NI_AVX2_Abs : NI_SSSE3_Abs; - return gtNewSimdAsHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); + return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); } else { @@ -19359,20 +19287,22 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; -#if defined(TARGET_XARCH) - if (simdSize == 32) - { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - } -#endif // TARGET_XARCH - switch (op) { #if defined(TARGET_XARCH) case GT_EQ: { - intrinsic = (simdSize == 32) ? NI_Vector256_op_Equality : NI_Vector128_op_Equality; + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Equality; + } + else + { + intrinsic = NI_Vector128_op_Equality; + } break; } @@ -19388,6 +19318,12 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, if (simdSize == 32) { + // TODO-XArch-CQ: It's a non-trivial amount of work to support these + // for floating-point while only utilizing AVX. It would require, among + // other things, inverting the comparison and potentially support for a + // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + intrinsic = NI_Vector256_op_Equality; getAllBitsSet = NI_Vector256_get_AllBitsSet; } @@ -19397,7 +19333,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, getAllBitsSet = NI_Vector128_get_AllBitsSet; } - op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); if (simdBaseType == TYP_FLOAT) @@ -19411,7 +19347,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, simdBaseJitType = CORINFO_TYPE_LONG; } - op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize); + op2 = gtNewSimdHWIntrinsicNode(simdType, getAllBitsSet, simdBaseJitType, simdSize); break; } #elif defined(TARGET_ARM64) @@ -19442,7 +19378,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, getAllBitsSet = NI_Vector128_get_AllBitsSet; } - op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); if (simdBaseType == TYP_FLOAT) @@ -19456,7 +19392,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, simdBaseJitType = CORINFO_TYPE_LONG; } - op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize); + op2 = gtNewSimdHWIntrinsicNode(simdType, getAllBitsSet, simdBaseJitType, simdSize); break; } #else @@ -19498,14 +19434,6 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; -#if defined(TARGET_XARCH) - if (simdSize == 32) - { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - } -#endif // TARGET_XARCH - switch (op) { #if defined(TARGET_XARCH) @@ -19518,9 +19446,22 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, // We want to generate a comparison along the lines of // GT_XX(op1, op2).As() != Vector128.Zero - intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; + if (simdSize == 32) + { + // TODO-XArch-CQ: It's a non-trivial amount of work to support these + // for floating-point while only utilizing AVX. It would require, among + // other things, inverting the comparison and potentially support for a + // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Inequality; + } + else + { + intrinsic = NI_Vector128_op_Inequality; + } - op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); if (simdBaseType == TYP_FLOAT) @@ -19534,13 +19475,23 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, simdBaseJitType = CORINFO_TYPE_LONG; } - op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + op2 = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); break; } case GT_NE: { - intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Inequality; + } + else + { + intrinsic = NI_Vector128_op_Inequality; + } break; } #elif defined(TARGET_ARM64) @@ -19555,7 +19506,7 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, intrinsic = (simdSize == 8) ? NI_Vector64_op_Inequality : NI_Vector128_op_Inequality; - op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); if (simdBaseType == TYP_FLOAT) @@ -19569,7 +19520,7 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, simdBaseJitType = CORINFO_TYPE_LONG; } - op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + op2 = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); break; } @@ -19642,7 +19593,8 @@ GenTree* Compiler::gtNewSimdCndSelNode(var_types type, // result = op2 | op3 return gtNewSimdBinOpNode(GT_OR, type, op2, op3, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); #elif defined(TARGET_ARM64) - return gtNewSimdAsHWIntrinsicNode(type, op1, op2, op3, NI_AdvSimd_BitwiseSelect, simdBaseJitType, simdSize); + return gtNewSimdHWIntrinsicNode(type, op1, op2, op3, NI_AdvSimd_BitwiseSelect, simdBaseJitType, simdSize, + isSimdAsHWIntrinsic); #else #error Unsupported platform #endif // !TARGET_XARCH && !TARGET_ARM64 @@ -19701,7 +19653,7 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types type, assert(op2->TypeIs(simdType)); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); - assert(genActualType(simdBaseType) == type); + assert(JITtype2varType(simdBaseJitType) == type); NamedIntrinsic intrinsic = NI_Illegal; @@ -20734,7 +20686,7 @@ GenTree* Compiler::gtNewSimdSumNode( for (int i = 0; i < haddCount; i++) { op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for vector sum")); - op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, intrinsic, simdBaseJitType, simdSize); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, intrinsic, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); } if (simdSize == 32) @@ -20742,14 +20694,15 @@ GenTree* Compiler::gtNewSimdSumNode( intrinsic = (simdBaseType == TYP_FLOAT) ? NI_SSE_Add : NI_SSE2_Add; op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for vector sum")); - op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD16, op1, gtNewIconNode(0x01, TYP_INT), NI_AVX_ExtractVector128, - simdBaseJitType, simdSize); + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, gtNewIconNode(0x01, TYP_INT), NI_AVX_ExtractVector128, + simdBaseJitType, simdSize, isSimdAsHWIntrinsic); - tmp = gtNewSimdAsHWIntrinsicNode(simdType, tmp, NI_Vector256_GetLower, simdBaseJitType, simdSize); - op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD16, op1, tmp, intrinsic, simdBaseJitType, 16); + tmp = gtNewSimdHWIntrinsicNode(simdType, tmp, NI_Vector256_GetLower, simdBaseJitType, simdSize, + isSimdAsHWIntrinsic); + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, tmp, intrinsic, simdBaseJitType, 16, isSimdAsHWIntrinsic); } - return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize); + return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); #elif defined(TARGET_ARM64) switch (simdBaseType) { @@ -20757,34 +20710,64 @@ GenTree* Compiler::gtNewSimdSumNode( case TYP_UBYTE: case TYP_SHORT: case TYP_USHORT: + { + tmp = gtNewSimdHWIntrinsicNode(simdType, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize, + isSimdAsHWIntrinsic); + return gtNewSimdHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic); + } + case TYP_INT: case TYP_UINT: { - tmp = gtNewSimdAsHWIntrinsicNode(simdType, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize); - return gtNewSimdAsHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8); + if (simdSize == 8) + { + op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector sum")); + tmp = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_AddPairwise, simdBaseJitType, simdSize, + isSimdAsHWIntrinsic); + } + else + { + tmp = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, 16, + isSimdAsHWIntrinsic); + } + return gtNewSimdHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic); } + case TYP_FLOAT: { - unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType); - int haddCount = genLog2(vectorLength); - - for (int i = 0; i < haddCount; i++) + if (simdSize == 8) { - op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, - nullptr DEBUGARG("Clone op1 for vector sum")); - op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType, - simdSize); + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType, + simdSize, isSimdAsHWIntrinsic); } + else + { + unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType); + int haddCount = genLog2(vectorLength); - return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize); + for (int i = 0; i < haddCount; i++) + { + op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector sum")); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType, + simdSize, isSimdAsHWIntrinsic); + } + } + return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize, + isSimdAsHWIntrinsic); } + case TYP_DOUBLE: case TYP_LONG: case TYP_ULONG: { - op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType, - simdSize); - return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector64_ToScalar, simdBaseJitType, 8); + if (simdSize == 16) + { + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType, + simdSize, isSimdAsHWIntrinsic); + } + return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic); } default: { @@ -21397,7 +21380,9 @@ GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode( bool GenTreeHWIntrinsic::OperIsMemoryLoad() const { #if defined(TARGET_XARCH) || defined(TARGET_ARM64) - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(GetHWIntrinsicId()); + NamedIntrinsic intrinsicId = GetHWIntrinsicId(); + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); + if (category == HW_Category_MemoryLoad) { return true; @@ -21406,17 +21391,42 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad() const 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_SIMDScalar) + if ((category == HW_Category_SimpleSIMD) || (category == HW_Category_SIMDScalar)) { - // Avx2.BroadcastScalarToVector128/256 have vector and pointer overloads both, e.g., - // Vector128 BroadcastScalarToVector128(Vector128 value) - // Vector128 BroadcastScalarToVector128(byte* source) - // So, we need to check the argument's type is memory-reference or Vector128 assert(GetOperandCount() == 1); - return (GetHWIntrinsicId() == NI_AVX2_BroadcastScalarToVector128 || - GetHWIntrinsicId() == NI_AVX2_BroadcastScalarToVector256) && - !Op(1)->TypeIs(TYP_SIMD16); + + switch (intrinsicId) + { + case NI_SSE41_ConvertToVector128Int16: + case NI_SSE41_ConvertToVector128Int32: + case NI_SSE41_ConvertToVector128Int64: + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX2_ConvertToVector256Int16: + case NI_AVX2_ConvertToVector256Int32: + case NI_AVX2_ConvertToVector256Int64: + { + CorInfoType auxiliaryType = GetAuxiliaryJitType(); + + if (auxiliaryType == CORINFO_TYPE_PTR) + { + return true; + } + + assert(auxiliaryType == CORINFO_TYPE_UNDEF); + return false; + } + + default: + { + unreached(); + } + } } else if (category == HW_Category_IMM) { @@ -22015,8 +22025,7 @@ bool GenTreeLclFld::IsOffsetMisaligned() const bool GenTree::IsInvariant() const { - GenTree* lclVarTree = nullptr; - return OperIsConst() || Compiler::impIsAddressInLocal(this, &lclVarTree); + return OperIsConst() || Compiler::impIsAddressInLocal(this); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 3c5fff088cef1..085bc17a1e510 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1235,12 +1235,10 @@ struct GenTree bool OperIsBlkOp(); bool OperIsCopyBlkOp(); bool OperIsInitBlkOp(); - bool OperIsDynBlkOp(); static bool OperIsBlk(genTreeOps gtOper) { - return ((gtOper == GT_BLK) || (gtOper == GT_OBJ) || (gtOper == GT_DYN_BLK) || (gtOper == GT_STORE_BLK) || - (gtOper == GT_STORE_OBJ) || (gtOper == GT_STORE_DYN_BLK)); + return (gtOper == GT_BLK) || (gtOper == GT_OBJ) || OperIsStoreBlk(gtOper); } bool OperIsBlk() const @@ -1248,19 +1246,9 @@ struct GenTree return OperIsBlk(OperGet()); } - static bool OperIsDynBlk(genTreeOps gtOper) - { - return ((gtOper == GT_DYN_BLK) || (gtOper == GT_STORE_DYN_BLK)); - } - - bool OperIsDynBlk() const - { - return OperIsDynBlk(OperGet()); - } - static bool OperIsStoreBlk(genTreeOps gtOper) { - return ((gtOper == GT_STORE_BLK) || (gtOper == GT_STORE_OBJ) || (gtOper == GT_STORE_DYN_BLK)); + return StaticOperIs(gtOper, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYN_BLK); } bool OperIsStoreBlk() const @@ -1704,6 +1692,8 @@ struct GenTree inline bool IsIntegralConst(ssize_t constVal) const; inline bool IsIntegralConstVector(ssize_t constVal) const; inline bool IsSIMDZero() const; + inline bool IsFloatPositiveZero() const; + inline bool IsVectorZero() const; inline bool IsBoxedValue(); @@ -1917,7 +1907,7 @@ struct GenTree // where Y is an arbitrary tree, and X is a lclVar. unsigned IsLclVarUpdateTree(GenTree** otherTree, genTreeOps* updateOper); - bool IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq); + bool IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeqNode** pFldSeq); // Requires "this" to be the address of an array (the child of a GT_IND labeled with GTF_IND_ARR_INDEX). // Sets "pArr" to the node representing the array (either an array object pointer, or perhaps a byref to the some @@ -2076,9 +2066,14 @@ struct GenTree SetAllEffectsFlags(source->gtFlags & GTF_ALL_EFFECT); } - void SetAllEffectsFlags(GenTree* source, GenTree* otherSource) + void SetAllEffectsFlags(GenTree* firstSource, GenTree* secondSource) + { + SetAllEffectsFlags((firstSource->gtFlags | secondSource->gtFlags) & GTF_ALL_EFFECT); + } + + void SetAllEffectsFlags(GenTree* firstSource, GenTree* secondSource, GenTree* thirdSouce) { - SetAllEffectsFlags((source->gtFlags | otherSource->gtFlags) & GTF_ALL_EFFECT); + SetAllEffectsFlags((firstSource->gtFlags | secondSource->gtFlags | thirdSouce->gtFlags) & GTF_ALL_EFFECT); } void SetAllEffectsFlags(GenTreeFlags sourceFlags) @@ -2097,7 +2092,7 @@ struct GenTree inline bool IsCnsFltOrDbl() const; - inline bool IsCnsNonZeroFltOrDbl(); + inline bool IsCnsNonZeroFltOrDbl() const; bool IsIconHandle() const { @@ -2743,7 +2738,6 @@ class GenTreeUseEdgeIterator final void AdvanceCmpXchg(); void AdvanceArrElem(); void AdvanceArrOffset(); - void AdvanceDynBlk(); void AdvanceStoreDynBlk(); void AdvanceFieldList(); void AdvancePhi(); @@ -5983,8 +5977,6 @@ struct GenTreeAddrMode : public GenTreeOp struct GenTreeIndir : public GenTreeOp { // The address for the indirection. - // Since GenTreeDynBlk derives from this, but is an "EXOP" (i.e. it has extra fields), - // we can't access Op1 and Op2 in the normal manner if we may have a DynBlk. GenTree*& Addr() { return gtOp1; @@ -6051,7 +6043,7 @@ struct GenTreeBlk : public GenTreeIndir void SetLayout(ClassLayout* layout) { - assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK)); + assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); m_layout = layout; } @@ -6068,7 +6060,7 @@ struct GenTreeBlk : public GenTreeIndir // The size of the buffer to be copied. unsigned Size() const { - assert((m_layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK)); + assert((m_layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); return (m_layout != nullptr) ? m_layout->GetSize() : 0; } @@ -6106,7 +6098,7 @@ struct GenTreeBlk : public GenTreeIndir #endif { assert(OperIsBlk(oper)); - assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK)); + assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); gtFlags |= (addr->gtFlags & GTF_ALL_EFFECT); } @@ -6119,7 +6111,7 @@ struct GenTreeBlk : public GenTreeIndir #endif { assert(OperIsBlk(oper)); - assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK)); + assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); gtFlags |= (addr->gtFlags & GTF_ALL_EFFECT); gtFlags |= (data->gtFlags & GTF_ALL_EFFECT); } @@ -6168,28 +6160,33 @@ struct GenTreeObj : public GenTreeBlk #endif }; -// gtDynBlk -- 'dynamic block' (GT_DYN_BLK). +// GenTreeStoreDynBlk -- 'dynamic block store' (GT_STORE_DYN_BLK). // -// This node is used for block values that have a dynamic size. -// Note that such a value can never have GC pointers. - -struct GenTreeDynBlk : public GenTreeBlk +// This node is used to represent stores that have a dynamic size - the "cpblk" and "initblk" +// IL instructions are implemented with it. Note that such stores assume the input has no GC +// pointers in it, and as such do not ever use write barriers. +// +// The "Data()" member of this node will either be a "dummy" IND(struct) node, for "cpblk", or +// the zero constant/INIT_VAL for "initblk". +// +struct GenTreeStoreDynBlk : public GenTreeBlk { public: GenTree* gtDynamicSize; - GenTreeDynBlk(GenTree* addr, GenTree* dynamicSize) - : GenTreeBlk(GT_DYN_BLK, TYP_STRUCT, addr, nullptr), gtDynamicSize(dynamicSize) + GenTreeStoreDynBlk(GenTree* dstAddr, GenTree* data, GenTree* dynamicSize) + : GenTreeBlk(GT_STORE_DYN_BLK, TYP_VOID, dstAddr, data, nullptr), gtDynamicSize(dynamicSize) { - // Conservatively the 'addr' could be null or point into the global heap. - gtFlags |= GTF_EXCEPT | GTF_GLOB_REF; + // Conservatively the 'dstAddr' could be null or point into the global heap. + // Likewise, this is a store and so must be marked with the GTF_ASG flag. + gtFlags |= (GTF_ASG | GTF_EXCEPT | GTF_GLOB_REF); gtFlags |= (dynamicSize->gtFlags & GTF_ALL_EFFECT); } #if DEBUGGABLE_GENTREE protected: friend GenTree; - GenTreeDynBlk() : GenTreeBlk() + GenTreeStoreDynBlk() : GenTreeBlk() { } #endif // DEBUGGABLE_GENTREE @@ -7488,20 +7485,7 @@ struct GenTreeCC final : public GenTree inline bool GenTree::OperIsBlkOp() { - return ((gtOper == GT_ASG) && varTypeIsStruct(AsOp()->gtOp1)) || (OperIsBlk() && (AsBlk()->Data() != nullptr)); -} - -inline bool GenTree::OperIsDynBlkOp() -{ - if (gtOper == GT_ASG) - { - return gtGetOp1()->OperGet() == GT_DYN_BLK; - } - else if (gtOper == GT_STORE_DYN_BLK) - { - return true; - } - return false; + return ((gtOper == GT_ASG) && varTypeIsStruct(AsOp()->gtOp1)) || OperIsStoreBlk(); } inline bool GenTree::OperIsInitBlkOp() @@ -7650,6 +7634,79 @@ inline bool GenTree::IsSIMDZero() const return false; } +//------------------------------------------------------------------- +// IsFloatPositiveZero: returns true if this is exactly a const float value of postive zero (+0.0) +// +// Returns: +// True if this represents a const floating-point value of exactly positive zero (+0.0). +// Will return false if the value is negative zero (-0.0). +// +inline bool GenTree::IsFloatPositiveZero() const +{ + return IsCnsFltOrDbl() && !IsCnsNonZeroFltOrDbl(); +} + +//------------------------------------------------------------------- +// IsVectorZero: returns true if this is an integral or floating-point (SIMD or HW intrinsic) vector +// with all its elements equal to zero. +// +// Returns: +// True if this represents an integral or floating-point const (SIMD or HW intrinsic) vector with all its elements +// equal to zero. +// +// TODO: We already have IsSIMDZero() and IsIntegralConstVector(0), +// however, IsSIMDZero() does not cover hardware intrinsics, and IsIntegralConstVector(0) does not cover floating +// point. In order to not risk adverse behaviour by modifying those, this function 'IsVectorZero' was introduced. +// At some point, it makes sense to normalize this logic to be a single function call rather than have several +// separate ones; preferably this one. +inline bool GenTree::IsVectorZero() const +{ +#ifdef FEATURE_SIMD + if (gtOper == GT_SIMD) + { + const GenTreeSIMD* node = AsSIMD(); + + if (node->GetSIMDIntrinsicId() == SIMDIntrinsicInit) + { + return (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero()); + } + } +#endif + +#ifdef FEATURE_HW_INTRINSICS + if (gtOper == GT_HWINTRINSIC) + { + const GenTreeHWIntrinsic* node = AsHWIntrinsic(); + const var_types simdBaseType = node->GetSimdBaseType(); + + if (varTypeIsIntegral(simdBaseType) || varTypeIsFloating(simdBaseType)) + { + const NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + + if (node->GetOperandCount() == 0) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + else if ((node->GetOperandCount() == 1) && + (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero())) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_Create) || (intrinsicId == NI_Vector256_Create); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_Create) || (intrinsicId == NI_Vector128_Create); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + } + } +#endif // FEATURE_HW_INTRINSICS + + return false; +} + inline bool GenTree::IsBoxedValue() { assert(gtOper != GT_BOX || AsBox()->BoxOp() != nullptr); @@ -8328,7 +8385,7 @@ inline bool GenTree::IsCnsFltOrDbl() const return OperGet() == GT_CNS_DBL; } -inline bool GenTree::IsCnsNonZeroFltOrDbl() +inline bool GenTree::IsCnsNonZeroFltOrDbl() const { if (OperGet() == GT_CNS_DBL) { diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 5a5afe6aad050..9b40861fef0fd 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -90,8 +90,7 @@ GTNODE(OBJ , GenTreeObj ,0,(GTK_UNOP|GTK_EXOP)) GTNODE(STORE_OBJ , GenTreeObj ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. GTNODE(BLK , GenTreeBlk ,0,(GTK_UNOP|GTK_EXOP)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) GTNODE(STORE_BLK , GenTreeBlk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(DYN_BLK , GenTreeDynBlk ,0,GTK_SPECIAL) // Dynamically sized block object -GTNODE(STORE_DYN_BLK , GenTreeDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block object +GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block store GTNODE(BOX , GenTreeBox ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP)) // Member-field diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h index 591753837fe89..6373011779020 100644 --- a/src/coreclr/jit/gtstructs.h +++ b/src/coreclr/jit/gtstructs.h @@ -92,14 +92,14 @@ GTSTRUCT_2(ClsVar , GT_CLS_VAR, GT_CLS_VAR_ADDR) GTSTRUCT_1(ArgPlace , GT_ARGPLACE) GTSTRUCT_1(CmpXchg , GT_CMPXCHG) GTSTRUCT_1(AddrMode , GT_LEA) -GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_DYN_BLK, GT_STORE_DYN_BLK) +GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK) GTSTRUCT_2(Obj , GT_OBJ, GT_STORE_OBJ) -GTSTRUCT_2(DynBlk , GT_DYN_BLK, GT_STORE_DYN_BLK) +GTSTRUCT_1(StoreDynBlk , GT_STORE_DYN_BLK) GTSTRUCT_1(Qmark , GT_QMARK) GTSTRUCT_1(PhiArg , GT_PHI_ARG) GTSTRUCT_1(Phi , GT_PHI) GTSTRUCT_1(StoreInd , GT_STOREIND) -GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_DYN_BLK, GT_STORE_DYN_BLK) +GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK) #if FEATURE_ARG_SPLIT GTSTRUCT_2_SPECIAL(PutArgStk, GT_PUTARG_STK, GT_PUTARG_SPLIT) GTSTRUCT_1(PutArgSplit , GT_PUTARG_SPLIT) diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index dfde343fe52cb..fe9729ee7a9f1 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -285,7 +285,26 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, bool isIsaSupported = comp->compSupportsHWIntrinsic(isa); - if ((strcmp(methodName, "get_IsSupported") == 0) || (strcmp(methodName, "get_IsHardwareAccelerated") == 0)) + bool isHardwareAcceleratedProp = (strcmp(methodName, "get_IsHardwareAccelerated") == 0); +#ifdef TARGET_XARCH + if (isHardwareAcceleratedProp) + { + // Special case: Some of Vector128/256 APIs are hardware accelerated with Sse1 and Avx1, + // but we want IsHardwareAccelerated to return true only when all of them are (there are + // still can be cases where e.g. Sse41 might give an additional boost for Vector128, but it's + // not important enough to bump the minimal Sse version here) + if (strcmp(className, "Vector128") == 0) + { + isa = InstructionSet_SSE2; + } + else if (strcmp(className, "Vector256") == 0) + { + isa = InstructionSet_AVX2; + } + } +#endif + + if ((strcmp(methodName, "get_IsSupported") == 0) || isHardwareAcceleratedProp) { return isIsaSupported ? (comp->compExactlyDependsOn(isa) ? NI_IsSupported_True : NI_IsSupported_Dynamic) : NI_IsSupported_False; @@ -1007,6 +1026,41 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, retNode = isScalar ? gtNewScalarHWIntrinsicNode(retType, op1, intrinsic) : gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + +#if defined(TARGET_XARCH) + switch (intrinsic) + { + case NI_SSE41_ConvertToVector128Int16: + case NI_SSE41_ConvertToVector128Int32: + case NI_SSE41_ConvertToVector128Int64: + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX2_ConvertToVector256Int16: + case NI_AVX2_ConvertToVector256Int32: + case NI_AVX2_ConvertToVector256Int64: + { + // These intrinsics have both pointer and vector overloads + // We want to be able to differentiate between them so lets + // just track the aux type as a ptr or undefined, depending + + CorInfoType auxiliaryType = CORINFO_TYPE_UNDEF; + + if (!varTypeIsSIMD(op1->TypeGet())) + { + auxiliaryType = CORINFO_TYPE_PTR; + } + + retNode->AsHWIntrinsic()->SetAuxiliaryJitType(auxiliaryType); + break; + } + + default: + { + break; + } + } +#endif // TARGET_XARCH + break; case 2: diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 43bd543c599f1..4551ed9e4e1ce 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -577,6 +577,25 @@ struct HWIntrinsicInfo return lookup(id).ins[type - TYP_BYTE]; } + static instruction lookupIns(GenTreeHWIntrinsic* intrinsicNode) + { + assert(intrinsicNode != nullptr); + + NamedIntrinsic intrinsic = intrinsicNode->GetHWIntrinsicId(); + var_types type = TYP_UNKNOWN; + + if (lookupCategory(intrinsic) == HW_Category_Scalar) + { + type = intrinsicNode->TypeGet(); + } + else + { + type = intrinsicNode->GetSimdBaseType(); + } + + return lookupIns(intrinsic, type); + } + static HWIntrinsicCategory lookupCategory(NamedIntrinsic id) { return lookup(id).category; diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 0c1b01e64ed93..3e5c612236050 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -339,6 +339,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, GenTree* op1 = nullptr; GenTree* op2 = nullptr; GenTree* op3 = nullptr; + GenTree* op4 = nullptr; switch (intrinsic) { @@ -601,11 +602,16 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - op2 = impSIMDPopStack(retType); - op1 = impSIMDPopStack(retType); + if (!varTypeIsLong(simdBaseType)) + { + var_types simdType = getSIMDTypeForSize(simdSize); - retNode = - gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -681,6 +687,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case TYP_UBYTE: { op2 = gtNewIconNode(0x80); + simdBaseType = TYP_UBYTE; + simdBaseJitType = CORINFO_TYPE_UBYTE; vectorCreateOp1 = gtNewLconNode(0x00FFFEFDFCFBFAF9); if (simdSize == 16) @@ -705,30 +713,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case TYP_INT: case TYP_UINT: - { - op2 = gtNewIconNode(0x80000000); - vectorCreateOp1 = gtNewLconNode(0xFFFFFFE2FFFFFFE1); - - if (simdSize == 16) - { - vectorCreateOp2 = gtNewLconNode(0xFFFFFFE4FFFFFFE3); - } - break; - } - - case TYP_LONG: - case TYP_ULONG: - { - op2 = gtNewLconNode(0x8000000000000000); - vectorCreateOp1 = gtNewLconNode(0xFFFFFFFFFFFFFFC1); - - if (simdSize == 16) - { - vectorCreateOp2 = gtNewLconNode(0xFFFFFFFFFFFFFFC2); - } - break; - } - case TYP_FLOAT: { op2 = gtNewIconNode(0x80000000); @@ -743,6 +727,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case TYP_LONG: + case TYP_ULONG: case TYP_DOUBLE: { op2 = gtNewLconNode(0x8000000000000000); @@ -774,17 +760,27 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, gtNewSimdHWIntrinsicNode(simdType, vectorCreateOp1, NI_Vector64_Create, vectorCreateType, simdSize); } + op2 = + gtNewSimdCreateBroadcastNode(simdType, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op2, NI_AdvSimd_And, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); - op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op3, NI_AdvSimd_ShiftLogical, simdBaseJitType, simdSize, + NamedIntrinsic shiftIntrinsic = NI_AdvSimd_ShiftLogical; + + if ((simdSize == 8) && varTypeIsLong(simdBaseType)) + { + shiftIntrinsic = NI_AdvSimd_ShiftLogicalScalar; + } + + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op3, shiftIntrinsic, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); if (varTypeIsByte(simdBaseType) && (simdSize == 16)) { - CORINFO_CLASS_HANDLE clsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType); + CORINFO_CLASS_HANDLE simdClsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType); - op1 = impCloneExpr(op1, &op2, clsHnd, (unsigned)CHECK_SPILL_ALL, + op1 = impCloneExpr(op1, &op2, simdClsHnd, (unsigned)CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for vector extractmostsignificantbits")); op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_Vector128_GetLower, simdBaseJitType, simdSize, @@ -793,9 +789,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ false); op1 = gtNewSimdHWIntrinsicNode(simdBaseType, op1, NI_Vector64_ToScalar, simdBaseJitType, 8, /* isSimdAsHWIntrinsic */ false); - op1 = gtNewCastNode(TYP_INT, op1, /* isUnsigned */ true, simdBaseType); + op1 = gtNewCastNode(TYP_INT, op1, /* isUnsigned */ true, TYP_INT); - GenTree* zero = gtNewSimdHWIntrinsicNode(retType, NI_Vector128_get_Zero, simdBaseJitType, simdSize); + GenTree* zero = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); ssize_t index = 8 / genTypeSize(simdBaseType); op2 = gtNewSimdHWIntrinsicNode(simdType, op2, zero, gtNewIconNode(index), NI_AdvSimd_ExtractVector128, @@ -806,7 +802,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ false); op2 = gtNewSimdHWIntrinsicNode(simdBaseType, op2, NI_Vector64_ToScalar, simdBaseJitType, 8, /* isSimdAsHWIntrinsic */ false); - op2 = gtNewCastNode(TYP_INT, op2, /* isUnsigned */ true, simdBaseType); + op2 = gtNewCastNode(TYP_INT, op2, /* isUnsigned */ true, TYP_INT); op2 = gtNewOperNode(GT_LSH, TYP_INT, op2, gtNewIconNode(8)); retNode = gtNewOperNode(GT_OR, TYP_INT, op1, op2); @@ -815,8 +811,20 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { if (!varTypeIsLong(simdBaseType)) { - op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, - simdSize, /* isSimdAsHWIntrinsic */ false); + if ((simdSize == 8) && ((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT))) + { + CORINFO_CLASS_HANDLE simdClsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType); + + op1 = impCloneExpr(op1, &op2, simdClsHnd, (unsigned)CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector extractmostsignificantbits")); + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, op2, NI_AdvSimd_AddPairwise, simdBaseJitType, + simdSize, /* isSimdAsHWIntrinsic */ false); + } + else + { + op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, + simdSize, /* isSimdAsHWIntrinsic */ false); + } } else if (simdSize == 16) { @@ -829,7 +837,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdBaseType != TYP_INT) && (simdBaseType != TYP_UINT)) { - retNode = gtNewCastNode(TYP_INT, retNode, /* isUnsigned */ true, simdBaseType); + retNode = gtNewCastNode(TYP_INT, retNode, /* isUnsigned */ true, TYP_INT); } } break; @@ -1398,9 +1406,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_Store: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize); break; @@ -1410,6 +1419,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_StoreAligned: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); if (!opts.MinOpts()) { @@ -1419,7 +1429,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize); break; @@ -1429,6 +1439,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_StoreAlignedNonTemporal: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); if (!opts.MinOpts()) { @@ -1438,7 +1449,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); // ARM64 has non-temporal stores (STNP) but we don't currently support them @@ -1449,6 +1460,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector64_StoreUnsafe: case NI_Vector128_StoreUnsafe: { + var_types simdType = getSIMDTypeForSize(simdSize); + if (sig->numArgs == 3) { op3 = impPopStack().val; @@ -1459,13 +1472,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); if (sig->numArgs == 3) { - op3 = gtNewIconNode(genTypeSize(simdBaseType), op2->TypeGet()); - op2 = gtNewOperNode(GT_MUL, op2->TypeGet(), op2, op3); - op2 = gtNewOperNode(GT_ADD, op1->TypeGet(), op1, op2); + op4 = gtNewIconNode(genTypeSize(simdBaseType), op3->TypeGet()); + op3 = gtNewOperNode(GT_MUL, op3->TypeGet(), op3, op4); + op2 = gtNewOperNode(GT_ADD, op2->TypeGet(), op2, op3); } retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize); @@ -1476,8 +1489,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_Sum: { assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); break; } diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 706b988f049e5..6dfe48047c094 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -206,6 +206,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { const HWIntrinsic intrin(node); + // We need to validate that other phases of the compiler haven't introduced unsupported intrinsics + assert(compiler->compIsaSupportedDebugOnly(HWIntrinsicInfo::lookupIsa(intrin.id))); + regNumber targetReg = node->GetRegNum(); regNumber op1Reg = REG_NA; @@ -496,6 +499,29 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); break; + case NI_AdvSimd_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqualScalar: + if (intrin.op1->isContained()) + { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); + assert(intrin.op1->IsVectorZero()); + + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt); + } + else if (intrin.op2->isContained()) + { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); + assert(intrin.op2->IsVectorZero()); + + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); + } + else + { + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + } + break; + case NI_AdvSimd_AbsoluteCompareLessThan: case NI_AdvSimd_AbsoluteCompareLessThanOrEqual: case NI_AdvSimd_CompareLessThan: diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index cd9e0f8f8fc3d..10c8dcaedb197 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -27,11 +27,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // assertIsContainableHWIntrinsicOp: Asserts that op is containable by node // // Arguments: -// lowering - The lowering phase from the compiler -// node - The HWIntrinsic node that has the contained node -// op - The op that is contained +// lowering - The lowering phase from the compiler +// containingNode - The HWIntrinsic node that has the contained node +// containedNode - The node that is contained // -static void assertIsContainableHWIntrinsicOp(Lowering* lowering, GenTreeHWIntrinsic* node, GenTree* op) +static void assertIsContainableHWIntrinsicOp(Lowering* lowering, + GenTreeHWIntrinsic* containingNode, + GenTree* containedNode) { #if DEBUG // The Lowering::IsContainableHWIntrinsicOp call is not quite right, since it follows pre-register allocation @@ -39,14 +41,15 @@ static void assertIsContainableHWIntrinsicOp(Lowering* lowering, GenTreeHWIntrin // // We use isContainable to track the special HWIntrinsic node containment rules (for things like LoadAligned and // LoadUnaligned) and we use the supportsRegOptional check to support general-purpose loads (both from stack - // spillage - // and for isUsedFromMemory contained nodes, in the case where the register allocator decided to not allocate a - // register - // in the first place). + // spillage and for isUsedFromMemory contained nodes, in the case where the register allocator decided to not + // allocate a register in the first place). + + GenTree* node = containedNode; + bool supportsRegOptional = false; + bool isContainable = lowering->TryGetContainableHWIntrinsicOp(containingNode, &node, &supportsRegOptional); - bool supportsRegOptional = false; - bool isContainable = lowering->IsContainableHWIntrinsicOp(node, op, &supportsRegOptional); assert(isContainable || supportsRegOptional); + assert(node == containedNode); #endif // DEBUG } @@ -83,6 +86,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); size_t numArgs = node->GetOperandCount(); + // We need to validate that other phases of the compiler haven't introduced unsupported intrinsics + assert(compiler->compIsaSupportedDebugOnly(isa)); + int ival = HWIntrinsicInfo::lookupIval(intrinsicId, compiler->compOpportunisticallyDependsOn(InstructionSet_AVX)); assert(HWIntrinsicInfo::RequiresCodegen(intrinsicId)); @@ -521,6 +527,14 @@ void CodeGen::genHWIntrinsic_R_RM( break; } + case GT_CNS_DBL: + { + GenTreeDblCon* cns = rmOp->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_R_C(ins, attr, reg, hnd, 0); + return; + } + default: { unreached(); @@ -737,6 +751,14 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, break; } + case GT_CNS_DBL: + { + GenTreeDblCon* cns = op2->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_SIMD_R_R_C_I(ins, simdSize, targetReg, op1Reg, hnd, 0, ival); + return; + } + default: unreached(); break; @@ -886,6 +908,14 @@ void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, break; } + case GT_CNS_DBL: + { + GenTreeDblCon* cns = op2->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_SIMD_R_R_C_R(ins, simdSize, targetReg, op1Reg, op3Reg, hnd, 0); + return; + } + default: unreached(); break; @@ -1012,6 +1042,14 @@ void CodeGen::genHWIntrinsic_R_R_R_RM( break; } + case GT_CNS_DBL: + { + GenTreeDblCon* cns = op3->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_SIMD_R_R_R_C(ins, attr, targetReg, op1Reg, op2Reg, hnd, 0); + return; + } + default: unreached(); break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 4b2e3fa132ad7..7d4582db97616 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -42,28 +42,28 @@ HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, HARDWARE_INTRINSIC(Vector64, Create, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Vector64, Divide, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Load, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, LoadAligned, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, LoadAlignedNonTemporal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -90,12 +90,12 @@ HARDWARE_INTRINSIC(Vector64, ShiftLeft, HARDWARE_INTRINSIC(Vector64, ShiftRightArithmetic, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, ShiftRightLogical, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Store, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, Store, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Subtract, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128Unsafe, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) @@ -140,11 +140,11 @@ HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) @@ -153,17 +153,17 @@ HARDWARE_INTRINSIC(Vector128, GetElement, HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, GetUpper, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Load, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -190,12 +190,12 @@ HARDWARE_INTRINSIC(Vector128, ShiftLeft, HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) @@ -240,7 +240,7 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) @@ -492,8 +492,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 95ab714ae6334..7c80de358cf4e 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -59,28 +59,28 @@ HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Load, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -107,12 +107,12 @@ HARDWARE_INTRINSIC(Vector128, ShiftLeft, HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -155,11 +155,11 @@ HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, Divide, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, get_Count, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -167,17 +167,17 @@ HARDWARE_INTRINSIC(Vector256, get_Zero, HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Load, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, LoadAligned, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, LoadAlignedNonTemporal, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -204,12 +204,12 @@ HARDWARE_INTRINSIC(Vector256, ShiftLeft, HARDWARE_INTRINSIC(Vector256, ShiftRightArithmetic, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, ShiftRightLogical, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Store, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, Store, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Subtract, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, WidenLower, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, WidenUpper, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) @@ -494,9 +494,9 @@ HARDWARE_INTRINSIC(SSE41, BlendVariable, HARDWARE_INTRINSIC(SSE41, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41, CeilingScalar, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int16, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int32, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int64, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int16, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) +HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int32, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) +HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int64, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(SSE41, DotProduct, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_dppd}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE41, Extract, 16, 2, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) @@ -649,9 +649,9 @@ HARDWARE_INTRINSIC(AVX2, CompareLessThan, HARDWARE_INTRINSIC(AVX2, ExtractVector128, 32, 2, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(AVX2, ConvertToInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX2, ConvertToUInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int16, 32, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int16, 32, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad) +HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad) +HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(AVX2, GatherVector128, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment) HARDWARE_INTRINSIC(AVX2, GatherVector256, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment) HARDWARE_INTRINSIC(AVX2, GatherMaskVector128, 16, 5, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index e6f499588c528..aec1be705f3db 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -535,6 +535,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, GenTree* op1 = nullptr; GenTree* op2 = nullptr; GenTree* op3 = nullptr; + GenTree* op4 = nullptr; if (!featureSIMD || !IsBaselineSimdIsaSupported()) { @@ -947,6 +948,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_Dot: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); if (varTypeIsByte(simdBaseType) || varTypeIsLong(simdBaseType)) { @@ -973,8 +975,8 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, } } - op2 = impSIMDPopStack(retType); - op1 = impSIMDPopStack(retType); + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); retNode = gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); @@ -1022,7 +1024,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1044,24 +1046,137 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(simdType); - NamedIntrinsic moveMaskIntrinsic = NI_Illegal; + NamedIntrinsic shuffleIntrinsic = NI_Illegal; + NamedIntrinsic createIntrinsic = NI_Illegal; - if (simdBaseType == TYP_FLOAT) - { - moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE_MoveMask; - } - else if (simdBaseType == TYP_DOUBLE) - { - moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE2_MoveMask; - } - else + switch (simdBaseType) { - moveMaskIntrinsic = (simdSize == 32) ? NI_AVX2_MoveMask : NI_SSE2_MoveMask; - simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + case TYP_BYTE: + case TYP_UBYTE: + { + op1 = impSIMDPopStack(simdType); + moveMaskIntrinsic = (simdSize == 32) ? NI_AVX2_MoveMask : NI_SSE2_MoveMask; + break; + } + + case TYP_SHORT: + case TYP_USHORT: + { + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + + assert((simdSize == 16) || (simdSize == 32)); + IntrinsicNodeBuilder nodeBuilder(getAllocator(CMK_ASTNode), simdSize); + + // We want to tightly pack the most significant byte of each short/ushort + // and then zero the tightly packed least significant bytes + + nodeBuilder.AddOperand(0x00, gtNewIconNode(0x01)); + nodeBuilder.AddOperand(0x01, gtNewIconNode(0x03)); + nodeBuilder.AddOperand(0x02, gtNewIconNode(0x05)); + nodeBuilder.AddOperand(0x03, gtNewIconNode(0x07)); + nodeBuilder.AddOperand(0x04, gtNewIconNode(0x09)); + nodeBuilder.AddOperand(0x05, gtNewIconNode(0x0B)); + nodeBuilder.AddOperand(0x06, gtNewIconNode(0x0D)); + nodeBuilder.AddOperand(0x07, gtNewIconNode(0x0F)); + + for (unsigned i = 0x08; i < 0x10; i++) + { + // The most significant bit being set means zero the value + nodeBuilder.AddOperand(i, gtNewIconNode(0x80)); + } + + if (simdSize == 32) + { + // Vector256 works on 2x128-bit lanes, so repeat the same indices for the upper lane + + nodeBuilder.AddOperand(0x10, gtNewIconNode(0x01)); + nodeBuilder.AddOperand(0x11, gtNewIconNode(0x03)); + nodeBuilder.AddOperand(0x12, gtNewIconNode(0x05)); + nodeBuilder.AddOperand(0x13, gtNewIconNode(0x07)); + nodeBuilder.AddOperand(0x14, gtNewIconNode(0x09)); + nodeBuilder.AddOperand(0x15, gtNewIconNode(0x0B)); + nodeBuilder.AddOperand(0x16, gtNewIconNode(0x0D)); + nodeBuilder.AddOperand(0x17, gtNewIconNode(0x0F)); + + for (unsigned i = 0x18; i < 0x20; i++) + { + // The most significant bit being set means zero the value + nodeBuilder.AddOperand(i, gtNewIconNode(0x80)); + } + + createIntrinsic = NI_Vector256_Create; + shuffleIntrinsic = NI_AVX2_Shuffle; + moveMaskIntrinsic = NI_AVX2_MoveMask; + } + else if (compOpportunisticallyDependsOn(InstructionSet_SSSE3)) + { + createIntrinsic = NI_Vector128_Create; + shuffleIntrinsic = NI_SSSE3_Shuffle; + moveMaskIntrinsic = NI_SSE2_MoveMask; + } + else + { + return nullptr; + } + + op2 = gtNewSimdHWIntrinsicNode(simdType, std::move(nodeBuilder), createIntrinsic, + simdBaseJitType, simdSize); + + op1 = impSIMDPopStack(simdType); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op2, shuffleIntrinsic, simdBaseJitType, simdSize); + + if (simdSize == 32) + { + CorInfoType simdOtherJitType; + + // Since Vector256 is 2x128-bit lanes we need a full width permutation so we get the lower + // 64-bits of each lane next to eachother. The upper bits should be zero, but also don't + // matter so we can also then simplify down to a 128-bit move mask. + + simdOtherJitType = (simdBaseType == TYP_UBYTE) ? CORINFO_TYPE_ULONG : CORINFO_TYPE_LONG; + + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, gtNewIconNode(0xD8), NI_AVX2_Permute4x64, + simdOtherJitType, simdSize); + + simdSize = 16; + simdType = TYP_SIMD16; + + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, NI_Vector256_GetLower, simdBaseJitType, + simdSize); + } + break; + } + + case TYP_INT: + case TYP_UINT: + case TYP_FLOAT: + { + simdBaseJitType = CORINFO_TYPE_FLOAT; + op1 = impSIMDPopStack(simdType); + moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE_MoveMask; + break; + } + + case TYP_LONG: + case TYP_ULONG: + case TYP_DOUBLE: + { + simdBaseJitType = CORINFO_TYPE_DOUBLE; + op1 = impSIMDPopStack(simdType); + moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE2_MoveMask; + break; + } + + default: + { + unreached(); + } } + assert(moveMaskIntrinsic != NI_Illegal); + assert(op1 != nullptr); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, moveMaskIntrinsic, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); } @@ -1172,7 +1287,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1190,7 +1305,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1224,7 +1339,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1242,7 +1357,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1276,7 +1391,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1294,7 +1409,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1328,7 +1443,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1346,7 +1461,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1780,9 +1895,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_Store: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); NamedIntrinsic storeIntrinsic = NI_Illegal; @@ -1807,9 +1923,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_StoreAligned: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); NamedIntrinsic storeIntrinsic = NI_Illegal; @@ -1834,9 +1951,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_StoreAlignedNonTemporal: { assert(sig->numArgs == 2); + var_types simdType = getSIMDTypeForSize(simdSize); op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); NamedIntrinsic storeIntrinsic = NI_Illegal; @@ -1860,6 +1978,8 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_StoreUnsafe: case NI_Vector256_StoreUnsafe: { + var_types simdType = getSIMDTypeForSize(simdSize); + if (sig->numArgs == 3) { op3 = impPopStack().val; @@ -1870,13 +1990,13 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, } op2 = impPopStack().val; - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); if (sig->numArgs == 3) { - op3 = gtNewIconNode(genTypeSize(simdBaseType), op2->TypeGet()); - op2 = gtNewOperNode(GT_MUL, op2->TypeGet(), op2, op3); - op2 = gtNewOperNode(GT_ADD, op1->TypeGet(), op1, op2); + op4 = gtNewIconNode(genTypeSize(simdBaseType), op3->TypeGet()); + op3 = gtNewOperNode(GT_MUL, op3->TypeGet(), op3, op4); + op2 = gtNewOperNode(GT_ADD, op2->TypeGet(), op2, op3); } NamedIntrinsic storeIntrinsic = NI_Illegal; @@ -1902,8 +2022,14 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_Sum: { assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); - if (varTypeIsFloating(simdBaseType)) + if ((simdSize == 32) && !compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + // Vector256 for integer types requires AVX2 + break; + } + else if (varTypeIsFloating(simdBaseType)) { if (!compOpportunisticallyDependsOn(InstructionSet_SSE3)) { @@ -1922,7 +2048,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, break; } - op1 = impSIMDPopStack(retType); + op1 = impSIMDPopStack(simdType); retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); break; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index aab024d3ac30d..b9cc2ff883d64 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -91,42 +91,6 @@ void Compiler::impPushOnStack(GenTree* tree, typeInfo ti) CORINFO_CLASS_HANDLE clsHnd = ti.GetClassHandle(); assert(clsHnd != NO_CLASS_HANDLE); } - - if (tiVerificationNeeded && !ti.IsDead()) - { - assert(typeInfo::AreEquivalent(NormaliseForStack(ti), ti)); // types are normalized - - // The ti type is consistent with the tree type. - // - - // On 64-bit systems, nodes whose "proper" type is "native int" get labeled TYP_LONG. - // In the verification type system, we always transform "native int" to "TI_INT". - // Ideally, we would keep track of which nodes labeled "TYP_LONG" are really "native int", but - // attempts to do that have proved too difficult. Instead, we'll assume that in checks like this, - // when there's a mismatch, it's because of this reason -- the typeInfo::AreEquivalentModuloNativeInt - // method used in the last disjunct allows exactly this mismatch. - assert(ti.IsDead() || (ti.IsByRef() && ((tree->TypeGet() == TYP_I_IMPL) || (tree->TypeGet() == TYP_BYREF))) || - (ti.IsUnboxedGenericTypeVar() && tree->TypeGet() == TYP_REF) || - (ti.IsObjRef() && tree->TypeGet() == TYP_REF) || (ti.IsMethod() && tree->TypeGet() == TYP_I_IMPL) || - (ti.IsType(TI_STRUCT) && tree->TypeGet() != TYP_REF) || - typeInfo::AreEquivalentModuloNativeInt(NormaliseForStack(ti), - NormaliseForStack(typeInfo(tree->TypeGet())))); - - // If it is a struct type, make certain we normalized the primitive types - assert(!ti.IsType(TI_STRUCT) || - info.compCompHnd->getTypeForPrimitiveValueClass(ti.GetClassHandle()) == CORINFO_TYPE_UNDEF); - } - -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("About to push to stack: "); - ti.Dump(); - } -#endif // VERBOSE_VERIFY - #endif // DEBUG verCurrentState.esStack[verCurrentState.esStackDepth].seTypeInfo = ti; @@ -257,14 +221,7 @@ void Compiler::impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolv pResolvedToken->token = getU4LittleEndian(addr); pResolvedToken->tokenType = kind; - if (!tiVerificationNeeded) - { - info.compCompHnd->resolveToken(pResolvedToken); - } - else - { - Verify(eeTryResolveToken(pResolvedToken), "Token resolution failed"); - } + info.compCompHnd->resolveToken(pResolvedToken); } /***************************************************************************** @@ -279,19 +236,6 @@ StackEntry Compiler::impPopStack() BADCODE("stack underflow"); } -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - JITDUMP("\n"); - printf(TI_DUMP_PADDING); - printf("About to pop from the stack: "); - const typeInfo& ti = verCurrentState.esStack[verCurrentState.esStackDepth - 1].seTypeInfo; - ti.Dump(); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - return verCurrentState.esStack[--verCurrentState.esStackDepth]; } @@ -824,7 +768,7 @@ void Compiler::impAssignTempGen(unsigned tmpNum, // so at least ignore it in the case when verification is turned on // since any block that tries to use the temp would have failed verification. var_types varType = lvaTable[tmpNum].lvType; - assert(tiVerificationNeeded || varType == TYP_UNDEF || varTypeIsStruct(varType)); + assert(varType == TYP_UNDEF || varTypeIsStruct(varType)); lvaSetStruct(tmpNum, structType, false); varType = lvaTable[tmpNum].lvType; @@ -1864,7 +1808,6 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, case GT_OBJ: case GT_BLK: - case GT_DYN_BLK: case GT_ASG: // These should already have the appropriate type. assert(structVal->gtType == structType); @@ -2488,21 +2431,9 @@ bool Compiler::impSpillStackEntry(unsigned level, /* Allocate a temp if we haven't been asked to use a particular one */ - if (tiVerificationNeeded) - { - // Ignore bad temp requests (they will happen with bad code and will be - // catched when importing the destblock) - if (tnum != BAD_VAR_NUM && tnum >= lvaCount) - { - return false; - } - } - else + if (tnum != BAD_VAR_NUM && (tnum >= lvaCount)) { - if (tnum != BAD_VAR_NUM && (tnum >= lvaCount)) - { - return false; - } + return false; } bool isNewTemp = false; @@ -2512,27 +2443,6 @@ bool Compiler::impSpillStackEntry(unsigned level, tnum = lvaGrabTemp(true DEBUGARG(reason)); isNewTemp = true; } - else if (tiVerificationNeeded && lvaTable[tnum].TypeGet() != TYP_UNDEF) - { - // if verification is needed and tnum's type is incompatible with - // type on that stack, we grab a new temp. This is safe since - // we will throw a verification exception in the dest block. - - var_types valTyp = tree->TypeGet(); - var_types dstTyp = lvaTable[tnum].TypeGet(); - - // if the two types are different, we return. This will only happen with bad code and will - // be catched when importing the destblock. We still allow int/byrefs and float/double differences. - if ((genActualType(valTyp) != genActualType(dstTyp)) && - !( -#ifndef TARGET_64BIT - (valTyp == TYP_I_IMPL && dstTyp == TYP_BYREF) || (valTyp == TYP_BYREF && dstTyp == TYP_I_IMPL) || -#endif // !TARGET_64BIT - (varTypeIsFloating(dstTyp) && varTypeIsFloating(valTyp)))) - { - return false; - } - } /* Assign the spilled entry to the temp */ impAssignTempGen(tnum, tree, verCurrentState.esStack[level].seTypeInfo.GetClassHandle(), level); @@ -2647,11 +2557,9 @@ inline void Compiler::impSpillSideEffects(bool spillGlobEffects, unsigned chkLev { GenTree* tree = verCurrentState.esStack[i].val; - GenTree* lclVarTree; - if ((tree->gtFlags & spillFlags) != 0 || - (spillGlobEffects && // Only consider the following when spillGlobEffects == true - !impIsAddressInLocal(tree, &lclVarTree) && // No need to spill the GT_ADDR node on a local. + (spillGlobEffects && // Only consider the following when spillGlobEffects == true + !impIsAddressInLocal(tree) && // No need to spill the GT_ADDR node on a local. gtHasLocalsWithAddrOp(tree))) // Spill if we still see GT_LCL_VAR that contains lvHasLdAddrOp or // lvAddrTaken flag. { @@ -3879,19 +3787,25 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, return new (this, GT_LABEL) GenTree(GT_LABEL, TYP_I_IMPL); } - if (((ni == NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan) || - (ni == NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray)) && - IsTargetAbi(CORINFO_CORERT_ABI)) + switch (ni) { // CreateSpan must be expanded for NativeAOT - mustExpand = true; - } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan: + case NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray: + mustExpand |= IsTargetAbi(CORINFO_CORERT_ABI); + break; - if ((ni == NI_System_ByReference_ctor) || (ni == NI_System_ByReference_get_Value) || - (ni == NI_System_Activator_AllocatorOf) || (ni == NI_System_Activator_DefaultConstructorOf) || - (ni == NI_System_Object_MethodTableOf) || (ni == NI_System_EETypePtr_EETypePtrOf)) - { - mustExpand = true; + case NI_System_ByReference_ctor: + case NI_System_ByReference_get_Value: + case NI_System_Activator_AllocatorOf: + case NI_System_Activator_DefaultConstructorOf: + case NI_System_Object_MethodTableOf: + case NI_System_EETypePtr_EETypePtrOf: + mustExpand = true; + break; + + default: + break; } GenTree* retNode = nullptr; @@ -3935,29 +3849,19 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, case NI_System_String_get_Length: { GenTree* op1 = impPopStack().val; - if (opts.OptimizationEnabled()) + if (op1->OperIs(GT_CNS_STR)) { - if (op1->OperIs(GT_CNS_STR)) + // Optimize `ldstr + String::get_Length()` to CNS_INT + // e.g. "Hello".Length => 5 + GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon()); + if (iconNode != nullptr) { - // Optimize `ldstr + String::get_Length()` to CNS_INT - // e.g. "Hello".Length => 5 - GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon()); - if (iconNode != nullptr) - { - retNode = iconNode; - break; - } + retNode = iconNode; + break; } - GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB); - op1 = arrLen; - } - else - { - /* Create the expression "*(str_addr + stringLengthOffset)" */ - op1 = gtNewOperNode(GT_ADD, TYP_BYREF, op1, - gtNewIconNode(OFFSETOF__CORINFO_String__stringLen, TYP_I_IMPL)); - op1 = gtNewOperNode(GT_IND, TYP_INT, op1); } + GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB); + op1 = arrLen; // Getting the length of a null string should throw op1->gtFlags |= GTF_EXCEPT; @@ -4007,6 +3911,26 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: + { + GenTree* op1 = impPopStack().val; + if (op1->OperIsConst()) + { + // op1 is a known constant, replace with 'true'. + retNode = gtNewIconNode(1); + JITDUMP("\nExpanding RuntimeHelpers.IsKnownConstant to true early\n"); + // We can also consider FTN_ADDR and typeof(T) here + } + else + { + // op1 is not a known constant, we'll do the expansion in morph + retNode = new (this, GT_INTRINSIC) GenTreeIntrinsic(TYP_INT, op1, ni, method); + JITDUMP("\nConverting RuntimeHelpers.IsKnownConstant to:\n"); + DISPTREE(retNode); + } + break; + } + case NI_System_Activator_AllocatorOf: case NI_System_Activator_DefaultConstructorOf: case NI_System_Object_MethodTableOf: @@ -4283,7 +4207,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, case NI_System_Threading_Thread_get_ManagedThreadId: { - if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_RET_EXPR)) + if (impStackTop().val->OperIs(GT_RET_EXPR)) { GenTreeCall* call = impStackTop().val->AsRetExpr()->gtInlineCandidate->AsCall(); if (call->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) @@ -4306,7 +4230,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, case NI_System_Threading_Interlocked_Or: case NI_System_Threading_Interlocked_And: { - if (opts.OptimizationEnabled() && compOpportunisticallyDependsOn(InstructionSet_Atomics)) + if (compOpportunisticallyDependsOn(InstructionSet_Atomics)) { assert(sig->numArgs == 2); GenTree* op2 = impPopStack().val; @@ -5352,6 +5276,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray; } + else if (strcmp(methodName, "IsKnownConstant") == 0) + { + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant; + } } else if (strncmp(namespaceName, "System.Runtime.Intrinsics", 25) == 0) { @@ -6341,8 +6269,8 @@ void Compiler::verVerifyCall(OPCODE opcode, info.compCompHnd->resolveToken(&delegateResolvedToken); CORINFO_CALL_INFO delegateCallInfo; - eeGetCallInfo(&delegateResolvedToken, nullptr /* constraint typeRef */, - addVerifyFlag(CORINFO_CALLINFO_SECURITYCHECKS), &delegateCallInfo); + eeGetCallInfo(&delegateResolvedToken, nullptr /* constraint typeRef */, CORINFO_CALLINFO_SECURITYCHECKS, + &delegateCallInfo); bool isOpenDelegate = false; VerifyOrReturn(info.compCompHnd->isCompatibleDelegate(objTypeHandle, delegateResolvedToken.hClass, @@ -9523,6 +9451,10 @@ var_types Compiler::impImportCall(OPCODE opcode, // Take care to pass raw IL offset here as the 'debug info' might be different for // inlinees. rawILOffset); + + // Devirtualization may change which method gets invoked. Update our local cache. + // + methHnd = callInfo->hMethod; } if (impIsThis(obj)) @@ -9594,9 +9526,6 @@ var_types Compiler::impImportCall(OPCODE opcode, { if (newobjThis->gtOper == GT_COMMA) { - // In coreclr the callout can be inserted even if verification is disabled - // so we cannot rely on tiVerificationNeeded alone - // We must have inserted the callout. Get the real newobj. newobjThis = newobjThis->AsOp()->gtOp2; } @@ -9905,14 +9834,6 @@ var_types Compiler::impImportCall(OPCODE opcode, eeGetCallSiteSig(pResolvedToken->token, pResolvedToken->tokenScope, pResolvedToken->tokenContext, sig); } - // Find the return type used for verification by interpreting the method signature. - // NB: we are clobbering the already established sig. - if (tiVerificationNeeded) - { - // Actually, we never get the sig for the original method. - sig = &(callInfo->verSig); - } - typeInfo tiRetVal = verMakeTypeInfo(sig->retType, sig->retTypeClass); tiRetVal.NormaliseForStack(); @@ -9923,17 +9844,6 @@ var_types Compiler::impImportCall(OPCODE opcode, tiRetVal.SetIsReadonlyByRef(); } - if (tiVerificationNeeded) - { - // We assume all calls return permanent home byrefs. If they - // didn't they wouldn't be verifiable. This is also covering - // the Address() helper for multidimensional arrays. - if (tiRetVal.IsByRef()) - { - tiRetVal.SetIsPermanentHomeByRef(); - } - } - if (call->IsCall()) { // Sometimes "call" is not a GT_CALL (if we imported an intrinsic that didn't turn into a call) @@ -10766,7 +10676,7 @@ void Compiler::impImportLeave(BasicBlock* block) * scope */ exitBlock = fgNewBBinRegion(BBJ_EHCATCHRET, 0, XTnum + 1, step); - assert(step->bbJumpKind == BBJ_ALWAYS || step->bbJumpKind == BBJ_EHCATCHRET); + assert(step->KindIs(BBJ_ALWAYS, BBJ_EHCATCHRET)); step->bbJumpDest = exitBlock; // the previous step (maybe a call to a nested finally, or a nested catch // exit) returns to this block step->bbJumpDest->bbRefs++; @@ -10874,7 +10784,7 @@ void Compiler::impImportLeave(BasicBlock* block) // never returns to the call-to-finally call, and the finally-protected 'try' region doesn't appear on // stack walks.) - assert(step->bbJumpKind == BBJ_ALWAYS || step->bbJumpKind == BBJ_EHCATCHRET); + assert(step->KindIs(BBJ_ALWAYS, BBJ_EHCATCHRET)); #if FEATURE_EH_CALLFINALLY_THUNKS if (step->bbJumpKind == BBJ_EHCATCHRET) @@ -11773,41 +11683,48 @@ void Compiler::impImportBlockCode(BasicBlock* block) CORINFO_HELPER_DESC calloutHelper; const BYTE* lastLoadToken = nullptr; - // reject cyclic constraints - if (tiVerificationNeeded) - { - Verify(!info.hasCircularClassConstraints, "Method parent has circular class type parameter constraints."); - Verify(!info.hasCircularMethodConstraints, "Method has circular method type parameter constraints."); - } - /* Get the tree list started */ impBeginTreeList(); #ifdef FEATURE_ON_STACK_REPLACEMENT - // Are there any places in the method where we might add a patchpoint? + bool enablePatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0); + +#ifdef DEBUG + + // Optionally suppress patchpoints by method hash // - if (compHasBackwardJump) + static ConfigMethodRange JitEnablePatchpointRange; + JitEnablePatchpointRange.EnsureInit(JitConfig.JitEnablePatchpointRange()); + const unsigned hash = impInlineRoot()->info.compMethodHash(); + const bool inRange = JitEnablePatchpointRange.Contains(hash); + enablePatchpoints &= inRange; + +#endif // DEBUG + + if (enablePatchpoints) { - // Is OSR enabled? + // We don't inline at Tier0, if we do, we may need rethink our approach. + // Could probably support inlines that don't introduce flow. + // + assert(!compIsForInlining()); + + // OSR is not yet supported for methods with explicit tail calls. // - if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0)) + // But we also do not have to switch these methods to be optimized as we should be + // able to avoid getting trapped in Tier0 code by normal call counting. + // So instead, just suppress adding patchpoints. + // + if (!compTailPrefixSeen) { - // OSR is not yet supported for methods with explicit tail calls. - // - // But we also may not switch methods to be optimized as we should be - // able to avoid getting trapped in Tier0 code by normal call counting. - // So instead, just suppress adding patchpoints. + // The normaly policy is only to add patchpoints to the targets of lexically + // backwards branches. // - if (!compTailPrefixSeen) + if (compHasBackwardJump) { assert(compCanHavePatchpoints()); - // We don't inline at Tier0, if we do, we may need rethink our approach. - // Could probably support inlines that don't introduce flow. - assert(!compIsForInlining()); - // Is the start of this block a suitable patchpoint? // if (((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) != 0) && (verCurrentState.esStackDepth == 0)) @@ -11820,12 +11737,64 @@ void Compiler::impImportBlockCode(BasicBlock* block) setMethodHasPatchpoint(); } } + else + { + // Should not see backward branch targets w/o backwards branches + assert((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) == 0); + } } - } - else - { - // Should not see backward branch targets w/o backwards branches - assert((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) == 0); + +#ifdef DEBUG + // As a stress test, we can place patchpoints at the start of any block + // that is a stack empty point and is not within a handler. + // + // Todo: enable for mid-block stack empty points too. + // + const int offsetOSR = JitConfig.JitOffsetOnStackReplacement(); + const int randomOSR = JitConfig.JitRandomOnStackReplacement(); + const bool tryOffsetOSR = offsetOSR >= 0; + const bool tryRandomOSR = randomOSR > 0; + + if (compCanHavePatchpoints() && (tryOffsetOSR || tryRandomOSR) && (verCurrentState.esStackDepth == 0) && + !block->hasHndIndex() && ((block->bbFlags & BBF_PATCHPOINT) == 0)) + { + // Block start can have a patchpoint. See if we should add one. + // + bool addPatchpoint = false; + + // Specific offset? + // + if (tryOffsetOSR) + { + if (impCurOpcOffs == (unsigned)offsetOSR) + { + addPatchpoint = true; + } + } + // Random? + // + else + { + // Reuse the random inliner's random state. + // Note m_inlineStrategy is always created, even if we're not inlining. + // + CLRRandom* const random = impInlineRoot()->m_inlineStrategy->GetRandom(randomOSR); + const int randomValue = (int)random->Next(100); + + addPatchpoint = (randomValue < randomOSR); + } + + if (addPatchpoint) + { + block->bbFlags |= BBF_PATCHPOINT; + setMethodHasPatchpoint(); + } + + JITDUMP("\n** %s patchpoint%s added to " FMT_BB " (il offset %u)\n", tryOffsetOSR ? "offset" : "random", + addPatchpoint ? "" : " not", block->bbNum, impCurOpcOffs); + } + +#endif // DEBUG } // Mark stack-empty rare blocks to be considered for partial compilation. @@ -12259,11 +12228,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) val = getU4LittleEndian(codeAddr); JITDUMP(" %08X", val); - if (tiVerificationNeeded) - { - Verify(info.compCompHnd->isValidStringRef(info.compScopeHnd, val), "bad string"); - tiRetVal = typeInfo(TI_REF, impGetStringClass()); - } impPushOnStack(gtNewSconNode(val, info.compScopeHnd), tiRetVal); break; @@ -12319,11 +12283,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) STARG: JITDUMP(" %u", lclNum); - if (tiVerificationNeeded) - { - Verify(lclNum < info.compILargsCount, "bad arg num"); - } - if (compIsForInlining()) { op1 = impInlineFetchArg(lclNum, impInlineInfo->inlArgInfo, impInlineInfo->lclVarInfo); @@ -12344,18 +12303,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // We should have seen this arg write in the prescan assert(lvaTable[lclNum].lvHasILStoreOp); - if (tiVerificationNeeded) - { - typeInfo& tiLclVar = lvaTable[lclNum].lvVerTypeInfo; - Verify(tiCompatibleWith(impStackTop().seTypeInfo, NormaliseForStack(tiLclVar), true), - "type mismatch"); - - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiLclVar.IsThisPtr(), "storing to uninit this ptr"); - } - } - goto VAR_ST; case CEE_STLOC: @@ -12379,14 +12326,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert(lclNum >= 0 && lclNum < 4); LOC_ST: - if (tiVerificationNeeded) - { - Verify(lclNum < info.compMethodInfo->locals.numArgs, "bad local num"); - Verify(tiCompatibleWith(impStackTop().seTypeInfo, - NormaliseForStack(lvaTable[lclNum + numArgs].lvVerTypeInfo), true), - "type mismatch"); - } - if (compIsForInlining()) { lclTyp = impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclTypeInfo; @@ -12404,7 +12343,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (lclNum >= info.compLocalsCount && lclNum != lvaArg0Var) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. BADCODE("Bad IL"); } @@ -12446,7 +12384,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Downcast the TYP_I_IMPL into a 32-bit Int for x86 JIT compatiblity if (varTypeIsI(op1->TypeGet()) && (genActualType(lclTyp) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op1 = gtNewCastNode(TYP_INT, op1, false, TYP_INT); } #endif // TARGET_64BIT @@ -12560,11 +12497,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclNum = getU1LittleEndian(codeAddr); LDLOCA: JITDUMP(" %u", lclNum); - if (tiVerificationNeeded) - { - Verify(lclNum < info.compMethodInfo->locals.numArgs, "bad local num"); - Verify(info.compInitMem, "initLocals not set"); - } if (compIsForInlining()) { @@ -12641,23 +12573,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert((op1->gtFlags & GTF_GLOB_REF) == 0); tiRetVal = lvaTable[lclNum].lvVerTypeInfo; - if (tiVerificationNeeded) - { - // Don't allow taking address of uninit this ptr. - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiRetVal.IsThisPtr(), "address of uninit this ptr"); - } - - if (!tiRetVal.IsByRef()) - { - tiRetVal.MakeByRef(); - } - else - { - Verify(false, "byref to byref"); - } - } impPushOnStack(op1, tiRetVal); break; @@ -12669,10 +12584,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("arglist in non-vararg method"); } - if (tiVerificationNeeded) - { - tiRetVal = typeInfo(TI_STRUCT, impGetRuntimeArgumentHandle()); - } assertImp((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_MASK) == CORINFO_CALLCONV_VARARG); /* The ARGLIST cookie is a hidden 'last' parameter, we have already @@ -12724,11 +12635,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("endfilter outside filter"); } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsType(TI_INT), "bad endfilt arg"); - } - op1 = impPopStack().val; assertImp(op1->gtType == TYP_INT); if (!bbInFilterILRange(block)) @@ -12767,11 +12673,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert(!compIsForInlining()); - if (tiVerificationNeeded) - { - Verify(false, "Invalid opcode: CEE_JMP"); - } - if ((info.compFlags & CORINFO_FLG_SYNCH) || block->hasTryIndex() || block->hasHndIndex()) { /* CEE_JMP does not make sense in some "protected" regions. */ @@ -12828,30 +12729,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) ldelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - - typeInfo arrayElemType = verMakeTypeInfo(ldelemClsHnd); - Verify(tiArray.IsNullObjRef() || - typeInfo::AreEquivalent(verGetArrayElemType(tiArray), arrayElemType), - "bad array"); - - tiRetVal = arrayElemType; - tiRetVal.MakeByRef(); - if (prefixFlags & PREFIX_READONLY) - { - tiRetVal.SetIsReadonlyByRef(); - } - - // an array interior pointer is always in the heap - tiRetVal.SetIsPermanentHomeByRef(); - } - // If it's a value class array we just do a simple address-of if (eeIsValueClass(ldelemClsHnd)) { @@ -12902,20 +12779,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) ldelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - tiRetVal = verMakeTypeInfo(ldelemClsHnd); - - Verify(tiArray.IsNullObjRef() || tiCompatibleWith(verGetArrayElemType(tiArray), tiRetVal, false), - "type of array incompatible with type operand"); - tiRetVal.NormaliseForStack(); - } - // If it's a reference type or generic variable type // then just generate code as though it's a ldelem.ref instruction if (!eeIsValueClass(ldelemClsHnd)) @@ -12971,47 +12834,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto ARR_LD; ARR_LD: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - if (tiArray.IsNullObjRef()) - { - if (lclTyp == TYP_REF) - { // we will say a deref of a null array yields a null ref - tiRetVal = typeInfo(TI_NULL); - } - else - { - tiRetVal = typeInfo(lclTyp); - } - } - else - { - tiRetVal = verGetArrayElemType(tiArray); - typeInfo arrayElemTi = typeInfo(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_LDELEM_I) - { - arrayElemTi = typeInfo::nativeInt(); - } - - if (lclTyp != TYP_REF && lclTyp != TYP_STRUCT) - { - Verify(typeInfo::AreEquivalent(tiRetVal, arrayElemTi), "bad array"); - } - else -#endif // TARGET_64BIT - { - Verify(tiRetVal.IsType(arrayElemTi.GetType()), "bad array"); - } - } - tiRetVal.NormaliseForStack(); - } ARR_LD_POST_VERIFY: /* Pull the index value and array address */ @@ -13106,22 +12928,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) stelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - typeInfo arrayElem = verMakeTypeInfo(stelemClsHnd); - - Verify(tiArray.IsNullObjRef() || tiCompatibleWith(arrayElem, verGetArrayElemType(tiArray), false), - "type operand incompatible with array element type"); - arrayElem.NormaliseForStack(); - Verify(tiCompatibleWith(tiValue, arrayElem, true), "value incompatible with type operand"); - } - // If it's a reference type just behave as though it's a stelem.ref instruction if (!eeIsValueClass(stelemClsHnd)) { @@ -13136,21 +12942,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } case CEE_STELEM_REF: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - Verify(tiValue.IsObjRef(), "bad value"); - - // we only check that it is an object referece, The helper does additional checks - Verify(tiArray.IsNullObjRef() || verGetArrayElemType(tiArray).IsType(TI_REF), "bad array"); - } - STELEM_REF_POST_VERIFY: if (opts.OptimizationEnabled()) @@ -13193,29 +12984,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto ARR_ST; ARR_ST: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - typeInfo arrayElem = typeInfo(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_STELEM_I) - { - arrayElem = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - Verify(tiArray.IsNullObjRef() || typeInfo::AreEquivalent(verGetArrayElemType(tiArray), arrayElem), - "bad array"); - - Verify(tiCompatibleWith(NormaliseForStack(tiValue), arrayElem.NormaliseForStack(), true), - "bad value"); - } - ARR_ST_POST_VERIFY: /* The strict order of evaluation is LHS-operands, RHS-operands, range-check, and then assignment. However, codegen currently @@ -13382,33 +13150,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Pull two values and push back the result */ - if (tiVerificationNeeded) - { - const typeInfo& tiOp1 = impStackTop(1).seTypeInfo; - const typeInfo& tiOp2 = impStackTop().seTypeInfo; - - Verify(tiCompatibleWith(tiOp1, tiOp2, true), "different arg type"); - if (oper == GT_ADD || oper == GT_DIV || oper == GT_SUB || oper == GT_MUL || oper == GT_MOD) - { - Verify(tiOp1.IsNumberType(), "not number"); - } - else - { - Verify(tiOp1.IsIntegerType(), "not integer"); - } - - Verify(!ovfl || tiOp1.IsIntegerType(), "not integer"); - - tiRetVal = tiOp1; - -#ifdef TARGET_64BIT - if (tiOp2.IsNativeIntType()) - { - tiRetVal = tiOp2; - } -#endif // TARGET_64BIT - } - op2 = impPopStack().val; op1 = impPopStack().val; @@ -13513,13 +13254,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto CEE_SH_OP2; CEE_SH_OP2: - if (tiVerificationNeeded) - { - const typeInfo& tiVal = impStackTop(1).seTypeInfo; - const typeInfo& tiShift = impStackTop(0).seTypeInfo; - Verify(tiVal.IsIntegerType() && tiShift.IsType(TI_INT), "Bad shift args"); - tiRetVal = tiVal; - } op2 = impPopStack().val; op1 = impPopStack().val; // operand to be shifted impBashVarAddrsToI(op1, op2); @@ -13531,12 +13265,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_NOT: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsIntegerType(), "bad int value"); - } - op1 = impPopStack().val; impBashVarAddrsToI(op1, nullptr); type = genActualType(op1->TypeGet()); @@ -13544,11 +13272,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_CKFINITE: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsType(TI_DOUBLE), "bad R value"); - } op1 = impPopStack().val; type = op1->TypeGet(); op1 = gtNewOperNode(GT_CKFINITE, type, op1); @@ -13605,12 +13328,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_BRFALSE_S: /* Pop the comparand (now there's a neat term) from the stack */ - if (tiVerificationNeeded) - { - typeInfo& tiVal = impStackTop().seTypeInfo; - Verify(tiVal.IsObjRef() || tiVal.IsByRef() || tiVal.IsIntegerType() || tiVal.IsMethod(), - "bad value"); - } op1 = impPopStack().val; type = op1->TypeGet(); @@ -13733,12 +13450,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto CMP_2_OPs; CMP_2_OPs: - if (tiVerificationNeeded) - { - verVerifyCond(impStackTop(1).seTypeInfo, impStackTop().seTypeInfo, opcode); - tiRetVal = typeInfo(TI_INT); - } - op2 = impPopStack().val; op1 = impPopStack().val; @@ -13841,15 +13552,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) unordered = false; goto CMP_2_OPs_AND_BR_ALL; CMP_2_OPs_AND_BR_ALL: - - if (tiVerificationNeeded) - { - verVerifyCond(impStackTop(1).seTypeInfo, impStackTop().seTypeInfo, opcode); - } - - /* Pull two values */ - op2 = impPopStack().val; - op1 = impPopStack().val; + /* Pull two values */ + op2 = impPopStack().val; + op1 = impPopStack().val; #ifdef TARGET_64BIT if ((op1->TypeGet() == TYP_I_IMPL) && (genActualType(op2->TypeGet()) == TYP_INT)) @@ -13934,10 +13639,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto COND_JUMP; case CEE_SWITCH: - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsType(TI_INT), "Bad switch val"); - } /* Pop the switch value off the stack */ op1 = impPopStack().val; assertImp(genActualTypeIsIntOrI(op1->TypeGet())); @@ -14088,40 +13789,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto _CONV; _CONV: - // just check that we have a number on the stack - if (tiVerificationNeeded) - { - const typeInfo& tiVal = impStackTop().seTypeInfo; - Verify(tiVal.IsNumberType(), "bad arg"); - -#ifdef TARGET_64BIT - bool isNative = false; - - switch (opcode) - { - case CEE_CONV_OVF_I: - case CEE_CONV_OVF_I_UN: - case CEE_CONV_I: - case CEE_CONV_OVF_U: - case CEE_CONV_OVF_U_UN: - case CEE_CONV_U: - isNative = true; - break; - default: - // leave 'isNative' = false; - break; - } - if (isNative) - { - tiRetVal = typeInfo::nativeInt(); - } - else -#endif // TARGET_64BIT - { - tiRetVal = typeInfo(lclTyp).NormaliseForStack(); - } - } - // only converts from FLOAT or DOUBLE to an integer type // and converts from ULONG (or LONG on ARM) to DOUBLE are morphed to calls @@ -14237,12 +13904,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_NEG: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsNumberType(), "Bad arg"); - } - op1 = impPopStack().val; impBashVarAddrsToI(op1, nullptr); impPushOnStack(gtNewOperNode(GT_NEG, genActualType(op1->gtType), op1), tiRetVal); @@ -14331,22 +13992,40 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_DUP: { - if (tiVerificationNeeded) - { - // Dup could start the beginning of delegate creation sequence, remember that - delegateCreateStart = codeAddr - 1; - impStackTop(0); - } - - // If the expression to dup is simple, just clone it. - // Otherwise spill it to a temp, and reload the temp - // twice. StackEntry se = impPopStack(); GenTree* tree = se.val; tiRetVal = se.seTypeInfo; op1 = tree; - if (!opts.compDbgCode && !op1->IsIntegralConst(0) && !op1->IsFPZero() && !op1->IsLocal()) + // If the expression to dup is simple, just clone it. + // Otherwise spill it to a temp, and reload the temp twice. + bool cloneExpr = false; + + if (!opts.compDbgCode) + { + // Duplicate 0 and +0.0 + if (op1->IsIntegralConst(0) || op1->IsFloatPositiveZero()) + { + cloneExpr = true; + } + // Duplicate locals and addresses of them + else if (op1->IsLocal()) + { + cloneExpr = true; + } + else if (op1->TypeIs(TYP_BYREF) && op1->OperIs(GT_ADDR) && op1->gtGetOp1()->IsLocal() && + (OPCODE)impGetNonPrefixOpcode(codeAddr + sz, codeEndp) != CEE_INITOBJ) + { + cloneExpr = true; + } + } + else + { + // Always clone for debug mode + cloneExpr = true; + } + + if (!cloneExpr) { const unsigned tmpNum = lvaGrabTemp(true DEBUGARG("dup spill")); impAssignTempGen(tmpNum, op1, tiRetVal.GetClassHandle(), (unsigned)CHECK_SPILL_ALL); @@ -14397,22 +14076,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_DOUBLE; goto STIND; STIND: - - if (tiVerificationNeeded) - { - typeInfo instrType(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_STIND_I) - { - instrType = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - verVerifySTIND(impStackTop(1).seTypeInfo, impStackTop(0).seTypeInfo, instrType); - } - else - { - compUnsafeCastUsed = true; // Have to go conservative - } + compUnsafeCastUsed = true; // Have to go conservative STIND_POST_VERIFY: @@ -14438,14 +14102,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) // if (varTypeIsI(op2->gtType) && (genActualType(lclTyp) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op2 = gtNewCastNode(TYP_INT, op2, false, TYP_INT); } // Allow an upcast of op2 from a 32-bit Int into TYP_I_IMPL for x86 JIT compatiblity // if (varTypeIsI(lclTyp) && (genActualType(op2->gtType) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op2 = gtNewCastNode(TYP_I_IMPL, op2, false, TYP_I_IMPL); } } @@ -14540,23 +14202,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_USHORT; goto LDIND; LDIND: - - if (tiVerificationNeeded) - { - typeInfo lclTiType(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_LDIND_I) - { - lclTiType = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - tiRetVal = verVerifyLDIND(impStackTop().seTypeInfo, lclTiType); - tiRetVal.NormaliseForStack(); - } - else - { - compUnsafeCastUsed = true; // Have to go conservative - } + compUnsafeCastUsed = true; // Have to go conservative LDIND_POST_VERIFY: @@ -14568,7 +14214,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // if (genActualType(op1->gtType) == TYP_INT) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op1 = gtNewCastNode(TYP_I_IMPL, op1, false, TYP_I_IMPL); } #endif @@ -14638,8 +14283,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); eeGetCallInfo(&resolvedToken, (prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr, - addVerifyFlag(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN)), - &callInfo); + combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), &callInfo); // This check really only applies to intrinsic Array.Address methods if (callInfo.sig.callConv & CORINFO_CALLCONV_PARAMTYPE) @@ -14650,22 +14294,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Do this before DO_LDFTN since CEE_LDVIRTFN does it on its own. impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper); - if (tiVerificationNeeded) - { - // LDFTN could start the beginning of delegate creation sequence, remember that - delegateCreateStart = codeAddr - 2; - - // check any constraints on the callee's class and type parameters - VerifyOrReturn(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "method has unsatisfied class constraints"); - VerifyOrReturn(info.compCompHnd->satisfiesMethodConstraints(resolvedToken.hClass, - resolvedToken.hMethod), - "method has unsatisfied method constraints"); - - mflags = callInfo.verMethodFlags; - Verify(!(mflags & CORINFO_FLG_CONSTRUCTOR), "LDFTN on a constructor"); - } - DO_LDFTN: op1 = impMethodPointer(&resolvedToken, &callInfo); @@ -14693,8 +14321,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); eeGetCallInfo(&resolvedToken, nullptr /* constraint typeRef */, - addVerifyFlag(combine(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), - CORINFO_CALLINFO_CALLVIRT)), + combine(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), + CORINFO_CALLINFO_CALLVIRT), &callInfo); // This check really only applies to intrinsic Array.Address methods @@ -14718,40 +14346,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) CORINFO_SIG_INFO& ftnSig = callInfo.sig; - if (tiVerificationNeeded) - { - - Verify(ftnSig.hasThis(), "ldvirtftn on a static method"); - Verify(!(mflags & CORINFO_FLG_CONSTRUCTOR), "LDVIRTFTN on a constructor"); - - // JIT32 verifier rejects verifiable ldvirtftn pattern - typeInfo declType = - verMakeTypeInfo(resolvedToken.hClass, true); // Change TI_STRUCT to TI_REF when necessary - - typeInfo arg = impStackTop().seTypeInfo; - Verify((arg.IsType(TI_REF) || arg.IsType(TI_NULL)) && tiCompatibleWith(arg, declType, true), - "bad ldvirtftn"); - - CORINFO_CLASS_HANDLE instanceClassHnd = info.compClassHnd; - if (!(arg.IsType(TI_NULL) || (mflags & CORINFO_FLG_STATIC))) - { - instanceClassHnd = arg.GetClassHandleForObjRef(); - } - - // check any constraints on the method's class and type parameters - VerifyOrReturn(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "method has unsatisfied class constraints"); - VerifyOrReturn(info.compCompHnd->satisfiesMethodConstraints(resolvedToken.hClass, - resolvedToken.hMethod), - "method has unsatisfied method constraints"); - - if (mflags & CORINFO_FLG_PROTECTED) - { - Verify(info.compCompHnd->canAccessFamily(info.compMethodHnd, instanceClassHnd), - "Accessing protected method through wrong type."); - } - } - /* Get the object-ref */ op1 = impPopStack().val; assertImp(op1->gtType == TYP_REF); @@ -14864,8 +14458,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) _impResolveToken(CORINFO_TOKENKIND_NewObj); eeGetCallInfo(&resolvedToken, nullptr /* constraint typeRef*/, - addVerifyFlag(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_ALLOWINSTPARAM)), - &callInfo); + combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_ALLOWINSTPARAM), &callInfo); if (compIsForInlining()) { @@ -14899,19 +14492,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) clsFlags = callInfo.classFlags; if (clsFlags & CORINFO_FLG_ARRAY) { - if (tiVerificationNeeded) - { - CORINFO_CLASS_HANDLE elemTypeHnd; - INDEBUG(CorInfoType corType =) - info.compCompHnd->getChildType(resolvedToken.hClass, &elemTypeHnd); - assert(!(elemTypeHnd == nullptr && corType == CORINFO_TYPE_VALUECLASS)); - Verify(elemTypeHnd == nullptr || - !(info.compCompHnd->getClassAttribs(elemTypeHnd) & CORINFO_FLG_BYREF_LIKE), - "newarr of byref-like objects"); - verVerifyCall(opcode, &resolvedToken, nullptr, ((prefixFlags & PREFIX_TAILCALL_EXPLICIT) != 0), - ((prefixFlags & PREFIX_READONLY) != 0), delegateCreateStart, codeAddr - 1, - &callInfo DEBUGARG(info.compFullName)); - } // Arrays need to call the NEWOBJ helper. assertImp(clsFlags & CORINFO_FLG_VAROBJSIZE); @@ -15103,10 +14683,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) eeGetCallInfo(&resolvedToken, (prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr, // this is how impImportCall invokes getCallInfo - addVerifyFlag( - combine(combine(CORINFO_CALLINFO_ALLOWINSTPARAM, CORINFO_CALLINFO_SECURITYCHECKS), - (opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT - : CORINFO_CALLINFO_NONE)), + combine(combine(CORINFO_CALLINFO_ALLOWINSTPARAM, CORINFO_CALLINFO_SECURITYCHECKS), + (opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT : CORINFO_CALLINFO_NONE), &callInfo); } else @@ -15247,13 +14825,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper); } - if (tiVerificationNeeded) - { - verVerifyCall(opcode, &resolvedToken, constraintCall ? &constrainedResolvedToken : nullptr, - explicitTailCall, readonlyCall, delegateCreateStart, codeAddr - 1, - &callInfo DEBUGARG(info.compFullName)); - } - callTyp = impImportCall(opcode, &resolvedToken, constraintCall ? &constrainedResolvedToken : nullptr, newObjThisPtr, prefixFlags, &callInfo, opcodeOffs); if (compDonotInline()) @@ -15373,45 +14944,10 @@ void Compiler::impImportBlockCode(BasicBlock* block) // SkipVerification. impHandleAccessAllowed(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper); - if (tiVerificationNeeded) + // Raise InvalidProgramException if static load accesses non-static field + if (isLoadStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) { - // You can also pass the unboxed struct to LDFLD - bool bAllowPlainValueTypeAsThis = false; - if (opcode == CEE_LDFLD && impIsValueType(tiObj)) - { - bAllowPlainValueTypeAsThis = true; - } - - verVerifyField(&resolvedToken, fieldInfo, tiObj, isLoadAddress, bAllowPlainValueTypeAsThis); - - // If we're doing this on a heap object or from a 'safe' byref - // then the result is a safe byref too - if (isLoadAddress) // load address - { - if (fieldInfo.fieldFlags & - CORINFO_FLG_FIELD_STATIC) // statics marked as safe will have permanent home - { - if (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN) - { - tiRetVal.SetIsPermanentHomeByRef(); - } - } - else if (tiObj->IsObjRef() || tiObj->IsPermanentHomeByRef()) - { - // ldflda of byref is safe if done on a gc object or on a - // safe byref - tiRetVal.SetIsPermanentHomeByRef(); - } - } - } - else - { - // tiVerificationNeeded is false. - // Raise InvalidProgramException if static load accesses non-static field - if (isLoadStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) - { - BADCODE("static access on an instance field"); - } + BADCODE("static access on an instance field"); } // We are using ldfld/a on a static field. We allow it, but need to get side-effect from obj. @@ -15726,20 +15262,10 @@ void Compiler::impImportBlockCode(BasicBlock* block) impHandleAccessAllowed(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper); - if (tiVerificationNeeded) + // Raise InvalidProgramException if static store accesses non-static field + if (isStoreStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) { - verVerifyField(&resolvedToken, fieldInfo, tiObj, true); - typeInfo fieldType = verMakeTypeInfo(ciType, fieldClsHnd); - Verify(tiCompatibleWith(tiVal, fieldType.NormaliseForStack(), true), "type mismatch"); - } - else - { - // tiVerificationNeed is false. - // Raise InvalidProgramException if static store accesses non-static field - if (isStoreStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) - { - BADCODE("static access on an instance field"); - } + BADCODE("static access on an instance field"); } // We are using stfld on a static field. @@ -16004,18 +15530,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - // As per ECMA 'numElems' specified can be either int32 or native int. - Verify(impStackTop().seTypeInfo.IsIntOrNativeIntType(), "bad bound"); - - CORINFO_CLASS_HANDLE elemTypeHnd; - info.compCompHnd->getChildType(resolvedToken.hClass, &elemTypeHnd); - Verify(elemTypeHnd == nullptr || - !(info.compCompHnd->getClassAttribs(elemTypeHnd) & CORINFO_FLG_BYREF_LIKE), - "array of byref-like type"); - } - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); accessAllowedResult = @@ -16096,11 +15610,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_LOCALLOC: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } - // We don't allow locallocs inside handlers if (block->hasHndIndex()) { @@ -16226,12 +15735,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsObjRef(), "obj reference needed"); - // Even if this is a value class, we know it is boxed. - tiRetVal = typeInfo(TI_REF, resolvedToken.hClass); - } accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16303,13 +15806,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; } - if (tiVerificationNeeded) - { - Verify(typeInfo::AreEquivalent(impStackTop().seTypeInfo, verMakeTypeInfo(impGetRefAnyClass())), - "need refany"); - tiRetVal = verMakeTypeInfo(resolvedToken.hClass).MakeByRef(); - } - op1 = impPopStack().val; // make certain it is normalized; op1 = impNormStructVal(op1, impGetRefAnyClass(), (unsigned)CHECK_SPILL_ALL); @@ -16322,12 +15818,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_REFANYTYPE: - if (tiVerificationNeeded) - { - Verify(typeInfo::AreEquivalent(impStackTop().seTypeInfo, verMakeTypeInfo(impGetRefAnyClass())), - "need refany"); - } - op1 = impPopStack().val; // make certain it is normalized; @@ -16451,13 +15941,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (opcode == CEE_UNBOX_ANY && !eeIsValueClass(resolvedToken.hClass)) { - if (tiVerificationNeeded) - { - typeInfo tiUnbox = impStackTop().seTypeInfo; - Verify(tiUnbox.IsObjRef(), "bad unbox.any arg"); - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - tiRetVal.NormaliseForStack(); - } JITDUMP("\n Importing UNBOX.ANY(refClass) as CASTCLASS\n"); op1 = impPopStack().val; goto CASTCLASS; @@ -16468,19 +15951,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* (non-byref) type, but here we're making the tiRetVal that is used */ /* for the intermediate pointer which we then transfer onto the OBJ */ /* instruction. OBJ then creates the appropriate tiRetVal. */ - if (tiVerificationNeeded) - { - typeInfo tiUnbox = impStackTop().seTypeInfo; - Verify(tiUnbox.IsObjRef(), "Bad unbox arg"); - - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - Verify(tiRetVal.IsValueClass(), "not value class"); - tiRetVal.MakeByRef(); - - // We always come from an objref, so this is safe byref - tiRetVal.SetIsPermanentHomeByRef(); - tiRetVal.SetIsReadonlyByRef(); - } op1 = impPopStack().val; assertImp(op1->gtType == TYP_REF); @@ -16649,7 +16119,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } assert(op1->gtType == TYP_BYREF); - assert(!tiVerificationNeeded || tiRetVal.IsByRef()); } else { @@ -16694,7 +16163,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) oper = GT_OBJ; assert(op1->gtType == TYP_BYREF); - assert(!tiVerificationNeeded || tiRetVal.IsByRef()); goto OBJ; } @@ -16723,29 +16191,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiActual = impStackTop().seTypeInfo; - typeInfo tiBox = verMakeTypeInfo(resolvedToken.hClass); - - Verify(verIsBoxable(tiBox), "boxable type expected"); - - // check the class constraints of the boxed type in case we are boxing an uninitialized value - Verify(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "boxed type has unsatisfied class constraints"); - - Verify(tiCompatibleWith(tiActual, tiBox.NormaliseForStack(), true), "type mismatch"); - - // Observation: the following code introduces a boxed value class on the stack, but, - // according to the ECMA spec, one would simply expect: tiRetVal = - // typeInfo(TI_REF,impGetObjectClass()); - - // Push the result back on the stack, - // even if clsHnd is a value class we want the TI_REF - // we call back to the EE to get find out what hte type we should push (for nullable we push T) - tiRetVal = typeInfo(TI_REF, info.compCompHnd->getTypeForBox(resolvedToken.hClass)); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16786,11 +16231,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - tiRetVal = typeInfo(TI_INT); - } - op1 = gtNewIconNode(info.compCompHnd->getClassSize(resolvedToken.hClass)); impPushOnStack(op1, tiRetVal); break; @@ -16814,13 +16254,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsObjRef(), "object ref expected"); - // box it - tiRetVal = typeInfo(TI_REF, resolvedToken.hClass); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16887,16 +16320,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_THROW: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsObjRef(), "object ref expected"); - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiRetVal.IsThisPtr(), "throw uninitialized this"); - } - } - // Any block with a throw is rarely executed. block->bbSetRunRarely(); @@ -16924,22 +16347,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("rethrow outside catch"); } - if (tiVerificationNeeded) - { - Verify(block->hasHndIndex(), "rethrow outside catch"); - if (block->hasHndIndex()) - { - EHblkDsc* HBtab = ehGetDsc(block->getHndIndex()); - Verify(!HBtab->HasFinallyOrFaultHandler(), "rethrow in finally or fault"); - if (HBtab->HasFilter()) - { - // we better be in the handler clause part, not the filter part - Verify(jitIsBetween(compCurBB->bbCodeOffs, HBtab->ebdHndBegOffs(), HBtab->ebdHndEndOffs()), - "rethrow in filter"); - } - } - } - /* Create the 'rethrow' helper call */ op1 = gtNewHelperCallNode(CORINFO_HELP_RETHROW, TYP_VOID); @@ -16954,18 +16361,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiTo = impStackTop().seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(tiTo.IsByRef(), "byref expected"); - Verify(!tiTo.IsReadonlyByRef(), "write to readonly byref"); - - Verify(tiCompatibleWith(tiInstr, tiTo.DereferenceByRef(), false), - "type operand incompatible with type of address"); - } - op2 = gtNewIconNode(0); // Value op1 = impPopStack().val; // Dest @@ -16989,59 +16384,66 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_INITBLK: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } - op3 = impPopStack().val; // Size op2 = impPopStack().val; // Value - op1 = impPopStack().val; // Dest + op1 = impPopStack().val; // Dst addr if (op3->IsCnsIntOrI()) { size = (unsigned)op3->AsIntConCommon()->IconValue(); op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size)); + op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false); } else { - op1 = new (this, GT_DYN_BLK) GenTreeDynBlk(op1, op3); + if (!op2->IsIntegralConst(0)) + { + op2 = gtNewOperNode(GT_INIT_VAL, TYP_INT, op2); + } + + op1 = new (this, GT_STORE_DYN_BLK) GenTreeStoreDynBlk(op1, op2, op3); size = 0; + + if ((prefixFlags & PREFIX_VOLATILE) != 0) + { + op1->gtFlags |= GTF_BLK_VOLATILE; + } } - op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false); goto SPILL_APPEND; case CEE_CPBLK: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } op3 = impPopStack().val; // Size - op2 = impPopStack().val; // Src - op1 = impPopStack().val; // Dest + op2 = impPopStack().val; // Src addr + op1 = impPopStack().val; // Dst addr - if (op3->IsCnsIntOrI()) + if (op2->OperGet() == GT_ADDR) { - size = (unsigned)op3->AsIntConCommon()->IconValue(); - op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size)); + op2 = op2->AsOp()->gtOp1; } else { - op1 = new (this, GT_DYN_BLK) GenTreeDynBlk(op1, op3); - size = 0; + op2 = gtNewOperNode(GT_IND, TYP_STRUCT, op2); } - if (op2->OperGet() == GT_ADDR) + + if (op3->IsCnsIntOrI()) { - op2 = op2->AsOp()->gtOp1; + size = (unsigned)op3->AsIntConCommon()->IconValue(); + op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size)); + op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, true); } else { - op2 = gtNewOperNode(GT_IND, TYP_STRUCT, op2); + op1 = new (this, GT_STORE_DYN_BLK) GenTreeStoreDynBlk(op1, op2, op3); + size = 0; + + if ((prefixFlags & PREFIX_VOLATILE) != 0) + { + op1->gtFlags |= GTF_BLK_VOLATILE; + } } - op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, true); goto SPILL_APPEND; case CEE_CPOBJ: @@ -17052,22 +16454,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiFrom = impStackTop().seTypeInfo; - typeInfo tiTo = impStackTop(1).seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(tiFrom.IsByRef(), "expected byref source"); - Verify(tiTo.IsByRef(), "expected byref destination"); - - Verify(tiCompatibleWith(tiFrom.DereferenceByRef(), tiInstr, false), - "type of source address incompatible with type operand"); - Verify(!tiTo.IsReadonlyByRef(), "write to readonly byref"); - Verify(tiCompatibleWith(tiInstr, tiTo.DereferenceByRef(), false), - "type operand incompatible with type of destination address"); - } - if (!eeIsValueClass(resolvedToken.hClass)) { op1 = impPopStack().val; // address to load from @@ -17107,38 +16493,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_REF; } - if (tiVerificationNeeded) - { - - typeInfo tiPtr = impStackTop(1).seTypeInfo; - - // Make sure we have a good looking byref - Verify(tiPtr.IsByRef(), "pointer not byref"); - Verify(!tiPtr.IsReadonlyByRef(), "write to readonly byref"); - if (!tiPtr.IsByRef() || tiPtr.IsReadonlyByRef()) - { - compUnsafeCastUsed = true; - } - - typeInfo ptrVal = DereferenceByRef(tiPtr); - typeInfo argVal = verMakeTypeInfo(resolvedToken.hClass); - - if (!tiCompatibleWith(impStackTop(0).seTypeInfo, NormaliseForStack(argVal), true)) - { - Verify(false, "type of value incompatible with type operand"); - compUnsafeCastUsed = true; - } - - if (!tiCompatibleWith(argVal, ptrVal, false)) - { - Verify(false, "type operand incompatible with type of address"); - compUnsafeCastUsed = true; - } - } - else - { - compUnsafeCastUsed = true; - } + compUnsafeCastUsed = true; if (lclTyp == TYP_REF) { @@ -17190,16 +16545,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; } - if (tiVerificationNeeded) - { - typeInfo tiPtr = impStackTop().seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(!verIsByRefLike(tiInstr), "mkrefany of byref-like class"); - Verify(!tiPtr.IsReadonlyByRef(), "readonly byref used with mkrefany"); - Verify(typeInfo::AreEquivalent(tiPtr.DereferenceByRef(), tiInstr), "type mismatch"); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -17229,29 +16574,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - if (tiVerificationNeeded) - { - typeInfo tiPtr = impStackTop().seTypeInfo; - - // Make sure we have a byref - if (!tiPtr.IsByRef()) - { - Verify(false, "pointer not byref"); - compUnsafeCastUsed = true; - } - typeInfo tiPtrVal = DereferenceByRef(tiPtr); - - if (!tiCompatibleWith(tiPtrVal, tiRetVal, false)) - { - Verify(false, "type of address incompatible with type operand"); - compUnsafeCastUsed = true; - } - tiRetVal.NormaliseForStack(); - } - else - { - compUnsafeCastUsed = true; - } + compUnsafeCastUsed = true; if (eeIsValueClass(resolvedToken.hClass)) { @@ -17295,13 +16618,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } case CEE_LDLEN: - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop().seTypeInfo; - Verify(verIsSDArray(tiArray), "bad array"); - tiRetVal = typeInfo(TI_INT); - } - op1 = impPopStack().val; if (opts.OptimizationEnabled()) { @@ -17455,12 +16771,6 @@ void Compiler::impLoadArg(unsigned ilArgNum, IL_OFFSET offset) // It will be mapped to the correct lvaTable index void Compiler::impLoadLoc(unsigned ilLclNum, IL_OFFSET offset) { - if (tiVerificationNeeded) - { - Verify(ilLclNum < info.compMethodInfo->locals.numArgs, "bad loc num"); - Verify(info.compInitMem, "initLocals not set"); - } - if (compIsForInlining()) { if (ilLclNum >= info.compMethodInfo->locals.numArgs) @@ -17583,25 +16893,6 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) { const bool isTailCall = (prefixFlags & PREFIX_TAILCALL) != 0; - if (tiVerificationNeeded) - { - verVerifyThisPtrInitialised(); - - unsigned expectedStack = 0; - if (info.compRetType != TYP_VOID) - { - typeInfo tiVal = impStackTop().seTypeInfo; - typeInfo tiDeclared = - verMakeTypeInfo(info.compMethodInfo->args.retType, info.compMethodInfo->args.retTypeClass); - - Verify(!verIsByRefLike(tiDeclared) || verIsSafeToReturnByRef(tiVal), "byref return"); - - Verify(tiCompatibleWith(tiVal, tiDeclared.NormaliseForStack(), true), "type mismatch"); - expectedStack = 1; - } - Verify(verCurrentState.esStackDepth == expectedStack, "stack non-empty on return"); - } - #ifdef DEBUG // If we are importing an inlinee and have GC ref locals we always // need to have a spill temp for the return value. This temp @@ -18470,27 +17761,6 @@ void Compiler::impImportBlock(BasicBlock* block) #ifdef TARGET_64BIT if (genActualType(tree->gtType) == TYP_I_IMPL && lvaTable[tempNum].lvType == TYP_INT) { - if (tiVerificationNeeded && tgtBlock->bbEntryState != nullptr && - (tgtBlock->bbFlags & BBF_FAILED_VERIFICATION) == 0) - { - // Merge the current state into the entry state of block; - // the call to verMergeEntryStates must have changed - // the entry state of the block by merging the int local var - // and the native-int stack entry. - bool changed = false; - if (verMergeEntryStates(tgtBlock, &changed)) - { - impRetypeEntryStateTemps(tgtBlock); - impReimportBlockPending(tgtBlock); - assert(changed); - } - else - { - tgtBlock->bbFlags |= BBF_FAILED_VERIFICATION; - break; - } - } - // Some other block in the spill clique set this to "int", but now we have "native int". // Change the type and go back to re-import any blocks that used the wrong type. lvaTable[tempNum].lvType = TYP_I_IMPL; @@ -18511,22 +17781,20 @@ void Compiler::impImportBlock(BasicBlock* block) // imported already, we need to change the type of the local and reimport the spill clique. // If the 'byref' side has imported, we insert a cast from int to 'native int' to match // the 'byref' size. - if (!tiVerificationNeeded) + if (genActualType(tree->gtType) == TYP_BYREF && lvaTable[tempNum].lvType == TYP_INT) { - if (genActualType(tree->gtType) == TYP_BYREF && lvaTable[tempNum].lvType == TYP_INT) - { - // Some other block in the spill clique set this to "int", but now we have "byref". - // Change the type and go back to re-import any blocks that used the wrong type. - lvaTable[tempNum].lvType = TYP_BYREF; - reimportSpillClique = true; - } - else if (genActualType(tree->gtType) == TYP_INT && lvaTable[tempNum].lvType == TYP_BYREF) - { - // Spill clique has decided this should be "byref", but this block only pushes an "int". - // Insert a sign-extension to "native int" so we match the clique size. - verCurrentState.esStack[level].val = gtNewCastNode(TYP_I_IMPL, tree, false, TYP_I_IMPL); - } + // Some other block in the spill clique set this to "int", but now we have "byref". + // Change the type and go back to re-import any blocks that used the wrong type. + lvaTable[tempNum].lvType = TYP_BYREF; + reimportSpillClique = true; } + else if (genActualType(tree->gtType) == TYP_INT && lvaTable[tempNum].lvType == TYP_BYREF) + { + // Spill clique has decided this should be "byref", but this block only pushes an "int". + // Insert a sign-extension to "native int" so we match the clique size. + verCurrentState.esStack[level].val = gtNewCastNode(TYP_I_IMPL, tree, false, TYP_I_IMPL); + } + #endif // TARGET_64BIT if (tree->gtType == TYP_DOUBLE && lvaTable[tempNum].lvType == TYP_FLOAT) @@ -18710,25 +17978,6 @@ void Compiler::impImportBlockPending(BasicBlock* block) #endif } - // Additionally, if we need to verify, merge the verification state. - if (tiVerificationNeeded) - { - // Merge the current state into the entry state of block; if this does not change the entry state - // by merging, do not add the block to the pending-list. - bool changed = false; - if (!verMergeEntryStates(block, &changed)) - { - block->bbFlags |= BBF_FAILED_VERIFICATION; - addToPending = true; // We will pop it off, and check the flag set above. - } - else if (changed) - { - addToPending = true; - - JITDUMP("Adding " FMT_BB " to pending set due to new merge result\n", block->bbNum); - } - } - if (!addToPending) { return; @@ -19180,16 +18429,6 @@ void Compiler::verInitCurrentState() verTrackObjCtorInitState = false; verCurrentState.thisInitialized = TIS_Bottom; - if (tiVerificationNeeded) - { - // Track this ptr initialization - if (!info.compIsStatic && (info.compFlags & CORINFO_FLG_CONSTRUCTOR) && lvaTable[0].lvVerTypeInfo.IsObjRef()) - { - verTrackObjCtorInitState = true; - verCurrentState.thisInitialized = TIS_Uninit; - } - } - // initialize stack info verCurrentState.esStackDepth = 0; @@ -19370,22 +18609,8 @@ void Compiler::impImport() if (dsc->pdBB->bbFlags & BBF_FAILED_VERIFICATION) { - -#ifdef TARGET_64BIT - // On AMD64, during verification we have to match JIT64 behavior since the VM is very tighly - // coupled with the JIT64 IL Verification logic. Look inside verHandleVerificationFailure - // method for further explanation on why we raise this exception instead of making the jitted - // code throw the verification exception during execution. - if (tiVerificationNeeded && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IMPORT_ONLY)) - { - BADCODE("Basic block marked as not verifiable"); - } - else -#endif // TARGET_64BIT - { - verConvertBBToThrowVerificationException(dsc->pdBB DEBUGARG(true)); - impEndTreeList(dsc->pdBB); - } + verConvertBBToThrowVerificationException(dsc->pdBB DEBUGARG(true)); + impEndTreeList(dsc->pdBB); } else { @@ -19395,7 +18620,7 @@ void Compiler::impImport() { return; } - if (compIsForImportOnly() && !tiVerificationNeeded) + if (compIsForImportOnly()) { return; } @@ -19416,8 +18641,6 @@ void Compiler::impImport() block->bbFlags &= ~BBF_VISITED; } #endif - - assert(!compIsForInlining() || !tiVerificationNeeded); } // Checks if a typeinfo (usually stored in the type stack) is a struct. @@ -19466,7 +18689,10 @@ bool Compiler::impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut) if (op->gtOper == GT_LCL_VAR) { - *lclVarTreeOut = op; + if (lclVarTreeOut != nullptr) + { + *lclVarTreeOut = op; + } return true; } else @@ -22134,7 +21360,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // Look up the new call info. CORINFO_CALL_INFO derivedCallInfo; - eeGetCallInfo(pDerivedResolvedToken, nullptr, addVerifyFlag(CORINFO_CALLINFO_ALLOWINSTPARAM), &derivedCallInfo); + eeGetCallInfo(pDerivedResolvedToken, nullptr, CORINFO_CALLINFO_ALLOWINSTPARAM, &derivedCallInfo); // Update the call. call->gtCallMoreFlags &= ~GTF_CALL_M_VIRTSTUB_REL_INDIRECT; diff --git a/src/coreclr/jit/inline.def b/src/coreclr/jit/inline.def index a28daf4e980fd..a519471a3caec 100644 --- a/src/coreclr/jit/inline.def +++ b/src/coreclr/jit/inline.def @@ -70,6 +70,8 @@ INLINE_OBSERVATION(ARG_FEEDS_CONSTANT_TEST, bool, "argument feeds constant t INLINE_OBSERVATION(ARG_FEEDS_TEST, bool, "argument feeds test", INFORMATION, CALLEE) INLINE_OBSERVATION(ARG_FEEDS_CAST, int, "argument feeds castclass or isinst", INFORMATION, CALLEE) INLINE_OBSERVATION(ARG_FEEDS_RANGE_CHECK, bool, "argument feeds range check", INFORMATION, CALLEE) +INLINE_OBSERVATION(ARG_FEEDS_ISCONST, bool, "argument feeds IsKnownConstant", INFORMATION, CALLEE) +INLINE_OBSERVATION(CONST_ARG_FEEDS_ISCONST, bool, "const argument feeds IsKnownConstant", INFORMATION, CALLEE) INLINE_OBSERVATION(ARG_STRUCT, int, "arg is a struct passed by value", INFORMATION, CALLEE) INLINE_OBSERVATION(RETURNS_STRUCT, bool, "returns a struct by value", INFORMATION, CALLEE) INLINE_OBSERVATION(ARG_STRUCT_FIELD_ACCESS, int, "ldfld/stfld over arg (struct)", INFORMATION, CALLEE) diff --git a/src/coreclr/jit/inlinepolicy.cpp b/src/coreclr/jit/inlinepolicy.cpp index 1ec47378872d5..0ea9135b82c24 100644 --- a/src/coreclr/jit/inlinepolicy.cpp +++ b/src/coreclr/jit/inlinepolicy.cpp @@ -326,6 +326,14 @@ void DefaultPolicy::NoteBool(InlineObservation obs, bool value) m_ArgFeedsRangeCheck++; break; + case InlineObservation::CALLEE_CONST_ARG_FEEDS_ISCONST: + m_ConstArgFeedsIsKnownConst = true; + break; + + case InlineObservation::CALLEE_ARG_FEEDS_ISCONST: + m_ArgFeedsIsKnownConst = true; + break; + case InlineObservation::CALLEE_UNSUPPORTED_OPCODE: propagate = true; break; @@ -727,6 +735,15 @@ double DefaultPolicy::DetermineMultiplier() JITDUMP("\nInline candidate has arg that feeds range check. Multiplier increased to %g.", multiplier); } + if (m_ConstArgFeedsIsKnownConst || (m_ArgFeedsIsKnownConst && m_IsPrejitRoot)) + { + // if we use RuntimeHelpers.IsKnownConstant we most likely expect our function to be always inlined + // at least in the case of constant arguments. In IsPrejitRoot we don't have callsite info so let's + // assume we have a constant here in order to avoid "baked" noinline + multiplier += 20; + JITDUMP("\nConstant argument feeds RuntimeHelpers.IsKnownConstant. Multiplier increased to %g.", multiplier); + } + if (m_ConstantArgFeedsConstantTest > 0) { multiplier += 3.0; @@ -1371,7 +1388,7 @@ void ExtendedDefaultPolicy::NoteInt(InlineObservation obs, int value) { SetNever(InlineObservation::CALLEE_DOES_NOT_RETURN); } - else if (!m_IsForceInline && !m_HasProfile) + else if (!m_IsForceInline && !m_HasProfile && !m_ConstArgFeedsIsKnownConst && !m_ArgFeedsIsKnownConst) { unsigned bbLimit = (unsigned)JitConfig.JitExtDefaultPolicyMaxBB(); if (m_IsPrejitRoot) @@ -1381,6 +1398,7 @@ void ExtendedDefaultPolicy::NoteInt(InlineObservation obs, int value) bbLimit += 5 + m_Switch * 10; } bbLimit += m_FoldableBranch + m_FoldableSwitch * 10; + if ((unsigned)value > bbLimit) { SetNever(InlineObservation::CALLEE_TOO_MANY_BASIC_BLOCKS); @@ -2638,6 +2656,8 @@ void DiscretionaryPolicy::DumpData(FILE* file) const fprintf(file, ",%u", m_ArgFeedsConstantTest); fprintf(file, ",%u", m_MethodIsMostlyLoadStore ? 1 : 0); fprintf(file, ",%u", m_ArgFeedsRangeCheck); + fprintf(file, ",%u", m_ConstArgFeedsIsKnownConst ? 1 : 0); + fprintf(file, ",%u", m_ArgFeedsIsKnownConst ? 1 : 0); fprintf(file, ",%u", m_ConstantArgFeedsConstantTest); fprintf(file, ",%d", m_CalleeNativeSizeEstimate); fprintf(file, ",%d", m_CallsiteNativeSizeEstimate); diff --git a/src/coreclr/jit/inlinepolicy.h b/src/coreclr/jit/inlinepolicy.h index f5f200e9f5bd7..05e8539982ee8 100644 --- a/src/coreclr/jit/inlinepolicy.h +++ b/src/coreclr/jit/inlinepolicy.h @@ -110,6 +110,8 @@ class DefaultPolicy : public LegalPolicy , m_CallsiteIsInLoop(false) , m_IsNoReturn(false) , m_IsNoReturnKnown(false) + , m_ConstArgFeedsIsKnownConst(false) + , m_ArgFeedsIsKnownConst(false) { // empty } @@ -178,6 +180,8 @@ class DefaultPolicy : public LegalPolicy bool m_CallsiteIsInLoop : 1; bool m_IsNoReturn : 1; bool m_IsNoReturnKnown : 1; + bool m_ConstArgFeedsIsKnownConst : 1; + bool m_ArgFeedsIsKnownConst : 1; }; // ExtendedDefaultPolicy is a slightly more aggressive variant of diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index bbf204c74caa8..1cbe07cb69b1c 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -1017,7 +1017,8 @@ void CodeGen::inst_RV_RV_IV(instruction ins, emitAttr size, regNumber reg1, regN // void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival) { - noway_assert(GetEmitter()->emitVerifyEncodable(ins, EA_SIZE(attr), reg1)); + emitter* emit = GetEmitter(); + noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(attr), reg1)); if (rmOp->isContained() || rmOp->isUsedFromSpillTemp()) { @@ -1069,7 +1070,7 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT case GT_CLS_VAR_ADDR: { - GetEmitter()->emitIns_R_C_I(ins, attr, reg1, addr->AsClsVar()->gtClsVarHnd, 0, ival); + emit->emitIns_R_C_I(ins, attr, reg1, addr->AsClsVar()->gtClsVarHnd, 0, ival); return; } @@ -1084,7 +1085,7 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT // temporary GT_IND to generate code with. memIndir = &load; } - GetEmitter()->emitIns_R_A_I(ins, attr, reg1, memIndir, ival); + emit->emitIns_R_A_I(ins, attr, reg1, memIndir, ival); return; } } @@ -1106,6 +1107,14 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT break; } + case GT_CNS_DBL: + { + GenTreeDblCon* cns = rmOp->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_R_C_I(ins, attr, reg1, hnd, 0, ival); + return; + } + default: unreached(); } @@ -1117,12 +1126,12 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT assert((varNum != BAD_VAR_NUM) || (tmpDsc != nullptr)); assert(offset != (unsigned)-1); - GetEmitter()->emitIns_R_S_I(ins, attr, reg1, varNum, offset, ival); + emit->emitIns_R_S_I(ins, attr, reg1, varNum, offset, ival); } else { regNumber rmOpReg = rmOp->GetRegNum(); - GetEmitter()->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpReg, ival); + emit->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpReg, ival); } } @@ -1142,7 +1151,8 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT void CodeGen::inst_RV_RV_TT( instruction ins, emitAttr size, regNumber targetReg, regNumber op1Reg, GenTree* op2, bool isRMW) { - noway_assert(GetEmitter()->emitVerifyEncodable(ins, EA_SIZE(size), targetReg)); + emitter* emit = GetEmitter(); + noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(size), targetReg)); // TODO-XArch-CQ: Commutative operations can have op1 be contained // TODO-XArch-CQ: Non-VEX encoded instructions can have both ops contained @@ -1197,7 +1207,7 @@ void CodeGen::inst_RV_RV_TT( case GT_CLS_VAR_ADDR: { - GetEmitter()->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, addr->AsClsVar()->gtClsVarHnd, 0); + emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, addr->AsClsVar()->gtClsVarHnd, 0); return; } @@ -1212,7 +1222,7 @@ void CodeGen::inst_RV_RV_TT( // temporary GT_IND to generate code with. memIndir = &load; } - GetEmitter()->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, memIndir); + emit->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, memIndir); return; } } @@ -1238,10 +1248,9 @@ void CodeGen::inst_RV_RV_TT( case GT_CNS_DBL: { - GenTreeDblCon* dblCns = op2->AsDblCon(); - CORINFO_FIELD_HANDLE cnsDblHnd = - GetEmitter()->emitFltOrDblConst(dblCns->gtDconVal, emitTypeSize(dblCns)); - GetEmitter()->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, cnsDblHnd, 0); + GenTreeDblCon* cns = op2->AsDblCon(); + CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns)); + emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, hnd, 0); return; } @@ -1258,7 +1267,7 @@ void CodeGen::inst_RV_RV_TT( assert((varNum != BAD_VAR_NUM) || (tmpDsc != nullptr)); assert(offset != (unsigned)-1); - GetEmitter()->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, varNum, offset); + emit->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, varNum, offset); } else { @@ -1277,7 +1286,7 @@ void CodeGen::inst_RV_RV_TT( op1Reg = targetReg; } - GetEmitter()->emitIns_SIMD_R_R_R(ins, size, targetReg, op1Reg, op2Reg); + emit->emitIns_SIMD_R_R_R(ins, size, targetReg, op1Reg, op2Reg); } } #endif // TARGET_XARCH diff --git a/src/coreclr/jit/instrsarm64.h b/src/coreclr/jit/instrsarm64.h index c89b006a41897..d4e7ef5b10c8d 100644 --- a/src/coreclr/jit/instrsarm64.h +++ b/src/coreclr/jit/instrsarm64.h @@ -312,8 +312,8 @@ INST4(neg, "neg", 0, IF_EN4G, 0x4B0003E0, 0x4B0003E0, INST4(cmeq, "cmeq", 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, 0x5E209800, 0x0E209800) // cmeq Vd,Vn,Vm DV_3E 01111110111mmmmm 100011nnnnnddddd 7EE0 8C00 Vd,Vn,Vm (scalar) // cmeq Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100011nnnnnddddd 2E20 8C00 Vd,Vn,Vm (vector) - // cmeq Vd,Vn DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn (scalar) - // cmeq Vd,Vn DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn (vector) + // cmeq Vd,Vn,#0 DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn,#0 (scalar - with zero) + // cmeq Vd,Vn,#0 DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn,#0 (vector - with zero) INST4(cmge, "cmge", 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800) // cmge Vd,Vn,Vm DV_3E 01011110111mmmmm 001111nnnnnddddd 5EE0 3C00 Vd,Vn,Vm (scalar) @@ -331,8 +331,8 @@ INST4(cmgt, "cmgt", 0, IF_EN4H, 0x5EE03400, 0x0E203400, INST4(fcmeq, "fcmeq", 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800) // fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd Vn Vm (scalar) // fcmeq Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111001nnnnnddddd 0E20 E400 Vd,Vn,Vm (vector) - // fcmeq Vd,Vn DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn (scalar) - // fcmeq Vd,Vn DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn (vector) + // fcmeq Vd,Vn,#0 DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn,#0 (scalar - with zero) + // fcmeq Vd,Vn,#0 DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn,#0 (vector - with zero) INST4(fcmge, "fcmge", 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800) // fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd Vn Vm (scalar) diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index 458f919fe2793..08d4c4a8c8675 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -595,7 +595,7 @@ INST3(FIRST_BMI_INSTRUCTION, "FIRST_BMI_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE INST3(andn, "andn", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF2), INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND NOT INST3(blsi, "blsi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), 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), INS_Flags_IsDstDstSrcAVXInstruction) // Reset 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 // BMI2 diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 1c8da276c3dc5..1346c2069da17 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -463,10 +463,24 @@ CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 0) CONFIG_INTEGER(TC_OnStackReplacement_InitialCounter, W("TC_OnStackReplacement_InitialCounter"), 1000) // Enable partial compilation for Tier0 methods CONFIG_INTEGER(TC_PartialCompilation, W("TC_PartialCompilation"), 0) +#if defined(DEBUG) +// Randomly sprinkle patchpoints. Value is the likelyhood any given stack-empty point becomes a patchpoint. +CONFIG_INTEGER(JitRandomOnStackReplacement, W("JitRandomOnStackReplacement"), 0) +// Place patchpoint at the specified IL offset, if possible. Overrides random placement. +CONFIG_INTEGER(JitOffsetOnStackReplacement, W("JitOffsetOnStackReplacement"), -1) +#endif // debug #if defined(DEBUG) -CONFIG_STRING(JitEnableOsrRange, W("JitEnableOsrRange")) // Enable osr for only some methods -#endif // debug +// EnableOsrRange allows you to limit the set of methods that will rely on OSR to escape +// from Tier0 code. Methods outside the range that would normally be jitted at Tier0 +// and have patchpoints will instead be switched to optimized. +CONFIG_STRING(JitEnableOsrRange, W("JitEnableOsrRange")) +// EnablePatchpointRange allows you to limit the set of Tier0 methods that +// will have patchpoints, and hence control which methods will create OSR methods. +// Unlike EnableOsrRange, it will not alter the optimization setting for methods +// outside the enabled range. +CONFIG_STRING(JitEnablePatchpointRange, W("JitEnablePatchpointRange")) +#endif // Profile instrumentation options CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 84d7965d395bf..66684e38e1a3b 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -567,26 +567,6 @@ class LocalAddressVisitor final : public GenTreeVisitor PopValue(); break; - case GT_DYN_BLK: - assert(TopValue(2).Node() == node); - assert(TopValue(1).Node() == node->AsDynBlk()->Addr()); - assert(TopValue(0).Node() == node->AsDynBlk()->gtDynamicSize); - - // The block size may be the result of an indirection so we need - // to escape the location that may be associated with it. - EscapeValue(TopValue(0), node); - - if (!TopValue(2).Indir(TopValue(1))) - { - // If the address comes from another indirection (e.g. DYN_BLK(IND(...)) - // then we need to escape the location. - EscapeLocation(TopValue(1), node); - } - - PopValue(); - PopValue(); - break; - case GT_RETURN: if (TopValue(0).Node() != node) { @@ -829,14 +809,13 @@ class LocalAddressVisitor final : public GenTreeVisitor // user - the node that uses the indirection // // Notes: - // This returns 0 for indirection of unknown size, typically GT_DYN_BLK. - // GT_IND nodes that have type TYP_STRUCT are expected to only appears - // on the RHS of an assignment, in which case the LHS size will be used instead. - // Otherwise 0 is returned as well. + // This returns 0 for indirection of unknown size. GT_IND nodes that have type + // TYP_STRUCT are expected to only appears on the RHS of an assignment, in which + // case the LHS size will be used instead. Otherwise 0 is returned as well. // unsigned GetIndirSize(GenTree* indir, GenTree* user) { - assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK, GT_FIELD)); + assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_FIELD)); if (indir->TypeGet() != TYP_STRUCT) { @@ -883,7 +862,7 @@ class LocalAddressVisitor final : public GenTreeVisitor case GT_OBJ: return indir->AsBlk()->GetLayout()->GetSize(); default: - assert(indir->OperIs(GT_IND, GT_DYN_BLK)); + assert(indir->OperIs(GT_IND)); return 0; } } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 7b329e0a86a46..a1cfc61822216 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -305,7 +305,9 @@ void Compiler::lvaInitTypeRef() JITDUMP("-- V%02u is OSR exposed\n", varNum); varDsc->lvHasLdAddrOp = 1; - if (varDsc->lvType != TYP_STRUCT) // Why does it apply only to non-structs? + // todo: Why does it apply only to non-structs? + // + if (!varTypeIsStruct(varDsc) && !varTypeIsSIMD(varDsc)) { lvaSetVarAddrExposed(varNum DEBUGARG(AddressExposedReason::OSR_EXPOSED)); } @@ -485,19 +487,7 @@ void Compiler::lvaInitThisPtr(InitVarDscInfo* varDscInfo) lvaSetClass(varDscInfo->varNum, info.compClassHnd); } - if (tiVerificationNeeded) - { - varDsc->lvVerTypeInfo = verMakeTypeInfo(info.compClassHnd); - - if (varDsc->lvVerTypeInfo.IsValueClass()) - { - varDsc->lvVerTypeInfo.MakeByRef(); - } - } - else - { - varDsc->lvVerTypeInfo = typeInfo(); - } + varDsc->lvVerTypeInfo = typeInfo(); // Mark the 'this' pointer for the method varDsc->lvVerTypeInfo.SetIsThisPtr(); @@ -1321,48 +1311,6 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, compFloatingPointUsed = true; } - if (tiVerificationNeeded) - { - varDsc->lvVerTypeInfo = verParseArgSigToTypeInfo(varSig, varList); - } - - if (tiVerificationNeeded) - { - if (varDsc->lvIsParam) - { - // For an incoming ValueType we better be able to have the full type information - // so that we can layout the parameter offsets correctly - - if (varTypeIsStruct(type) && varDsc->lvVerTypeInfo.IsDead()) - { - BADCODE("invalid ValueType parameter"); - } - - // For an incoming reference type we need to verify that the actual type is - // a reference type and not a valuetype. - - if (type == TYP_REF && - !(varDsc->lvVerTypeInfo.IsType(TI_REF) || varDsc->lvVerTypeInfo.IsUnboxedGenericTypeVar())) - { - BADCODE("parameter type mismatch"); - } - } - - // Disallow byrefs to byref like objects (ArgTypeHandle) - // techncally we could get away with just not setting them - if (varDsc->lvVerTypeInfo.IsByRef() && verIsByRefLike(DereferenceByRef(varDsc->lvVerTypeInfo))) - { - varDsc->lvVerTypeInfo = typeInfo(); - } - - // we don't want the EE to assert in lvaSetStruct on bad sigs, so change - // the JIT type to avoid even trying to call back - if (varTypeIsStruct(type) && varDsc->lvVerTypeInfo.IsDead()) - { - type = TYP_VOID; - } - } - if (typeHnd) { unsigned cFlags = info.compCompHnd->getClassAttribs(typeHnd); @@ -1371,11 +1319,8 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, // a primitive. We will need the typeHnd to distinguish them, so we store it here. if ((cFlags & CORINFO_FLG_VALUECLASS) && !varTypeIsStruct(type)) { - if (tiVerificationNeeded == false) - { - // printf("This is a struct that the JIT will treat as a primitive\n"); - varDsc->lvVerTypeInfo = verMakeTypeInfo(typeHnd); - } + // printf("This is a struct that the JIT will treat as a primitive\n"); + varDsc->lvVerTypeInfo = verMakeTypeInfo(typeHnd); } varDsc->lvOverlappingFields = StructHasOverlappingFields(cFlags); @@ -1393,7 +1338,7 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, } if ((varTypeIsStruct(type))) { - lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, !tiVerificationNeeded); + lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, true); if (info.compIsVarArgs) { lvaSetStructUsedAsVarArg(varNum); @@ -4111,8 +4056,8 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, #endif // UNIX_AMD64_ABI /* Variables must be used as the same type throughout the method */ - noway_assert(tiVerificationNeeded || varDsc->lvType == TYP_UNDEF || tree->gtType == TYP_UNKNOWN || - allowStructs || genActualType(varDsc->TypeGet()) == genActualType(tree->gtType) || + noway_assert(varDsc->lvType == TYP_UNDEF || tree->gtType == TYP_UNKNOWN || allowStructs || + genActualType(varDsc->TypeGet()) == genActualType(tree->gtType) || (tree->gtType == TYP_BYREF && varDsc->TypeGet() == TYP_I_IMPL) || (tree->gtType == TYP_I_IMPL && varDsc->TypeGet() == TYP_BYREF) || (tree->gtFlags & GTF_VAR_CAST) || (varTypeIsFloating(varDsc) && varTypeIsFloating(tree)) || diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp index 97f9e4f4807d2..81d03b93f7b34 100644 --- a/src/coreclr/jit/lir.cpp +++ b/src/coreclr/jit/lir.cpp @@ -1636,7 +1636,7 @@ void LIR::InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range) LIR::Range& blockRange = LIR::AsRange(block); GenTree* insertionPoint = nullptr; - if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN)) + if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN)) { insertionPoint = blockRange.LastNode(); assert(insertionPoint != nullptr); diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index 4f8d9334249cf..d9592683db798 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -2090,7 +2090,6 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: { bool removed = fgTryRemoveNonLocal(node, &blockRange); if (!removed && node->IsUnusedValue()) diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index c206249a43740..bdd8d763aa4c7 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -767,7 +767,7 @@ BasicBlock* LoopCloneContext::CondToStmtInBlock(Compiler* { noway_assert(conds.Size() > 0); assert(slowHead != nullptr); - assert((insertAfter->bbJumpKind == BBJ_NONE) || (insertAfter->bbJumpKind == BBJ_COND)); + assert(insertAfter->KindIs(BBJ_NONE, BBJ_COND)); // Choose how to generate the conditions const bool generateOneConditionPerBlock = true; @@ -1847,7 +1847,7 @@ void Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context) // X BasicBlock* h = loop.lpHead; - if (h->bbJumpKind != BBJ_NONE && h->bbJumpKind != BBJ_ALWAYS) + if (!h->KindIs(BBJ_NONE, BBJ_ALWAYS)) { // Make a new block to be the unique entry to the loop. JITDUMP("Create new unique single-successor entry to loop\n"); diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 06d42a37f986f..b111d73db6a99 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -139,7 +139,7 @@ GenTree* Lowering::LowerNode(GenTree* node) case GT_AND: case GT_OR: case GT_XOR: - return LowerBinaryArithmetic(node->AsOp()); + return LowerBinaryArithmeticCommon(node->AsOp()); case GT_MUL: case GT_MULHI: @@ -2708,10 +2708,16 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp) if (op2->IsIntegralConst(0) && (op1->gtNext == op2) && (op2->gtNext == cmp) && #ifdef TARGET_XARCH - op1->OperIs(GT_AND, GT_OR, GT_XOR, GT_ADD, GT_SUB, GT_NEG)) + (op1->OperIs(GT_AND, GT_OR, GT_XOR, GT_ADD, GT_SUB, GT_NEG) +#ifdef FEATURE_HW_INTRINSICS + || (op1->OperIs(GT_HWINTRINSIC) && + emitter::DoesWriteZeroFlag(HWIntrinsicInfo::lookupIns(op1->AsHWIntrinsic()))) +#endif // FEATURE_HW_INTRINSICS + ) #else // TARGET_ARM64 - op1->OperIs(GT_AND, GT_ADD, GT_SUB)) + op1->OperIs(GT_AND, GT_ADD, GT_SUB) #endif + ) { op1->gtFlags |= GTF_SET_FLAGS; op1->SetUnusedValue(); @@ -3792,32 +3798,29 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call) assert(thisArgNode != nullptr); assert(thisArgNode->gtOper == GT_PUTARG_REG); - GenTree* originalThisExpr = thisArgNode->AsOp()->gtOp1; - GenTree* thisExpr = originalThisExpr; + GenTree* thisExpr = thisArgNode->AsOp()->gtOp1; // We're going to use the 'this' expression multiple times, so make a local to copy it. - unsigned lclNum; - - if (call->IsTailCallViaJitHelper() && originalThisExpr->IsLocal()) + GenTree* base; + if (thisExpr->OperIs(GT_LCL_VAR)) + { + base = comp->gtNewLclvNode(thisExpr->AsLclVar()->GetLclNum(), thisExpr->TypeGet()); + } + else if (thisExpr->OperIs(GT_LCL_FLD)) { - // For ordering purposes for the special tailcall arguments on x86, we forced the - // 'this' pointer in this case to a local in Compiler::fgMorphTailCall(). - // We could possibly use this case to remove copies for all architectures and non-tailcall - // calls by creating a new lcl var or lcl field reference, as is done in the - // LowerVirtualVtableCall() code. - assert(originalThisExpr->OperGet() == GT_LCL_VAR); - lclNum = originalThisExpr->AsLclVarCommon()->GetLclNum(); + base = comp->gtNewLclFldNode(thisExpr->AsLclFld()->GetLclNum(), thisExpr->TypeGet(), + thisExpr->AsLclFld()->GetLclOffs()); } else { unsigned delegateInvokeTmp = comp->lvaGrabTemp(true DEBUGARG("delegate invoke call")); + base = comp->gtNewLclvNode(delegateInvokeTmp, thisExpr->TypeGet()); LIR::Use thisExprUse(BlockRange(), &thisArgNode->AsOp()->gtOp1, thisArgNode); ReplaceWithLclVar(thisExprUse, delegateInvokeTmp); thisExpr = thisExprUse.Def(); // it's changed; reload it. - lclNum = delegateInvokeTmp; } // replace original expression feeding into thisPtr with @@ -3836,8 +3839,6 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call) // the control target is // [originalThis + firstTgtOffs] - GenTree* base = new (comp, GT_LCL_VAR) GenTreeLclVar(GT_LCL_VAR, originalThisExpr->TypeGet(), lclNum); - unsigned targetOffs = comp->eeGetEEInfo()->offsetOfDelegateFirstTarget; GenTree* result = new (comp, GT_LEA) GenTreeAddrMode(TYP_REF, base, nullptr, 0, targetOffs); GenTree* callTarget = Ind(result); @@ -4606,7 +4607,7 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call) // If what we are passing as the thisptr is not already a local, make a new local to place it in // because we will be creating expressions based on it. unsigned lclNum; - if (thisPtr->IsLocal()) + if (thisPtr->OperIsLocal()) { lclNum = thisPtr->AsLclVarCommon()->GetLclNum(); } @@ -4890,20 +4891,29 @@ bool Lowering::AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, Ge // addressing mode and transform them to a GT_LEA // // Arguments: -// use - the use of the address we want to transform +// addr - the use of the address we want to transform // isContainable - true if this addressing mode can be contained -// targetType - on arm we can use "scale" only for appropriate target type +// parent - the node that consumes the given addr (most likely it's an IND) // // Returns: // true if the address node was changed to a LEA, false otherwise. // -bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType) +bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent) { if (!addr->OperIs(GT_ADD) || addr->gtOverflow()) { return false; } +#ifdef TARGET_ARM64 + if (parent->OperIsIndir() && parent->AsIndir()->IsVolatile() && !varTypeIsGC(addr)) + { + // For Arm64 we avoid using LEA for volatile INDs + // because we won't be able to use ldar/star + return false; + } +#endif + GenTree* base = nullptr; GenTree* index = nullptr; unsigned scale = 0; @@ -4919,6 +4929,8 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types ta &scale, // scaling &offset); // displacement + var_types targetType = parent->OperIsIndir() ? parent->TypeGet() : TYP_UNDEF; + #ifdef TARGET_ARMARCH // Multiplier should be a "natural-scale" power of two number which is equal to target's width. // @@ -5108,7 +5120,7 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) GenTree* parent = use.User(); if (!parent->OperIsIndir() && !parent->OperIs(GT_ADD)) { - TryCreateAddrMode(node, false); + TryCreateAddrMode(node, false, parent); } } #endif // !TARGET_ARMARCH @@ -5122,7 +5134,7 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) } //------------------------------------------------------------------------ -// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// LowerBinaryArithmeticCommon: lowers the given binary arithmetic node. // // Recognizes opportunities for using target-independent "combined" nodes // (currently AND_NOT on ARMArch). Performs containment checks. @@ -5133,41 +5145,39 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) // Returns: // The next node to lower. // -GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* node) +GenTree* Lowering::LowerBinaryArithmeticCommon(GenTreeOp* binOp) { // TODO-CQ-XArch: support BMI2 "andn" in codegen and condition // this logic on the support for the instruction set on XArch. CLANG_FORMAT_COMMENT_ANCHOR; #ifdef TARGET_ARMARCH - if (comp->opts.OptimizationEnabled() && node->OperIs(GT_AND)) + if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND)) { GenTree* opNode = nullptr; GenTree* notNode = nullptr; - if (node->gtGetOp1()->OperIs(GT_NOT)) + if (binOp->gtGetOp1()->OperIs(GT_NOT)) { - notNode = node->gtGetOp1(); - opNode = node->gtGetOp2(); + notNode = binOp->gtGetOp1(); + opNode = binOp->gtGetOp2(); } - else if (node->gtGetOp2()->OperIs(GT_NOT)) + else if (binOp->gtGetOp2()->OperIs(GT_NOT)) { - notNode = node->gtGetOp2(); - opNode = node->gtGetOp1(); + notNode = binOp->gtGetOp2(); + opNode = binOp->gtGetOp1(); } if (notNode != nullptr) { - node->gtOp1 = opNode; - node->gtOp2 = notNode->AsUnOp()->gtGetOp1(); - node->ChangeOper(GT_AND_NOT); + binOp->gtOp1 = opNode; + binOp->gtOp2 = notNode->AsUnOp()->gtGetOp1(); + binOp->ChangeOper(GT_AND_NOT); BlockRange().Remove(notNode); } } -#endif // TARGET_ARMARCH - - ContainCheckBinary(node); +#endif - return node->gtNext; + return LowerBinaryArithmetic(binOp); } //------------------------------------------------------------------------ @@ -6779,7 +6789,7 @@ void Lowering::ContainCheckBitCast(GenTree* node) void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) { assert(ind->TypeGet() != TYP_STRUCT); - TryCreateAddrMode(ind->Addr(), true, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), true, ind); if (!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)) { if (varTypeIsFloating(ind) && ind->Data()->IsCnsFltOrDbl()) @@ -6847,7 +6857,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind) // TODO-Cleanup: We're passing isContainable = true but ContainCheckIndir rejects // address containment in some cases so we end up creating trivial (reg + offfset) // or (reg + reg) LEAs that are not necessary. - TryCreateAddrMode(ind->Addr(), true, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), true, ind); ContainCheckIndir(ind); if (ind->OperIs(GT_NULLCHECK) || ind->IsUnusedValue()) @@ -6860,7 +6870,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind) // If the `ADDR` node under `STORE_OBJ(dstAddr, IND(struct(ADDR))` // is a complex one it could benefit from an `LEA` that is not contained. const bool isContainable = false; - TryCreateAddrMode(ind->Addr(), isContainable, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), isContainable, ind); } } @@ -6922,6 +6932,14 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) { assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK, GT_STORE_OBJ)); + + // Lose the type information stored in the source - we no longer need it. + if (blkNode->Data()->OperIs(GT_OBJ, GT_BLK)) + { + blkNode->Data()->SetOper(GT_IND); + LowerIndir(blkNode->Data()->AsIndir()); + } + if (TryTransformStoreObjAsStoreInd(blkNode)) { return; @@ -6996,7 +7014,7 @@ bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode) return false; } - JITDUMP("Replacing STORE_OBJ with STOREIND for [06%u]", blkNode->gtTreeID); + JITDUMP("Replacing STORE_OBJ with STOREIND for [%06u]\n", blkNode->gtTreeID); blkNode->ChangeOper(GT_STOREIND); blkNode->ChangeType(regType); diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index ed0ecc5661970..95843b6bded47 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -297,7 +297,8 @@ class Lowering final : public Phase void LowerStoreIndir(GenTreeStoreInd* node); GenTree* LowerAdd(GenTreeOp* node); GenTree* LowerMul(GenTreeOp* mul); - GenTree* LowerBinaryArithmetic(GenTreeOp* node); + GenTree* LowerBinaryArithmeticCommon(GenTreeOp* binOp); + GenTree* LowerBinaryArithmetic(GenTreeOp* binOp); bool LowerUnsignedDivOrMod(GenTreeOp* divMod); GenTree* LowerConstIntDivOrMod(GenTree* node); GenTree* LowerSignedDivOrMod(GenTree* node); @@ -306,7 +307,7 @@ class Lowering final : public Phase void ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenTree* addr); void LowerPutArgStk(GenTreePutArgStk* tree); - bool TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType = TYP_UNDEF); + bool TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent); bool TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode); @@ -343,6 +344,7 @@ class Lowering final : public Phase void LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node); void LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node); void LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node); + GenTree* TryLowerAndOpToResetLowestSetBit(GenTreeOp* binOp); #elif defined(TARGET_ARM64) bool IsValidConstForMovImm(GenTreeHWIntrinsic* node); void LowerHWIntrinsicFusedMultiplyAddScalar(GenTreeHWIntrinsic* node); @@ -564,8 +566,8 @@ class Lowering final : public Phase } #ifdef FEATURE_HW_INTRINSICS - // Return true if 'node' is a containable HWIntrinsic op. - bool IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree* node, bool* supportsRegOptional); + // Tries to get a containable node for a given HWIntrinsic + bool TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree** pNode, bool* supportsRegOptional); #endif // FEATURE_HW_INTRINSICS static void TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, BasicBlock* block); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index e4ba37cffb1d5..67e1269dfd429 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -281,6 +281,22 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) return mul->gtNext; } +//------------------------------------------------------------------------ +// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// +// Arguments: +// node - the arithmetic node to lower +// +// Returns: +// The next node to lower. +// +GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) +{ + ContainCheckBinary(binOp); + + return binOp->gtNext; +} + //------------------------------------------------------------------------ // LowerBlockStore: Lower a block store node // @@ -293,6 +309,8 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) GenTree* src = blkNode->Data(); unsigned size = blkNode->Size(); + const bool isDstAddrLocal = dstAddr->OperIsLocalAddr(); + if (blkNode->OperIsInitBlkOp()) { if (src->OperIs(GT_INIT_VAL)) @@ -306,7 +324,18 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) blkNode->SetOper(GT_STORE_BLK); } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= INITBLK_UNROLL_LIMIT) && src->OperIs(GT_CNS_INT)) + unsigned initBlockUnrollLimit = INITBLK_UNROLL_LIMIT; + +#ifdef TARGET_ARM64 + if (isDstAddrLocal) + { + // Since dstAddr points to the stack CodeGen can use more optimal + // quad-word store SIMD instructions for InitBlock. + initBlockUnrollLimit = INITBLK_LCL_UNROLL_LIMIT; + } +#endif + + if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= initBlockUnrollLimit) && src->OperIs(GT_CNS_INT)) { blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; @@ -353,19 +382,39 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) assert(src->OperIs(GT_IND, GT_LCL_VAR, GT_LCL_FLD)); src->SetContained(); + bool isSrcAddrLocal = false; + if (src->OperIs(GT_IND)) { + GenTree* srcAddr = src->AsIndir()->Addr(); // TODO-Cleanup: Make sure that GT_IND lowering didn't mark the source address as contained. // Sometimes the GT_IND type is a non-struct type and then GT_IND lowering may contain the // address, not knowing that GT_IND is part of a block op that has containment restrictions. - src->AsIndir()->Addr()->ClearContained(); + srcAddr->ClearContained(); + isSrcAddrLocal = srcAddr->OperIsLocalAddr(); + } + else + { + isSrcAddrLocal = true; + + if (src->OperIs(GT_LCL_VAR)) + { + // TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register. + const unsigned srcLclNum = src->AsLclVar()->GetLclNum(); + comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(DoNotEnregisterReason::BlockOp)); + } } - else if (src->OperIs(GT_LCL_VAR)) + + unsigned copyBlockUnrollLimit = CPBLK_UNROLL_LIMIT; + +#ifdef TARGET_ARM64 + if (isSrcAddrLocal && isDstAddrLocal) { - // TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register. - const unsigned srcLclNum = src->AsLclVar()->GetLclNum(); - comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(DoNotEnregisterReason::BlockOp)); + // Since both srcAddr and dstAddr point to the stack CodeGen can use more optimal + // quad-word load and store SIMD instructions for CopyBlock. + copyBlockUnrollLimit = CPBLK_LCL_UNROLL_LIMIT; } +#endif if (blkNode->OperIs(GT_STORE_OBJ)) { @@ -373,7 +422,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { blkNode->SetOper(GT_STORE_BLK); } - else if (dstAddr->OperIsLocalAddr() && (size <= CPBLK_UNROLL_LIMIT)) + else if (isDstAddrLocal && (size <= copyBlockUnrollLimit)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -389,7 +438,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; } - else if (blkNode->OperIs(GT_STORE_BLK) && (size <= CPBLK_UNROLL_LIMIT)) + else if (blkNode->OperIs(GT_STORE_BLK) && (size <= copyBlockUnrollLimit)) { blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; @@ -490,7 +539,6 @@ void Lowering::LowerCast(GenTree* tree) GenTree* op1 = tree->AsOp()->gtOp1; var_types dstType = tree->CastToType(); var_types srcType = genActualType(op1->TypeGet()); - var_types tmpType = TYP_UNDEF; if (varTypeIsFloating(srcType)) { @@ -501,16 +549,6 @@ void Lowering::LowerCast(GenTree* tree) assert(!varTypeIsSmall(srcType)); - if (tmpType != TYP_UNDEF) - { - GenTree* tmp = comp->gtNewCastNode(tmpType, op1, tree->IsUnsigned(), tmpType); - tmp->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT)); - - tree->gtFlags &= ~GTF_UNSIGNED; - tree->AsOp()->gtOp1 = tmp; - BlockRange().InsertAfter(op1, tmp); - } - // Now determine if we have operands that should be contained. ContainCheckCast(tree->AsCast()); } @@ -852,8 +890,8 @@ void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp) GenTree* insCns = comp->gtNewIconNode(-1, TYP_INT); BlockRange().InsertAfter(idxCns, insCns); - GenTree* tmp = comp->gtNewSimdAsHWIntrinsicNode(simdType, cmp, idxCns, insCns, NI_AdvSimd_Insert, - CORINFO_TYPE_INT, simdSize); + GenTree* tmp = comp->gtNewSimdHWIntrinsicNode(simdType, cmp, idxCns, insCns, NI_AdvSimd_Insert, + CORINFO_TYPE_INT, simdSize); BlockRange().InsertAfter(insCns, tmp); LowerNode(tmp); @@ -869,7 +907,7 @@ void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp) BlockRange().InsertAfter(msk, zroCns); GenTree* val = - comp->gtNewSimdAsHWIntrinsicNode(TYP_UBYTE, msk, zroCns, NI_AdvSimd_Extract, CORINFO_TYPE_UBYTE, simdSize); + comp->gtNewSimdHWIntrinsicNode(TYP_UBYTE, msk, zroCns, NI_AdvSimd_Extract, CORINFO_TYPE_UBYTE, simdSize); BlockRange().InsertAfter(zroCns, val); LowerNode(val); @@ -1147,7 +1185,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) BlockRange().InsertAfter(idx, tmp1); LowerNode(tmp1); - op1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op1, idx, tmp1, NI_AdvSimd_Insert, simdBaseJitType, simdSize); + op1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, idx, tmp1, NI_AdvSimd_Insert, simdBaseJitType, simdSize); BlockRange().InsertAfter(tmp1, op1); LowerNode(op1); @@ -1158,7 +1196,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) BlockRange().InsertAfter(idx, tmp2); LowerNode(tmp2); - op2 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op2, idx, tmp2, NI_AdvSimd_Insert, simdBaseJitType, simdSize); + op2 = comp->gtNewSimdHWIntrinsicNode(simdType, op2, idx, tmp2, NI_AdvSimd_Insert, simdBaseJitType, simdSize); BlockRange().InsertAfter(tmp2, op2); LowerNode(op2); } @@ -1183,32 +1221,35 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) } assert(!varTypeIsLong(simdBaseType)); - tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op1, op2, multiply, simdBaseJitType, simdSize); + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, multiply, simdBaseJitType, simdSize); BlockRange().InsertBefore(node, tmp1); LowerNode(tmp1); if (varTypeIsFloating(simdBaseType)) { - // We will be constructing the following parts: - // ... - // /--* tmp1 simd16 - // * STORE_LCL_VAR simd16 - // tmp1 = LCL_VAR simd16 - // tmp2 = LCL_VAR simd16 - // ... + if ((simdSize != 8) || (simdBaseType == TYP_FLOAT)) + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // ... - // This is roughly the following managed code: - // ... - // var tmp2 = tmp1; - // ... + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // ... - node->Op(1) = tmp1; - LIR::Use tmp1Use(BlockRange(), &node->Op(1), node); - ReplaceWithLclVar(tmp1Use); - tmp1 = node->Op(1); + node->Op(1) = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->Op(1), node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->Op(1); - tmp2 = comp->gtClone(tmp1); - BlockRange().InsertAfter(tmp1, tmp2); + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + } if (simdSize == 8) { @@ -1226,8 +1267,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // var tmp1 = AdvSimd.AddPairwise(tmp1, tmp2); // ... - tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType, - simdSize); + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType, + simdSize); BlockRange().InsertAfter(tmp2, tmp1); LowerNode(tmp1); } @@ -1252,8 +1293,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // var tmp1 = AdvSimd.Arm64.AddPairwise(tmp1, tmp2); // ... - tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType, - simdSize); + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType, + simdSize); BlockRange().InsertAfter(tmp2, tmp1); LowerNode(tmp1); @@ -1291,8 +1332,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) tmp2 = comp->gtClone(tmp1); BlockRange().InsertAfter(tmp1, tmp2); - tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, - simdBaseJitType, simdSize); + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, + simdBaseJitType, simdSize); BlockRange().InsertAfter(tmp2, tmp1); LowerNode(tmp1); } @@ -1304,20 +1345,66 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) { assert(varTypeIsIntegral(simdBaseType)); - // We will be constructing the following parts: - // ... - // /--* tmp1 simd16 - // tmp2 = * HWINTRINSIC simd16 T AddAcross - // ... + if ((simdSize == 8) && ((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT))) + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // ... - // This is roughly the following managed code: - // ... - // var tmp2 = AdvSimd.Arm64.AddAcross(tmp1); - // ... + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // ... - tmp2 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize); - BlockRange().InsertAfter(tmp1, tmp2); - LowerNode(tmp2); + node->Op(1) = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->Op(1), node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->Op(1); + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // /--* tmp2 simd16 + // tmp2 = * HWINTRINSIC simd8 T AddPairwise + // ... + + // This is roughly the following managed code: + // ... + // var tmp2 = AdvSimd.AddPairwise(tmp1, tmp2); + // ... + + tmp1 = + comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType, simdSize); + BlockRange().InsertAfter(tmp2, tmp1); + LowerNode(tmp1); + + tmp2 = tmp1; + } + else + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // tmp2 = * HWINTRINSIC simd16 T AddAcross + // ... + + // This is roughly the following managed code: + // ... + // var tmp2 = AdvSimd.Arm64.AddAcross(tmp1); + // ... + + tmp2 = + comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize); + BlockRange().InsertAfter(tmp1, tmp2); + LowerNode(tmp2); + } } // We will be constructing the following parts: @@ -1853,6 +1940,21 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) MakeSrcContained(node, intrin.op4); break; + case NI_AdvSimd_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqualScalar: + { + if (intrin.op1->IsVectorZero()) + { + MakeSrcContained(node, intrin.op1); + } + else if (intrin.op2->IsVectorZero()) + { + MakeSrcContained(node, intrin.op2); + } + break; + } + case NI_Vector64_CreateScalarUnsafe: case NI_Vector128_CreateScalarUnsafe: case NI_AdvSimd_DuplicateToVector64: diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index c8076c4525f2d..37459907558a0 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -159,6 +159,33 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) return mul->gtNext; } +//------------------------------------------------------------------------ +// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// +// Arguments: +// node - the arithmetic node to lower +// +// Returns: +// The next node to lower. +// +GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) +{ +#ifdef FEATURE_HW_INTRINSICS + if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND) && varTypeIsIntegral(binOp)) + { + GenTree* blsrNode = TryLowerAndOpToResetLowestSetBit(binOp); + if (blsrNode != nullptr) + { + return blsrNode->gtNext; + } + } +#endif + + ContainCheckBinary(binOp); + + return binOp->gtNext; +} + //------------------------------------------------------------------------ // LowerBlockStore: Lower a block store node // @@ -167,7 +194,7 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) // void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { - TryCreateAddrMode(blkNode->Addr(), false); + TryCreateAddrMode(blkNode->Addr(), false, blkNode); GenTree* dstAddr = blkNode->Addr(); GenTree* src = blkNode->Data(); @@ -381,7 +408,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT return; } - if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true)) + if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true, blkNode)) { return; } @@ -832,8 +859,8 @@ void Lowering::LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIn bool op1SupportsRegOptional = false; bool op2SupportsRegOptional = false; - if (!IsContainableHWIntrinsicOp(node, node->Op(2), &op2SupportsRegOptional) && - IsContainableHWIntrinsicOp(node, node->Op(1), &op1SupportsRegOptional)) + if (!TryGetContainableHWIntrinsicOp(node, &node->Op(2), &op2SupportsRegOptional) && + TryGetContainableHWIntrinsicOp(node, &node->Op(1), &op1SupportsRegOptional)) { // Swap operands if op2 cannot be contained but op1 can. swapOperands = true; @@ -3047,8 +3074,6 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) if (simdSize == 32) { - assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX2)); - switch (simdBaseType) { case TYP_SHORT: @@ -3056,6 +3081,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) case TYP_INT: case TYP_UINT: { + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX2)); + multiply = NI_AVX2_MultiplyLow; horizontalAdd = NI_AVX2_HorizontalAdd; add = NI_AVX2_Add; @@ -3064,6 +3091,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) case TYP_FLOAT: { + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + // We will be constructing the following parts: // idx = CNS_INT int 0xF1 // /--* op1 simd16 @@ -3127,6 +3156,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) case TYP_DOUBLE: { + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + multiply = NI_AVX_Multiply; horizontalAdd = NI_AVX_HorizontalAdd; add = NI_AVX_Add; @@ -3425,7 +3456,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // e6, e7, e4, e5 | e2, e3, e0, e1 // e7, e6, e5, e4 | e3, e2, e1, e0 - shuffleConst = 0x4D; + shuffleConst = 0x4E; break; } @@ -3693,6 +3724,84 @@ void Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node) LowerNode(cast); } } + +//---------------------------------------------------------------------------------------------- +// Lowering::TryLowerAndOpToResetLowestSetBit: Lowers a tree AND(X, ADD(X, -1) to HWIntrinsic::ResetLowestSetBit +// +// Arguments: +// andNode - GT_AND node of integral type +// +// Return Value: +// Returns the replacement node if one is created else nullptr indicating no replacement +// +GenTree* Lowering::TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode) +{ + assert(andNode->OperIs(GT_AND) && varTypeIsIntegral(andNode)); + + GenTree* op1 = andNode->gtGetOp1(); + if (!op1->OperIs(GT_LCL_VAR) || comp->lvaGetDesc(op1->AsLclVar())->IsAddressExposed()) + { + return nullptr; + } + + GenTree* op2 = andNode->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; + } + + NamedIntrinsic intrinsic; + if (op1->TypeIs(TYP_LONG) && comp->compOpportunisticallyDependsOn(InstructionSet_BMI1_X64)) + { + intrinsic = NamedIntrinsic::NI_BMI1_X64_ResetLowestSetBit; + } + else if (comp->compOpportunisticallyDependsOn(InstructionSet_BMI1)) + { + intrinsic = NamedIntrinsic::NI_BMI1_ResetLowestSetBit; + } + else + { + return nullptr; + } + + LIR::Use use; + if (!BlockRange().TryGetUse(andNode, &use)) + { + return nullptr; + } + + GenTreeHWIntrinsic* blsrNode = comp->gtNewScalarHWIntrinsicNode(andNode->TypeGet(), op1, intrinsic); + + JITDUMP("Lower: optimize AND(X, ADD(X, -1))\n"); + DISPNODE(andNode); + JITDUMP("to:\n"); + DISPNODE(blsrNode); + + use.ReplaceWith(blsrNode); + + BlockRange().InsertBefore(andNode, blsrNode); + BlockRange().Remove(andNode); + BlockRange().Remove(op2); + BlockRange().Remove(addOp1); + BlockRange().Remove(addOp2); + + ContainCheckHWIntrinsic(blsrNode); + + return blsrNode; +} + #endif // FEATURE_HW_INTRINSICS //---------------------------------------------------------------------------------------------- @@ -5158,21 +5267,34 @@ void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode) #ifdef FEATURE_HW_INTRINSICS //---------------------------------------------------------------------------------------------- -// IsContainableHWIntrinsicOp: Return true if 'node' is a containable HWIntrinsic op. +// TryGetContainableHWIntrinsicOp: Tries to get a containable node for a given HWIntrinsic // // Arguments: -// containingNode - The hardware intrinsic node which contains 'node' -// node - The node to check -// [Out] supportsRegOptional - On return, this will be true if 'containingNode' supports regOptional operands; +// [In] containingNode - The hardware intrinsic node which contains 'node' +// [In/Out] pNode - The node to check and potentially replace with the containable node +// [Out] supportsRegOptional - On return, this will be true if 'containingNode' supports regOptional operands // otherwise, false. // // Return Value: -// true if 'node' is a containable hardware intrinsic node; otherwise, false. +// true if 'node' is a containable by containingNode; otherwise, false. +// +// When true is returned 'node' (and by extension the relevant op of 'containingNode') may be modified +// to handle special scenarios such as CreateScalarUnsafe which exist to bridge the type system with +// the actual registers. // -bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree* node, bool* supportsRegOptional) +// When false is returned 'node' is not modified. +// +bool Lowering::TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, + GenTree** pNode, + bool* supportsRegOptional) { + assert(containingNode != nullptr); + assert((pNode != nullptr) && (*pNode != nullptr)); + assert(supportsRegOptional != nullptr); + NamedIntrinsic containingIntrinsicId = containingNode->GetHWIntrinsicId(); HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(containingIntrinsicId); + GenTree*& node = *pNode; // We shouldn't have called in here if containingNode doesn't support containment assert(HWIntrinsicInfo::SupportsContainment(containingIntrinsicId)); @@ -5213,8 +5335,10 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge switch (category) { case HW_Category_MemoryLoad: - supportsGeneralLoads = (!node->OperIsHWIntrinsic()); + { + supportsGeneralLoads = !node->OperIsHWIntrinsic(); break; + } case HW_Category_SimpleSIMD: { @@ -5227,26 +5351,90 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX2_ConvertToVector256Int32: case NI_AVX2_ConvertToVector256Int64: { - supportsGeneralLoads = (!node->OperIsHWIntrinsic()); + assert(!supportsSIMDScalarLoads); + + if (!containingNode->OperIsMemoryLoad()) + { + // The containable form is the one that takes a SIMD value, that may be in memory. + + if (!comp->canUseVexEncoding()) + { + supportsAlignedSIMDLoads = true; + supportsUnalignedSIMDLoads = !supportsAlignedSIMDLoads; + } + else + { + supportsAlignedSIMDLoads = !comp->opts.MinOpts(); + supportsUnalignedSIMDLoads = true; + } + + // General loads are a bit special where we need at least `sizeof(simdType) / (sizeof(baseType) + // * 2)` elements + // For example: + // * ConvertToVector128Int16 - sizeof(simdType) = 16; sizeof(baseType) = 1; expectedSize = 8 + // * ConvertToVector128Int32 - sizeof(simdType) = 16; sizeof(baseType) = 1 | 2; + // expectedSize = 8 | 4 + // * ConvertToVector128Int64 - sizeof(simdType) = 16; sizeof(baseType) = 1 | 2 | 4; + // expectedSize = 8 | 4 | 2 + // * ConvertToVector256Int16 - sizeof(simdType) = 32; sizeof(baseType) = 1; expectedSize = 16 + // * ConvertToVector256Int32 - sizeof(simdType) = 32; sizeof(baseType) = 1 | 2; + // expectedSize = 16 | 8 + // * ConvertToVector256Int64 - sizeof(simdType) = 32; sizeof(baseType) = 1 | 2 | 4; + // expectedSize = 16 | 8 | 4 + + const unsigned sizeof_simdType = genTypeSize(containingNode->TypeGet()); + const unsigned sizeof_baseType = genTypeSize(containingNode->GetSimdBaseType()); + + assert((sizeof_simdType == 16) || (sizeof_simdType == 32)); + assert((sizeof_baseType == 1) || (sizeof_baseType == 2) || (sizeof_baseType == 4)); + + const unsigned expectedSize = sizeof_simdType / (sizeof_baseType * 2); + const unsigned operandSize = genTypeSize(node->TypeGet()); + + assert((sizeof_simdType != 16) || (expectedSize == 8) || (expectedSize == 4) || + (expectedSize == 2)); + assert((sizeof_simdType != 32) || (expectedSize == 16) || (expectedSize == 8) || + (expectedSize == 4)); + + supportsGeneralLoads = (operandSize >= expectedSize); + } + else + { + // The memory form of this already takes a pointer and should be treated like a MemoryLoad + supportsGeneralLoads = !node->OperIsHWIntrinsic(); + } + break; + } + + case NI_SSE2_ConvertToVector128Double: + case NI_SSE3_MoveAndDuplicate: + case NI_AVX_ConvertToVector256Double: + { + assert(!supportsSIMDScalarLoads); + + // Most instructions under the non-VEX encoding require aligned operands. + // Those used for Sse2.ConvertToVector128Double (CVTDQ2PD and CVTPS2PD) + // and Sse3.MoveAndDuplicate (MOVDDUP) are exceptions and don't fail for + // unaligned inputs as they read mem64 (half the vector width) instead + + supportsAlignedSIMDLoads = !comp->opts.MinOpts(); + supportsUnalignedSIMDLoads = true; + + const unsigned expectedSize = genTypeSize(containingNode->TypeGet()) / 2; + const unsigned operandSize = genTypeSize(node->TypeGet()); + + supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize); break; } default: { - if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) - { - // These intrinsics only expect 16 or 32-byte nodes for containment - break; - } + assert(!supportsSIMDScalarLoads); if (!comp->canUseVexEncoding()) { - // Most instructions under the non-VEX encoding require aligned operands. - // Those used for Sse2.ConvertToVector128Double (CVTDQ2PD and CVTPS2PD) - // are exceptions and don't fail for unaligned inputs. - - supportsAlignedSIMDLoads = (containingIntrinsicId != NI_SSE2_ConvertToVector128Double); - supportsUnalignedSIMDLoads = !supportsAlignedSIMDLoads; + assert(!supportsUnalignedSIMDLoads); + supportsAlignedSIMDLoads = true; } else { @@ -5254,7 +5442,10 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge supportsUnalignedSIMDLoads = true; } - supportsGeneralLoads = supportsUnalignedSIMDLoads; + const unsigned expectedSize = genTypeSize(containingNode->TypeGet()); + const unsigned operandSize = genTypeSize(node->TypeGet()); + + supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize); break; } } @@ -5283,11 +5474,9 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX_Blend: case NI_AVX_Compare: case NI_AVX_DotProduct: - case NI_AVX_InsertVector128: case NI_AVX_Permute: case NI_AVX_Permute2x128: case NI_AVX2_Blend: - case NI_AVX2_InsertVector128: case NI_AVX2_MultipleSumAbsoluteDifferences: case NI_AVX2_Permute2x128: case NI_AVX2_Permute4x64: @@ -5297,17 +5486,29 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX2_ShuffleHigh: case NI_AVX2_ShuffleLow: { - if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) - { - // These intrinsics only expect 16 or 32-byte nodes for containment - break; - } assert(!supportsSIMDScalarLoads); + const unsigned expectedSize = genTypeSize(containingNode->GetSimdBaseType()); + const unsigned operandSize = genTypeSize(node->TypeGet()); + supportsAlignedSIMDLoads = !comp->canUseVexEncoding() || !comp->opts.MinOpts(); supportsUnalignedSIMDLoads = comp->canUseVexEncoding(); - supportsGeneralLoads = supportsUnalignedSIMDLoads; + supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize); + break; + } + case NI_AVX_InsertVector128: + case NI_AVX2_InsertVector128: + { + // InsertVector128 is special in that that it returns a TYP_SIMD32 but takes a TYP_SIMD16 + assert(!supportsSIMDScalarLoads); + + const unsigned expectedSize = 16; + const unsigned operandSize = genTypeSize(node->TypeGet()); + + supportsAlignedSIMDLoads = !comp->canUseVexEncoding() || !comp->opts.MinOpts(); + supportsUnalignedSIMDLoads = comp->canUseVexEncoding(); + supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize); break; } @@ -5315,16 +5516,13 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_SSE41_Insert: case NI_SSE41_X64_Insert: { + assert(supportsAlignedSIMDLoads == false); + assert(supportsUnalignedSIMDLoads == false); + if (containingNode->GetSimdBaseType() == TYP_FLOAT) { assert(containingIntrinsicId == NI_SSE41_Insert); - if (genTypeSize(node->TypeGet()) != 16) - { - // These intrinsics only expect 16-byte nodes for containment - break; - } - // Sse41.Insert(V128, V128, byte) is a bit special // in that it has different behavior depending on whether the // second operand is coming from a register or memory. When coming @@ -5333,8 +5531,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge // from memory, it only works with the lowest element and is effectively // a `SIMDScalar`. - assert(supportsAlignedSIMDLoads == false); - assert(supportsUnalignedSIMDLoads == false); assert(supportsGeneralLoads == false); assert(supportsSIMDScalarLoads == false); @@ -5342,8 +5538,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge GenTree* op2 = containingNode->Op(2); GenTree* op3 = containingNode->Op(3); - assert(node == op2); - // The upper two bits of the immediate value are ignored if // op2 comes from memory. In order to support using the upper // bits, we need to disable containment support if op3 is not @@ -5363,9 +5557,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge // We should only get here for integral nodes. assert(varTypeIsIntegral(node->TypeGet())); - - assert(supportsAlignedSIMDLoads == false); - assert(supportsUnalignedSIMDLoads == false); assert(supportsSIMDScalarLoads == false); const unsigned expectedSize = genTypeSize(containingNode->GetSimdBaseType()); @@ -5377,12 +5568,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX_CompareScalar: { - if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) - { - // These intrinsics only expect 16 or 32-byte nodes for containment - break; - } - assert(supportsAlignedSIMDLoads == false); assert(supportsUnalignedSIMDLoads == false); @@ -5413,21 +5598,38 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: { + if (!varTypeIsIntegral(node->TypeGet())) + { + // The floating-point overload doesn't require any special semantics + supportsSIMDScalarLoads = true; + supportsGeneralLoads = supportsSIMDScalarLoads; + break; + } + + // The integral overloads only take GPR/mem assert(supportsSIMDScalarLoads == false); const unsigned expectedSize = genTypeSize(genActualType(containingNode->GetSimdBaseType())); const unsigned operandSize = genTypeSize(node->TypeGet()); - supportsGeneralLoads = (operandSize == expectedSize); + supportsGeneralLoads = (operandSize >= expectedSize); break; } case NI_AVX2_BroadcastScalarToVector128: case NI_AVX2_BroadcastScalarToVector256: { - // The memory form of this already takes a pointer, and cannot be further contained. - // The containable form is the one that takes a SIMD value, that may be in memory. - supportsGeneralLoads = (node->TypeGet() == TYP_SIMD16); + if (!containingNode->OperIsMemoryLoad()) + { + // The containable form is the one that takes a SIMD value, that may be in memory. + supportsSIMDScalarLoads = true; + supportsGeneralLoads = supportsSIMDScalarLoads; + } + else + { + // The memory form of this already takes a pointer and should be treated like a MemoryLoad + supportsGeneralLoads = !node->OperIsHWIntrinsic(); + } break; } @@ -5449,23 +5651,18 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge break; } + // The integral overloads only take GPR/mem assert(supportsSIMDScalarLoads == false); const unsigned expectedSize = genTypeSize(genActualType(containingNode->GetSimdBaseType())); const unsigned operandSize = genTypeSize(node->TypeGet()); - supportsGeneralLoads = (operandSize == expectedSize); + supportsGeneralLoads = (operandSize >= expectedSize); break; } default: { - if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) - { - // These intrinsics only expect 16 or 32-byte nodes for containment - break; - } - supportsSIMDScalarLoads = true; supportsGeneralLoads = supportsSIMDScalarLoads; break; @@ -5508,20 +5705,55 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge } } - noway_assert(supportsRegOptional != nullptr); *supportsRegOptional = supportsGeneralLoads; if (!node->OperIsHWIntrinsic()) { - return supportsGeneralLoads && IsContainableMemoryOp(node); + return supportsGeneralLoads && (IsContainableMemoryOp(node) || node->IsCnsNonZeroFltOrDbl()); } // TODO-XArch: Update this to be table driven, if possible. - NamedIntrinsic intrinsicId = node->AsHWIntrinsic()->GetHWIntrinsicId(); + GenTreeHWIntrinsic* hwintrinsic = node->AsHWIntrinsic(); + NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId(); switch (intrinsicId) { + case NI_Vector128_CreateScalarUnsafe: + case NI_Vector256_CreateScalarUnsafe: + { + if (!supportsSIMDScalarLoads) + { + return false; + } + + GenTree* op1 = hwintrinsic->Op(1); + bool op1SupportsRegOptional = false; + + if (!TryGetContainableHWIntrinsicOp(containingNode, &op1, &op1SupportsRegOptional)) + { + return false; + } + + LIR::Use use; + if (!BlockRange().TryGetUse(node, &use) || (use.User() != containingNode)) + { + return false; + } + + // We have CreateScalarUnsafe where the underlying scalar is directly containable + // by containingNode. As such, we'll just remove CreateScalarUnsafe and consume + // the value directly. + + use.ReplaceWith(op1); + BlockRange().Remove(node); + + node = op1; + node->ClearContained(); + + return true; + } + case NI_SSE_LoadAlignedVector128: case NI_SSE2_LoadAlignedVector128: case NI_AVX_LoadAlignedVector256: @@ -5567,7 +5799,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge void Lowering::ContainCheckHWIntrinsicAddr(GenTreeHWIntrinsic* node, GenTree* addr) { assert((addr->TypeGet() == TYP_I_IMPL) || (addr->TypeGet() == TYP_BYREF)); - TryCreateAddrMode(addr, true); + TryCreateAddrMode(addr, true, node); if ((addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA) || (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp))) && IsSafeToContainMem(node, addr)) @@ -5709,7 +5941,22 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) bool supportsRegOptional = false; - if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + if (node->OperIsMemoryLoad()) + { + // We have a few cases that can be potential memory loads + + assert((intrinsicId == NI_SSE41_ConvertToVector128Int16) || + (intrinsicId == NI_SSE41_ConvertToVector128Int32) || + (intrinsicId == NI_SSE41_ConvertToVector128Int64) || + (intrinsicId == NI_AVX2_BroadcastScalarToVector128) || + (intrinsicId == NI_AVX2_BroadcastScalarToVector256) || + (intrinsicId == NI_AVX2_ConvertToVector256Int16) || + (intrinsicId == NI_AVX2_ConvertToVector256Int32) || + (intrinsicId == NI_AVX2_ConvertToVector256Int64)); + + ContainCheckHWIntrinsicAddr(node, op1); + } + else if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); } @@ -5765,13 +6012,13 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { bool supportsRegOptional = false; - if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } else if ((isCommutative || (intrinsicId == NI_BMI2_MultiplyNoFlags) || (intrinsicId == NI_BMI2_X64_MultiplyNoFlags)) && - IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); @@ -5817,7 +6064,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) if (!HWIntrinsicInfo::isImmOp(intrinsicId, op2)) { - if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } @@ -5839,7 +6086,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { // These intrinsics have op2 as an imm and op1 as a reg/mem - if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); } @@ -5866,7 +6113,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) if (HWIntrinsicInfo::isImmOp(intrinsicId, op2)) { - if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); } @@ -5875,7 +6122,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) op1->SetRegOptional(); } } - else if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + else if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } @@ -5888,7 +6135,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AES_KeygenAssist: { - if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); } @@ -6016,18 +6263,19 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) // Set op regOptional only if none of them is containable. // Prefer to make op3 contained, - if (resultOpNum != 3 && IsContainableHWIntrinsicOp(node, op3, &supportsOp3RegOptional)) + if (resultOpNum != 3 && TryGetContainableHWIntrinsicOp(node, &op3, &supportsOp3RegOptional)) { // result = (op1 * op2) + [op3] MakeSrcContained(node, op3); } - else if (resultOpNum != 2 && IsContainableHWIntrinsicOp(node, op2, &supportsOp2RegOptional)) + else if (resultOpNum != 2 && + TryGetContainableHWIntrinsicOp(node, &op2, &supportsOp2RegOptional)) { // result = (op1 * [op2]) + op3 MakeSrcContained(node, op2); } else if (resultOpNum != 1 && !HWIntrinsicInfo::CopiesUpperBits(intrinsicId) && - IsContainableHWIntrinsicOp(node, op1, &supportsOp1RegOptional)) + TryGetContainableHWIntrinsicOp(node, &op1, &supportsOp1RegOptional)) { // result = ([op1] * op2) + op3 MakeSrcContained(node, op1); @@ -6057,7 +6305,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AVX_BlendVariable: case NI_AVX2_BlendVariable: { - if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } @@ -6070,7 +6318,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AVXVNNI_MultiplyWideningAndAdd: case NI_AVXVNNI_MultiplyWideningAndAddSaturate: { - if (IsContainableHWIntrinsicOp(node, op3, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op3, &supportsRegOptional)) { MakeSrcContained(node, op3); } @@ -6083,11 +6331,11 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_BMI2_MultiplyNoFlags: case NI_BMI2_X64_MultiplyNoFlags: { - if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } - else if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional)) + else if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional)) { MakeSrcContained(node, op1); // MultiplyNoFlags is a Commutative operation, so swap the first two operands here @@ -6141,7 +6389,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AVX2_Permute2x128: case NI_PCLMULQDQ_CarrylessMultiply: { - if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional)) + if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional)) { MakeSrcContained(node, op2); } diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 9308836ff78fc..88f137ab65764 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -1299,6 +1299,10 @@ void LinearScan::doLinearScan() DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_POST)); +#ifdef DEBUG + compiler->fgDebugCheckLinks(); +#endif + compiler->compLSRADone = true; } @@ -2808,7 +2812,7 @@ regNumber LinearScan::allocateReg(Interval* currentInterval, bool wasAssigned = regSelector->foundUnassignedReg() && (assignedInterval != nullptr) && (assignedInterval->physReg == foundReg); unassignPhysReg(availablePhysRegRecord ARM_ARG(currentInterval->registerType)); - if (regSelector->isMatchingConstant()) + if (regSelector->isMatchingConstant() && compiler->opts.OptimizationEnabled()) { assert(assignedInterval->isConstant); refPosition->treeNode->SetReuseRegVal(); @@ -6415,7 +6419,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree, else { JITDUMP("at end of " FMT_BB ":\n", block->bbNum); - if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH) + if (block->KindIs(BBJ_COND, BBJ_SWITCH)) { noway_assert(!blockRange.IsEmpty()); @@ -6427,7 +6431,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree, } else { - assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS); + assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS)); blockRange.InsertAtEnd(LIR::SeqTree(compiler, simdNode)); } } @@ -7291,7 +7295,7 @@ void LinearScan::insertMove( { // Put the copy at the bottom GenTree* lastNode = blockRange.LastNode(); - if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH) + if (block->KindIs(BBJ_COND, BBJ_SWITCH)) { noway_assert(!blockRange.IsEmpty()); @@ -7359,7 +7363,7 @@ void LinearScan::insertSwap( { // Put the copy at the bottom // If there's a branch, make an embedded statement that executes just prior to the branch - if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH) + if (block->KindIs(BBJ_COND, BBJ_SWITCH)) { noway_assert(!blockRange.IsEmpty()); @@ -7371,7 +7375,7 @@ void LinearScan::insertSwap( } else { - assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS); + assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS)); blockRange.InsertAtEnd(std::move(swapRange)); } } diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 1b549424f0fc4..052c3f93999a3 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1772,7 +1772,7 @@ class LinearScan : public LinearScanInterface // The following keep track of information about internal (temporary register) intervals // during the building of a single node. - static const int MaxInternalCount = 4; + static const int MaxInternalCount = 5; RefPosition* internalDefs[MaxInternalCount]; int internalCount = 0; bool setInternalRegsDelayFree; diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 73b971ec5932f..f18099f4f573e 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -522,7 +522,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_BLK: - case GT_DYN_BLK: // These should all be eliminated prior to Lowering. assert(!"Non-store block node in Lowering"); srcCount = 0; @@ -1091,55 +1090,52 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) } } } - else + else if (intrin.op2 != nullptr) { - if (intrin.op2 != nullptr) - { - // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg - // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use. + // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg + // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use. - assert(intrin.op1 != nullptr); + assert(intrin.op1 != nullptr); - bool forceOp2DelayFree = false; - if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) + bool forceOp2DelayFree = false; + if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) + { + if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal())) { - if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal())) - { - // If the index is not a constant and the object is not contained or is a local - // we will need a general purpose register to calculate the address - // internal register must not clobber input index - // TODO-Cleanup: An internal register will never clobber a source; this code actually - // ensures that the index (op2) doesn't interfere with the target. - buildInternalIntRegisterDefForNode(intrinsicTree); - forceOp2DelayFree = true; - } - - if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained()) - { - // If the index is not a constant or op1 is in register, - // we will use the SIMD temp location to store the vector. - var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16; - compiler->getSIMDInitTempVarNum(requiredSimdTempType); - } + // If the index is not a constant and the object is not contained or is a local + // we will need a general purpose register to calculate the address + // internal register must not clobber input index + // TODO-Cleanup: An internal register will never clobber a source; this code actually + // ensures that the index (op2) doesn't interfere with the target. + buildInternalIntRegisterDefForNode(intrinsicTree); + forceOp2DelayFree = true; } - if (forceOp2DelayFree) - { - srcCount += BuildDelayFreeUses(intrin.op2); - } - else + if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained()) { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2); + // If the index is not a constant or op1 is in register, + // we will use the SIMD temp location to store the vector. + var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16; + compiler->getSIMDInitTempVarNum(requiredSimdTempType); } + } - if (intrin.op3 != nullptr) - { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3); + if (forceOp2DelayFree) + { + srcCount += BuildDelayFreeUses(intrin.op2); + } + else + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2); + } - if (intrin.op4 != nullptr) - { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4); - } + if (intrin.op3 != nullptr) + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3); + + if (intrin.op4 != nullptr) + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4); } } } diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index ef7a2d0440aa4..a8db1264b64af 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -694,36 +694,40 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) { buildInternalIntRegisterDefForNode(blkNode); #ifdef TARGET_ARM64 - const bool dstAddrMayNeedReg = dstAddr->isContained(); - const bool srcAddrMayNeedReg = src->OperIs(GT_LCL_VAR, GT_LCL_FLD) || - ((srcAddrOrFill != nullptr) && srcAddrOrFill->isContained()); + const bool canUseLoadStorePairIntRegsInstrs = (size >= 2 * REGSIZE_BYTES); - if (srcAddrMayNeedReg && dstAddrMayNeedReg) + if (canUseLoadStorePairIntRegsInstrs) { - // The following allocates an additional integer register in a case - // when a load instruction and a store instruction cannot be encoded. + // CodeGen can use ldp/stp instructions sequence. buildInternalIntRegisterDefForNode(blkNode); - // In this case, CodeGen will use a SIMD register for copying. - buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); - // And in case of a larger block size, two SIMD registers. - if (size >= 2 * REGSIZE_BYTES) - { - buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); - } } - else if (srcAddrMayNeedReg || dstAddrMayNeedReg) + + const bool isSrcAddrLocal = src->OperIs(GT_LCL_VAR, GT_LCL_FLD) || + ((srcAddrOrFill != nullptr) && srcAddrOrFill->OperIsLocalAddr()); + const bool isDstAddrLocal = dstAddr->OperIsLocalAddr(); + + // CodeGen can use 16-byte SIMD ldp/stp for larger block sizes + // only when both source and destination base address registers have known alignment. + // This is the case, when both registers are either sp or fp. + bool canUse16ByteWideInstrs = isSrcAddrLocal && isDstAddrLocal && (size >= 2 * FP_REGSIZE_BYTES); + + // Note that the SIMD registers allocation is speculative - LSRA doesn't know at this point + // whether CodeGen will use SIMD registers (i.e. if such instruction sequence will be more optimal). + // Therefore, it must allocate an additional integer register anyway. + if (canUse16ByteWideInstrs) { - if (size >= 2 * REGSIZE_BYTES) - { - buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); - buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); - } - else - { - buildInternalIntRegisterDefForNode(blkNode); - } + buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); + buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); } - else if (size >= 2 * REGSIZE_BYTES) + + const bool srcAddrMayNeedReg = + isSrcAddrLocal || ((srcAddrOrFill != nullptr) && srcAddrOrFill->isContained()); + const bool dstAddrMayNeedReg = isDstAddrLocal || dstAddr->isContained(); + + // The following allocates an additional integer register in a case + // when a load instruction and a store instruction cannot be encoded using offset + // from a corresponding base register. + if (srcAddrMayNeedReg && dstAddrMayNeedReg) { buildInternalIntRegisterDefForNode(blkNode); } @@ -781,7 +785,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) if (blkNode->OperIs(GT_STORE_DYN_BLK)) { useCount++; - BuildUse(blkNode->AsDynBlk()->gtDynamicSize, sizeRegMask); + BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); } buildInternalRegisterUses(); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index a48d7e7bdee57..d58f1996091fa 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3078,6 +3078,15 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates) return 1; } +#ifdef TARGET_ARM64 + // Must happen before OperIsHWIntrinsic case, + // but this occurs when a vector zero node is marked as contained. + if (node->IsVectorZero()) + { + return 0; + } +#endif + #if !defined(TARGET_64BIT) if (node->OperIs(GT_LONG)) { @@ -3164,6 +3173,14 @@ int LinearScan::BuildDelayFreeUses(GenTree* node, GenTree* rmwNode, regMaskTP ca { use = BuildUse(node, candidates); } +#ifdef TARGET_ARM64 + // Must happen before OperIsHWIntrinsic case, + // but this occurs when a vector zero node is marked as contained. + else if (node->IsVectorZero()) + { + return 0; + } +#endif #ifdef FEATURE_HW_INTRINSICS else if (node->OperIsHWIntrinsic()) { diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index ce1de0b6f4fde..e679f00b3bca3 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -496,7 +496,6 @@ int LinearScan::BuildNode(GenTree* tree) case GT_OBJ: #endif case GT_BLK: - case GT_DYN_BLK: // These should all be eliminated prior to Lowering. assert(!"Non-store block node in Lowering"); srcCount = 0; @@ -1438,7 +1437,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) if (blkNode->OperIs(GT_STORE_DYN_BLK)) { useCount++; - BuildUse(blkNode->AsDynBlk()->gtDynamicSize, sizeRegMask); + BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); } #ifdef TARGET_X86 diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 972cecf7cd2ee..f07fe3ca9ed02 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -4866,10 +4866,6 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, GenTreeCall::Use* argx->gtFlags &= ~(GTF_ALL_EFFECT) | (argx->AsBlk()->Addr()->gtFlags & GTF_ALL_EFFECT); argx->SetIndirExceptionFlags(this); } - else - { - argx->gtFlags |= GTF_DONT_CSE; - } // Copy the valuetype to the temp GenTree* copyBlk = gtNewBlkOpNode(dest, argx, false /* not volatile */, true /* copyBlock */); @@ -5198,7 +5194,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree) asIndex->Arr()->AsStrCon()->gtSconCPX, &length); if ((cnsIndex < length) && (str != nullptr)) { - GenTree* cnsCharNode = gtNewIconNode(str[cnsIndex], elemTyp); + GenTree* cnsCharNode = gtNewIconNode(str[cnsIndex], TYP_INT); INDEBUG(cnsCharNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); return cnsCharNode; } @@ -10431,15 +10427,8 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigne { if (indirTree != nullptr) { - if (indirTree->OperIsBlk() && !isBlkReqd) - { - effectiveVal->SetOper(GT_IND); - } - else - { - // If we have an indirection and a block is required, it should already be a block. - assert(indirTree->OperIsBlk() || !isBlkReqd); - } + // If we have an indirection and a block is required, it should already be a block. + assert(indirTree->OperIsBlk() || !isBlkReqd); effectiveVal->gtType = asgType; } else @@ -10778,7 +10767,7 @@ GenTree* Compiler::fgMorphFieldAssignToSimdSetElement(GenTree* tree) // A folded GenTree* instance or nullptr if something prevents folding. // -GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree) +GenTreeOp* Compiler::fgMorphCommutative(GenTreeOp* tree) { assert(varTypeIsIntegralOrI(tree->TypeGet())); assert(tree->OperIs(GT_ADD, GT_MUL, GT_OR, GT_AND, GT_XOR)); @@ -10850,7 +10839,7 @@ GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree) DEBUG_DESTROY_NODE(foldedCns); INDEBUG(cns1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); - return op1; + return op1->AsOp(); } //------------------------------------------------------------------------------ @@ -10863,6 +10852,8 @@ GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree) // A folded GenTree* instance, or nullptr if it couldn't be folded GenTree* Compiler::fgMorphCastedBitwiseOp(GenTreeOp* tree) { + // This transform does not preserve VNs and deletes a node. + assert(fgGlobalMorph); assert(varTypeIsIntegralOrI(tree)); assert(tree->OperIs(GT_OR, GT_AND, GT_XOR)); @@ -11610,7 +11601,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) break; case GT_OBJ: case GT_BLK: - case GT_DYN_BLK: case GT_IND: // A non-null mac here implies this node is part of an address computation (the tree parent is // GT_ADDR). @@ -11849,7 +11839,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } } // if (op2) +#ifndef TARGET_64BIT DONE_MORPHING_CHILDREN: +#endif // !TARGET_64BIT if (tree->OperIsIndirOrArrLength()) { @@ -11984,8 +11976,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) */ GenTree* temp; - GenTree* cns1; - GenTree* cns2; size_t ival1; GenTree* lclVarTree; GenTree* effectiveOp1; @@ -12236,335 +12226,15 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) case GT_OR: case GT_XOR: case GT_AND: - - /* Commute any non-REF constants to the right */ - - noway_assert(op1); - if (op1->OperIsConst() && (op1->gtType != TYP_REF)) - { - // TODO-Review: We used to assert here that - // noway_assert(!op2->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD)); - // With modifications to AddrTaken==>AddrExposed, we did more assertion propagation, - // and would sometimes hit this assertion. This may indicate a missed "remorph". - // Task is to re-enable this assertion and investigate. - - /* Swap the operands */ - tree->AsOp()->gtOp1 = op2; - tree->AsOp()->gtOp2 = op1; - - op1 = op2; - op2 = tree->AsOp()->gtOp2; - } - - // Fold "cmp & 1" to just "cmp" - if (tree->OperIs(GT_AND) && tree->TypeIs(TYP_INT) && op1->OperIsCompare() && op2->IsIntegralConst(1) && - !gtIsActiveCSE_Candidate(tree) && !gtIsActiveCSE_Candidate(op2)) - { - DEBUG_DESTROY_NODE(op2); - DEBUG_DESTROY_NODE(tree); - return op1; - } - - // See if we can fold floating point operations (can regress minopts mode) - if (opts.OptimizationEnabled() && varTypeIsFloating(tree->TypeGet()) && !optValnumCSE_phase) - { - if ((oper == GT_MUL) && !op1->IsCnsFltOrDbl() && op2->IsCnsFltOrDbl()) - { - if (op2->AsDblCon()->gtDconVal == 2.0) - { - bool needsComma = !op1->OperIsLeaf() && !op1->IsLocal(); - // if op1 is not a leaf/local we have to introduce a temp via GT_COMMA. - // Unfortunately, it's not optHoistLoopCode-friendly yet so let's do it later. - if (!needsComma || (fgOrder == FGOrderLinear)) - { - // Fold "x*2.0" to "x+x" - op2 = fgMakeMultiUse(&tree->AsOp()->gtOp1); - op1 = tree->AsOp()->gtOp1; - oper = GT_ADD; - tree = gtNewOperNode(oper, tree->TypeGet(), op1, op2); - INDEBUG(tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); - } - } - else if (op2->AsDblCon()->gtDconVal == 1.0) - { - // Fold "x*1.0" to "x" - DEBUG_DESTROY_NODE(op2); - DEBUG_DESTROY_NODE(tree); - return op1; - } - } - } - - /* See if we can fold GT_ADD nodes. */ - - if (oper == GT_ADD) - { - /* Fold "((x+icon1)+(y+icon2)) to ((x+y)+(icon1+icon2))" */ - - if (op1->gtOper == GT_ADD && op2->gtOper == GT_ADD && !gtIsActiveCSE_Candidate(op2) && - op1->AsOp()->gtOp2->gtOper == GT_CNS_INT && op2->AsOp()->gtOp2->gtOper == GT_CNS_INT && - !op1->gtOverflow() && !op2->gtOverflow()) - { - // Don't create a byref pointer that may point outside of the ref object. - // If a GC happens, the byref won't get updated. This can happen if one - // of the int components is negative. It also requires the address generation - // be in a fully-interruptible code region. - if (!varTypeIsGC(op1->AsOp()->gtOp1->TypeGet()) && !varTypeIsGC(op2->AsOp()->gtOp1->TypeGet())) - { - cns1 = op1->AsOp()->gtOp2; - cns2 = op2->AsOp()->gtOp2; - - ssize_t value = cns1->AsIntCon()->IconValue() + cns2->AsIntCon()->IconValue(); - cns1->AsIntCon()->SetValueTruncating(value); - - tree->AsOp()->gtOp2 = cns1; - DEBUG_DESTROY_NODE(cns2); - - op1->AsOp()->gtOp2 = op2->AsOp()->gtOp1; - op1->gtFlags |= (op1->AsOp()->gtOp2->gtFlags & GTF_ALL_EFFECT); - DEBUG_DESTROY_NODE(op2); - op2 = tree->AsOp()->gtOp2; - } - } - - if (op2->IsCnsIntOrI() && varTypeIsIntegralOrI(typ)) - { - // Fold (x + 0). - if ((op2->AsIntConCommon()->IconValue() == 0) && !gtIsActiveCSE_Candidate(tree)) - { - // Remove the addition iff it won't change the tree type - // to TYP_REF. - - if (!gtIsActiveCSE_Candidate(op2) && - ((op1->TypeGet() == tree->TypeGet()) || (op1->TypeGet() != TYP_REF))) - { - if (fgGlobalMorph && (op2->OperGet() == GT_CNS_INT) && - (op2->AsIntCon()->gtFieldSeq != nullptr) && - (op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField())) - { - fgAddFieldSeqForZeroOffset(op1, op2->AsIntCon()->gtFieldSeq); - } - - DEBUG_DESTROY_NODE(op2); - DEBUG_DESTROY_NODE(tree); - - return op1; - } - } - } - - if (opts.OptimizationEnabled() && fgGlobalMorph) - { - // - a + b = > b - a - // ADD((NEG(a), b) => SUB(b, a) - - // Skip optimization if non-NEG operand is constant. - if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && !op2->IsIntegralConst() && - gtCanSwapOrder(op1, op2)) - { - // tree: ADD - // op1: NEG - // op2: b - // op1Child: a - - GenTree* op1Child = op1->AsOp()->gtOp1; // a - oper = GT_SUB; - tree->SetOper(oper, GenTree::PRESERVE_VN); - tree->AsOp()->gtOp1 = op2; - tree->AsOp()->gtOp2 = op1Child; - - DEBUG_DESTROY_NODE(op1); - - op1 = op2; - op2 = op1Child; - } - // a + -b = > a - b - // ADD(a, (NEG(b)) => SUB(a, b) - else if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG)) - { - // a is non constant because it was already canonicalized to have - // variable on the left and constant on the right. - - // tree: ADD - // op1: a - // op2: NEG - // op2Child: b - - GenTree* op2Child = op2->AsOp()->gtOp1; // a - oper = GT_SUB; - tree->SetOper(oper, GenTree::PRESERVE_VN); - tree->AsOp()->gtOp2 = op2Child; - - DEBUG_DESTROY_NODE(op2); - - op2 = op2Child; - } - } - } - /* See if we can fold GT_MUL by const nodes */ - else if (oper == GT_MUL && op2->IsCnsIntOrI() && !optValnumCSE_phase) - { -#ifndef TARGET_64BIT - noway_assert(typ <= TYP_UINT); -#endif // TARGET_64BIT - noway_assert(!tree->gtOverflow()); - - ssize_t mult = op2->AsIntConCommon()->IconValue(); - bool op2IsConstIndex = op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr && - op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq(); - - assert(!op2IsConstIndex || op2->AsIntCon()->gtFieldSeq->m_next == nullptr); - - if (mult == 0) - { - // We may be able to throw away op1 (unless it has side-effects) - - if ((op1->gtFlags & GTF_SIDE_EFFECT) == 0) - { - DEBUG_DESTROY_NODE(op1); - DEBUG_DESTROY_NODE(tree); - return op2; // Just return the "0" node - } - - // We need to keep op1 for the side-effects. Hang it off - // a GT_COMMA node - - tree->ChangeOper(GT_COMMA); - return tree; - } - - size_t abs_mult = (mult >= 0) ? mult : -mult; - size_t lowestBit = genFindLowestBit(abs_mult); - bool changeToShift = false; - - // is it a power of two? (positive or negative) - if (abs_mult == lowestBit) - { - // if negative negate (min-int does not need negation) - if (mult < 0 && mult != SSIZE_T_MIN) - { - // The type of the new GT_NEG node cannot just be op1->TypeGet(). - // Otherwise we may sign-extend incorrectly in cases where the GT_NEG - // node ends up feeding directly a cast, for example in - // GT_CAST(GT_MUL(-1, s_1.ubyte)) - tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_NEG, genActualType(op1->TypeGet()), op1); - fgMorphTreeDone(op1); - } - - // If "op2" is a constant array index, the other multiplicand must be a constant. - // Transfer the annotation to the other one. - if (op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr && - op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq()) - { - assert(op2->AsIntCon()->gtFieldSeq->m_next == nullptr); - GenTree* otherOp = op1; - if (otherOp->OperGet() == GT_NEG) - { - otherOp = otherOp->AsOp()->gtOp1; - } - assert(otherOp->OperGet() == GT_CNS_INT); - assert(otherOp->AsIntCon()->gtFieldSeq == FieldSeqStore::NotAField()); - otherOp->AsIntCon()->gtFieldSeq = op2->AsIntCon()->gtFieldSeq; - } - - if (abs_mult == 1) - { - DEBUG_DESTROY_NODE(op2); - DEBUG_DESTROY_NODE(tree); - return op1; - } - - /* Change the multiplication into a shift by log2(val) bits */ - op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult)); - changeToShift = true; - } - else if ((lowestBit > 1) && jitIsScaleIndexMul(lowestBit) && optAvoidIntMult()) - { - int shift = genLog2(lowestBit); - ssize_t factor = abs_mult >> shift; - - if (factor == 3 || factor == 5 || factor == 9) - { - // if negative negate (min-int does not need negation) - if (mult < 0 && mult != SSIZE_T_MIN) - { - tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_NEG, genActualType(op1->TypeGet()), op1); - fgMorphTreeDone(op1); - } - - GenTree* factorIcon = gtNewIconNode(factor, TYP_I_IMPL); - if (op2IsConstIndex) - { - factorIcon->AsIntCon()->gtFieldSeq = - GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField); - } - - // change the multiplication into a smaller multiplication (by 3, 5 or 9) and a shift - tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_MUL, tree->gtType, op1, factorIcon); - fgMorphTreeDone(op1); - - op2->AsIntConCommon()->SetIconValue(shift); - changeToShift = true; - } - } - if (changeToShift) - { - // vnStore is null before the ValueNumber phase has run - if (vnStore != nullptr) - { - // Update the ValueNumber for 'op2', as we just changed the constant - fgValueNumberTreeConst(op2); - } - oper = GT_LSH; - // Keep the old ValueNumber for 'tree' as the new expr - // will still compute the same value as before - tree->ChangeOper(oper, GenTree::PRESERVE_VN); - - goto DONE_MORPHING_CHILDREN; - } - } - else if (fgOperIsBitwiseRotationRoot(oper)) - { - tree = fgRecognizeAndMorphBitwiseRotation(tree); - - // fgRecognizeAndMorphBitwiseRotation may return a new tree - oper = tree->OperGet(); - typ = tree->TypeGet(); - op1 = tree->AsOp()->gtOp1; - op2 = tree->AsOp()->gtOp2; - } - - if (fgGlobalMorph && varTypeIsIntegralOrI(tree) && tree->OperIs(GT_AND, GT_OR, GT_XOR)) - { - GenTree* result = fgMorphCastedBitwiseOp(tree->AsOp()); - if (result != nullptr) - { - assert(result->OperIs(GT_CAST)); - assert(result->AsOp()->gtOp2 == nullptr); - // tree got folded to a unary (cast) op - tree = result; - oper = tree->OperGet(); - typ = tree->TypeGet(); - op1 = tree->AsOp()->gtGetOp1(); - op2 = nullptr; - } - } - - if (varTypeIsIntegralOrI(tree->TypeGet()) && tree->OperIs(GT_ADD, GT_MUL, GT_AND, GT_OR, GT_XOR)) + tree = fgOptimizeCommutativeArithmetic(tree->AsOp()); + if (!tree->OperIsSimple()) { - GenTree* foldedTree = fgMorphCommutative(tree->AsOp()); - if (foldedTree != nullptr) - { - tree = foldedTree; - op1 = tree->gtGetOp1(); - op2 = tree->gtGetOp2(); - if (!tree->OperIs(oper)) - { - return tree; - } - } + return tree; } - + typ = tree->TypeGet(); + oper = tree->OperGet(); + op1 = tree->gtGetOp1(); + op2 = tree->gtGetOp2IfPresent(); break; case GT_NOT: @@ -13224,6 +12894,45 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } break; + case GT_INTRINSIC: + if (tree->AsIntrinsic()->gtIntrinsicName == + NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant) + { + // Should be expanded by the time it reaches CSE phase + assert(!optValnumCSE_phase); + + JITDUMP("\nExpanding RuntimeHelpers.IsKnownConstant to "); + if (op1->OperIsConst()) + { + // We're lucky to catch a constant here while importer was not + JITDUMP("true\n"); + DEBUG_DESTROY_NODE(tree, op1); + tree = gtNewIconNode(1); + } + else + { + GenTree* op1SideEffects = nullptr; + gtExtractSideEffList(op1, &op1SideEffects, GTF_ALL_EFFECT); + if (op1SideEffects != nullptr) + { + DEBUG_DESTROY_NODE(tree); + // Keep side-effects of op1 + tree = gtNewOperNode(GT_COMMA, TYP_INT, op1SideEffects, gtNewIconNode(0)); + JITDUMP("false with side effects:\n") + DISPTREE(tree); + } + else + { + JITDUMP("false\n"); + DEBUG_DESTROY_NODE(tree, op1); + tree = gtNewIconNode(0); + } + } + INDEBUG(tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + return tree; + } + break; + default: break; } @@ -13704,11 +13413,381 @@ GenTree* Compiler::fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp) return cmp; } +//------------------------------------------------------------------------ +// fgOptimizeCommutativeArithmetic: Optimizes commutative operations. +// +// Arguments: +// tree - the unchecked GT_ADD/GT_MUL/GT_OR/GT_XOR/GT_AND tree to optimize. +// +// Return Value: +// The optimized tree that can have any shape. +// +GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree) +{ + assert(tree->OperIs(GT_ADD, GT_MUL, GT_OR, GT_XOR, GT_AND)); + assert(!tree->gtOverflowEx()); + + // Commute constants to the right. + if (tree->gtGetOp1()->OperIsConst() && !tree->gtGetOp1()->TypeIs(TYP_REF)) + { + // TODO-Review: We used to assert here that "(!op2->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD))". + // This may indicate a missed "remorph". Task is to re-enable this assertion and investigate. + std::swap(tree->gtOp1, tree->gtOp2); + } + + if (fgOperIsBitwiseRotationRoot(tree->OperGet())) + { + GenTree* rotationTree = fgRecognizeAndMorphBitwiseRotation(tree); + if (rotationTree != nullptr) + { + return rotationTree; + } + } + + if (fgGlobalMorph && tree->OperIs(GT_AND, GT_OR, GT_XOR)) + { + GenTree* castTree = fgMorphCastedBitwiseOp(tree->AsOp()); + if (castTree != nullptr) + { + return castTree; + } + } + + if (varTypeIsIntegralOrI(tree)) + { + genTreeOps oldTreeOper = tree->OperGet(); + GenTreeOp* optimizedTree = fgMorphCommutative(tree->AsOp()); + if (optimizedTree != nullptr) + { + if (!optimizedTree->OperIs(oldTreeOper)) + { + // "optimizedTree" could end up being a COMMA. + return optimizedTree; + } + + tree = optimizedTree; + } + } + + if (!optValnumCSE_phase) + { + GenTree* optimizedTree = nullptr; + if (tree->OperIs(GT_ADD)) + { + optimizedTree = fgOptimizeAddition(tree); + } + else if (tree->OperIs(GT_MUL)) + { + optimizedTree = fgOptimizeMultiply(tree); + } + else if (tree->OperIs(GT_AND)) + { + optimizedTree = fgOptimizeBitwiseAnd(tree); + } + + if (optimizedTree != nullptr) + { + return optimizedTree; + } + } + + return tree; +} + +//------------------------------------------------------------------------ +// fgOptimizeAddition: optimizes addition. +// +// Arguments: +// add - the unchecked GT_ADD tree to optimize. +// +// Return Value: +// The optimized tree, that can have any shape, in case any transformations +// were performed. Otherwise, "nullptr", guaranteeing no state change. +// +GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) +{ + assert(add->OperIs(GT_ADD) && !add->gtOverflow()); + assert(!optValnumCSE_phase); + + GenTree* op1 = add->gtGetOp1(); + GenTree* op2 = add->gtGetOp2(); + + // Fold "((x + icon1) + (y + icon2))" to ((x + y) + (icon1 + icon2))". + // Be careful not to create a byref pointer that may point outside of the ref object. + // Only do this in global morph as we don't recompute the VN for "(x + y)", the new "op2". + if (op1->OperIs(GT_ADD) && op2->OperIs(GT_ADD) && !op1->gtOverflow() && !op2->gtOverflow() && + op1->AsOp()->gtGetOp2()->IsCnsIntOrI() && op2->AsOp()->gtGetOp2()->IsCnsIntOrI() && + !varTypeIsGC(op1->AsOp()->gtGetOp1()) && !varTypeIsGC(op2->AsOp()->gtGetOp1()) && fgGlobalMorph) + { + GenTreeOp* addOne = op1->AsOp(); + GenTreeOp* addTwo = op2->AsOp(); + GenTreeIntCon* constOne = addOne->gtGetOp2()->AsIntCon(); + GenTreeIntCon* constTwo = addTwo->gtGetOp2()->AsIntCon(); + + addOne->gtOp2 = addTwo->gtGetOp1(); + addOne->SetAllEffectsFlags(addOne->gtGetOp1(), addOne->gtGetOp2()); + DEBUG_DESTROY_NODE(addTwo); + + constOne->SetValueTruncating(constOne->IconValue() + constTwo->IconValue()); + op2 = constOne; + add->gtOp2 = constOne; + DEBUG_DESTROY_NODE(constTwo); + } + + // Fold (x + 0) - given it won't change the tree type to TYP_REF. + // TODO-Bug: this code will lose the GC-ness of a tree like "native int + byref(0)". + if (op2->IsIntegralConst(0) && ((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF))) + { + if (op2->IsCnsIntOrI() && (op2->AsIntCon()->gtFieldSeq != nullptr) && + (op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField())) + { + fgAddFieldSeqForZeroOffset(op1, op2->AsIntCon()->gtFieldSeq); + } + + DEBUG_DESTROY_NODE(op2); + DEBUG_DESTROY_NODE(add); + + return op1; + } + + // Note that these transformations are legal for floating-point ADDs as well. + if (opts.OptimizationEnabled()) + { + // - a + b = > b - a + // ADD((NEG(a), b) => SUB(b, a) + + // Do not do this if "op2" is constant for canonicalization purposes. + if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && !op2->IsIntegralConst() && gtCanSwapOrder(op1, op2)) + { + add->SetOper(GT_SUB); + add->gtOp1 = op2; + add->gtOp2 = op1->AsOp()->gtGetOp1(); + + DEBUG_DESTROY_NODE(op1); + + return add; + } + + // a + -b = > a - b + // ADD(a, (NEG(b)) => SUB(a, b) + if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG)) + { + add->SetOper(GT_SUB); + add->gtOp2 = op2->AsOp()->gtGetOp1(); + + DEBUG_DESTROY_NODE(op2); + + return add; + } + } + + return nullptr; +} + +//------------------------------------------------------------------------ +// fgOptimizeMultiply: optimizes multiplication. +// +// Arguments: +// mul - the unchecked TYP_I_IMPL/TYP_INT GT_MUL tree to optimize. +// +// Return Value: +// The optimized tree, that can have any shape, in case any transformations +// were performed. Otherwise, "nullptr", guaranteeing no state change. +// +GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul) +{ + assert(mul->OperIs(GT_MUL)); + assert(varTypeIsIntOrI(mul) || varTypeIsFloating(mul)); + assert(!mul->gtOverflow()); + assert(!optValnumCSE_phase); + + GenTree* op1 = mul->gtGetOp1(); + GenTree* op2 = mul->gtGetOp2(); + + assert(mul->TypeGet() == genActualType(op1)); + assert(mul->TypeGet() == genActualType(op2)); + + if (opts.OptimizationEnabled() && op2->IsCnsFltOrDbl()) + { + double multiplierValue = op2->AsDblCon()->gtDconVal; + + if (multiplierValue == 1.0) + { + // Fold "x * 1.0" to "x". + DEBUG_DESTROY_NODE(op2); + DEBUG_DESTROY_NODE(mul); + + return op1; + } + + // Fold "x * 2.0" to "x + x". + // If op1 is not a local we will have to introduce a temporary via GT_COMMA. + // Unfortunately, it's not optHoistLoopCode-friendly (yet), so we'll only do + // this for locals / after hoisting has run (when rationalization remorphs + // math INTRINSICSs into calls...). + if ((multiplierValue == 2.0) && (op1->IsLocal() || (fgOrder == FGOrderLinear))) + { + op2 = fgMakeMultiUse(&op1); + GenTree* add = gtNewOperNode(GT_ADD, mul->TypeGet(), op1, op2); + INDEBUG(add->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + + return add; + } + } + + if (op2->IsIntegralConst()) + { + ssize_t mult = op2->AsIntConCommon()->IconValue(); + bool op2IsConstIndex = op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr && + op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq(); + + assert(!op2IsConstIndex || op2->AsIntCon()->gtFieldSeq->m_next == nullptr); + + if (mult == 0) + { + // We may be able to throw away op1 (unless it has side-effects) + + if ((op1->gtFlags & GTF_SIDE_EFFECT) == 0) + { + DEBUG_DESTROY_NODE(op1); + DEBUG_DESTROY_NODE(mul); + + return op2; // Just return the "0" node + } + + // We need to keep op1 for the side-effects. Hang it off a GT_COMMA node. + mul->ChangeOper(GT_COMMA, GenTree::PRESERVE_VN); + return mul; + } + +#ifdef TARGET_XARCH + // Should we try to replace integer multiplication with lea/add/shift sequences? + bool mulShiftOpt = compCodeOpt() != SMALL_CODE; +#else // !TARGET_XARCH + bool mulShiftOpt = false; +#endif // !TARGET_XARCH + + size_t abs_mult = (mult >= 0) ? mult : -mult; + size_t lowestBit = genFindLowestBit(abs_mult); + bool changeToShift = false; + + // is it a power of two? (positive or negative) + if (abs_mult == lowestBit) + { + // if negative negate (min-int does not need negation) + if (mult < 0 && mult != SSIZE_T_MIN) + { + op1 = gtNewOperNode(GT_NEG, genActualType(op1), op1); + mul->gtOp1 = op1; + fgMorphTreeDone(op1); + } + + // If "op2" is a constant array index, the other multiplicand must be a constant. + // Transfer the annotation to the other one. + if (op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr && + op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq()) + { + assert(op2->AsIntCon()->gtFieldSeq->m_next == nullptr); + GenTree* otherOp = op1; + if (otherOp->OperGet() == GT_NEG) + { + otherOp = otherOp->AsOp()->gtOp1; + } + assert(otherOp->OperGet() == GT_CNS_INT); + assert(otherOp->AsIntCon()->gtFieldSeq == FieldSeqStore::NotAField()); + otherOp->AsIntCon()->gtFieldSeq = op2->AsIntCon()->gtFieldSeq; + } + + if (abs_mult == 1) + { + DEBUG_DESTROY_NODE(op2); + DEBUG_DESTROY_NODE(mul); + return op1; + } + + // Change the multiplication into a shift by log2(val) bits. + op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult)); + changeToShift = true; + } + else if (mulShiftOpt && (lowestBit > 1) && jitIsScaleIndexMul(lowestBit)) + { + int shift = genLog2(lowestBit); + ssize_t factor = abs_mult >> shift; + + if (factor == 3 || factor == 5 || factor == 9) + { + // if negative negate (min-int does not need negation) + if (mult < 0 && mult != SSIZE_T_MIN) + { + op1 = gtNewOperNode(GT_NEG, genActualType(op1), op1); + mul->gtOp1 = op1; + fgMorphTreeDone(op1); + } + + GenTree* factorIcon = gtNewIconNode(factor, mul->TypeGet()); + if (op2IsConstIndex) + { + factorIcon->AsIntCon()->gtFieldSeq = + GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField); + } + + // change the multiplication into a smaller multiplication (by 3, 5 or 9) and a shift + op1 = gtNewOperNode(GT_MUL, mul->TypeGet(), op1, factorIcon); + mul->gtOp1 = op1; + fgMorphTreeDone(op1); + + op2->AsIntConCommon()->SetIconValue(shift); + changeToShift = true; + } + } + + if (changeToShift) + { + fgUpdateConstTreeValueNumber(op2); + mul->ChangeOper(GT_LSH, GenTree::PRESERVE_VN); + + return mul; + } + } + + return nullptr; +} + +//------------------------------------------------------------------------ +// fgOptimizeBitwiseAnd: optimizes the "and" operation. +// +// Arguments: +// andOp - the GT_AND tree to optimize. +// +// Return Value: +// The optimized tree, currently always a relop, in case any transformations +// were performed. Otherwise, "nullptr", guaranteeing no state change. +// +GenTree* Compiler::fgOptimizeBitwiseAnd(GenTreeOp* andOp) +{ + assert(andOp->OperIs(GT_AND)); + assert(!optValnumCSE_phase); + + GenTree* op1 = andOp->gtGetOp1(); + GenTree* op2 = andOp->gtGetOp2(); + + // Fold "cmp & 1" to just "cmp". + if (andOp->TypeIs(TYP_INT) && op1->OperIsCompare() && op2->IsIntegralConst(1)) + { + DEBUG_DESTROY_NODE(op2); + DEBUG_DESTROY_NODE(andOp); + + return op1; + } + + return nullptr; +} + //------------------------------------------------------------------------ // fgPropagateCommaThrow: propagate a "comma throw" up the tree. // // "Comma throws" in the compiler represent the canonical form of an always -// throwing expression. They have the shape of COMMA(THROW, ZERO), to satsify +// throwing expression. They have the shape of COMMA(THROW, ZERO), to satisfy // the semantic that the original expression produced some value and are // generated by "gtFoldExprConst" when it encounters checked arithmetic that // will determinably overflow. @@ -14347,7 +14426,7 @@ bool Compiler::fgOperIsBitwiseRotationRoot(genTreeOps oper) // tree - tree to check for a rotation pattern // // Return Value: -// An equivalent GT_ROL or GT_ROR tree if a pattern is found; original tree otherwise. +// An equivalent GT_ROL or GT_ROR tree if a pattern is found; "nullptr" otherwise. // // Assumption: // The input is a GT_OR or a GT_XOR tree. @@ -14397,7 +14476,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) // We can't do anything if the tree has assignments, calls, or volatile // reads. Note that we allow GTF_EXCEPT side effect since any exceptions // thrown by the original tree will be thrown by the transformed tree as well. - return tree; + return nullptr; } genTreeOps oper = tree->OperGet(); @@ -14420,7 +14499,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) } else { - return tree; + return nullptr; } // Check if the trees representing the value to shift are identical. @@ -14452,7 +14531,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) } else { - return tree; + return nullptr; } } @@ -14465,7 +14544,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) } else { - return tree; + return nullptr; } } @@ -14475,7 +14554,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) // something like (x << y & 15) or // (x >> (32 - y) & 15 with 32 bit x. // The transformation is not valid. - return tree; + return nullptr; } GenTree* shiftIndexWithAdd = nullptr; @@ -14521,7 +14600,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) // TODO-X86-CQ: we need to handle variable-sized long shifts specially on x86. // GT_LSH, GT_RSH, and GT_RSZ have helpers for this case. We may need // to add helpers for GT_ROL and GT_ROR. - return tree; + return nullptr; } #endif @@ -14575,7 +14654,8 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) return tree; } } - return tree; + + return nullptr; } #if !defined(TARGET_64BIT) @@ -14902,23 +14982,7 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac) break; case GT_STORE_DYN_BLK: - case GT_DYN_BLK: - if (tree->OperGet() == GT_STORE_DYN_BLK) - { - tree->AsDynBlk()->Data() = fgMorphTree(tree->AsDynBlk()->Data()); - } - tree->AsDynBlk()->Addr() = fgMorphTree(tree->AsDynBlk()->Addr()); - tree->AsDynBlk()->gtDynamicSize = fgMorphTree(tree->AsDynBlk()->gtDynamicSize); - - tree->gtFlags &= ~GTF_CALL; - tree->SetIndirExceptionFlags(this); - - if (tree->OperGet() == GT_STORE_DYN_BLK) - { - tree->gtFlags |= tree->AsDynBlk()->Data()->gtFlags & GTF_ALL_EFFECT; - } - tree->gtFlags |= tree->AsDynBlk()->Addr()->gtFlags & GTF_ALL_EFFECT; - tree->gtFlags |= tree->AsDynBlk()->gtDynamicSize->gtFlags & GTF_ALL_EFFECT; + tree = fgMorphStoreDynBlock(tree->AsStoreDynBlk()); break; default: diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp index 233f72ef8f110..d725923478433 100644 --- a/src/coreclr/jit/morphblock.cpp +++ b/src/coreclr/jit/morphblock.cpp @@ -26,7 +26,6 @@ class MorphInitBlockHelper static GenTree* MorphBlock(Compiler* comp, GenTree* tree, bool isDest); static GenTree* MorphCommaBlock(Compiler* comp, GenTreeOp* firstComma); - static GenTreeBlk* MorphDynamicBlock(Compiler* comp, GenTreeDynBlk* dynBlock); protected: Compiler* m_comp; @@ -36,9 +35,7 @@ class MorphInitBlockHelper GenTree* m_dst = nullptr; GenTree* m_src = nullptr; - unsigned m_blockSize = 0; - bool m_blockSizeIsConst = false; - + unsigned m_blockSize = 0; unsigned m_dstLclNum = BAD_VAR_NUM; GenTreeLclVarCommon* m_dstLclNode = nullptr; LclVarDsc* m_dstVarDsc = nullptr; @@ -212,9 +209,8 @@ void MorphInitBlockHelper::PrepareDst() if (m_dst->IsLocal()) { - m_dstLclNode = m_dst->AsLclVarCommon(); - m_dstVarDsc = m_comp->lvaGetDesc(m_dstLclNode); - m_blockSizeIsConst = true; + m_dstLclNode = m_dst->AsLclVarCommon(); + m_dstVarDsc = m_comp->lvaGetDesc(m_dstLclNode); if (m_dst->OperIs(GT_LCL_VAR)) { @@ -248,21 +244,19 @@ void MorphInitBlockHelper::PrepareDst() else { assert(m_dst == m_dst->gtEffectiveVal() && "the commas were skipped in MorphBlock"); - assert(m_dst->OperIs(GT_IND, GT_BLK, GT_OBJ, GT_DYN_BLK)); + assert(m_dst->OperIs(GT_IND, GT_BLK, GT_OBJ)); GenTree* dstAddr = m_dst->AsIndir()->Addr(); if (m_dst->OperGet() == GT_IND) { assert(m_dst->TypeGet() != TYP_STRUCT); - m_blockSize = genTypeSize(m_dst); - m_blockSizeIsConst = true; + m_blockSize = genTypeSize(m_dst); } else { assert(m_dst->OperIsBlk()); - GenTreeBlk* blk = m_dst->AsBlk(); - m_blockSize = blk->Size(); - m_blockSizeIsConst = !blk->OperIs(GT_DYN_BLK); + GenTreeBlk* blk = m_dst->AsBlk(); + m_blockSize = blk->Size(); } noway_assert(dstAddr->TypeIs(TYP_BYREF, TYP_I_IMPL)); @@ -444,22 +438,10 @@ GenTree* MorphInitBlockHelper::MorphBlock(Compiler* comp, GenTree* tree, bool is return tree; } - GenTreeBlk* blkNode = tree->AsBlk(); - if (blkNode->OperIs(GT_DYN_BLK)) - { - blkNode = MorphDynamicBlock(comp, blkNode->AsDynBlk()); - if (blkNode->OperIs(GT_DYN_BLK)) - { - JITDUMP("MorphBlock after:\n"); - DISPTREE(blkNode); - return blkNode; - } - } - - GenTree* blkAddr = blkNode->Addr(); + GenTree* blkAddr = tree->AsBlk()->Addr(); assert(blkAddr != nullptr); assert(blkAddr->TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF)); - // GT_ADDR, GT_LCL_VAR/FLD, GT_ADD, GT_COMMA, GT_CALL, GT_CNST_INT, GT_LCL_VAR/FLD_ADDR + // GT_ADDR, GT_LCL_VAR/FLD, GT_ADD, GT_COMMA, GT_CALL, GT_CNS_INT, GT_LCL_VAR/FLD_ADDR JITDUMP("MorphBlock after:\n"); DISPTREE(tree); @@ -539,41 +521,6 @@ GenTree* MorphInitBlockHelper::MorphCommaBlock(Compiler* comp, GenTreeOp* firstC return res; } -//------------------------------------------------------------------------ -// MorphDynamicBlock: tries to transform a dynamic block as a const block. -// -// static -GenTreeBlk* MorphInitBlockHelper::MorphDynamicBlock(Compiler* comp, GenTreeDynBlk* dynBlock) -{ - if (dynBlock->gtDynamicSize->IsCnsIntOrI()) - { - GenTreeIntCon* dynSize = dynBlock->gtDynamicSize->AsIntCon(); - assert(dynSize->FitsInI32()); - unsigned size = static_cast(dynSize->IconValue()); - // A GT_BLK with size of zero is not supported, - // so if we encounter such a thing we just leave it as a GT_DYN_BLK - if (size != 0) - { - dynBlock->gtDynamicSize = nullptr; - GenTreeBlk* blkNode = dynBlock; - blkNode->ChangeOper(GT_BLK); - blkNode->SetLayout(comp->typGetBlkLayout(size)); - JITDUMP("MorphDynamicBlock: DYN_BLK was morphed into BLK:\n"); - return blkNode; - } - else - { - JITDUMP("MorphDynamicBlock: DYN_BLK with zero size can't be morphed:\n"); - return dynBlock; - } - } - else - { - JITDUMP("MorphDynamicBlock: DYN_BLK with non-const size can't be morphed:\n"); - return dynBlock; - } -} - class MorphCopyBlockHelper : public MorphInitBlockHelper { public: @@ -745,7 +692,7 @@ void MorphCopyBlockHelper::MorphStructCases() if (m_dstVarDsc != nullptr) { - if (m_dstVarDsc->lvPromoted && m_blockSizeIsConst) + if (m_dstVarDsc->lvPromoted) { noway_assert(varTypeIsStruct(m_dstVarDsc)); noway_assert(!m_comp->opts.MinOpts()); @@ -765,7 +712,7 @@ void MorphCopyBlockHelper::MorphStructCases() if (m_srcVarDsc != nullptr) { - if (m_srcVarDsc->lvPromoted && m_blockSizeIsConst) + if (m_srcVarDsc->lvPromoted) { noway_assert(varTypeIsStruct(m_srcVarDsc)); noway_assert(!m_comp->opts.MinOpts()); @@ -912,7 +859,7 @@ void MorphCopyBlockHelper::MorphStructCases() // [000085] -A---------- = long // [000083] D------N---- lclVar long V17 tmp9 // - if (m_blockSizeIsConst && (m_dstVarDsc->lvFieldCnt == 1) && (m_srcVarDsc != nullptr) && + if ((m_dstVarDsc->lvFieldCnt == 1) && (m_srcVarDsc != nullptr) && (m_blockSize == genTypeSize(m_srcVarDsc->TypeGet()))) { // Reject the following tree: @@ -950,7 +897,7 @@ void MorphCopyBlockHelper::MorphStructCases() // [000243] -----+------ \--* addr byref // [000242] D----+-N---- \--* lclVar byref V28 tmp19 // - if (m_blockSizeIsConst && (m_srcVarDsc->lvFieldCnt == 1) && (m_dstVarDsc != nullptr) && + if ((m_srcVarDsc->lvFieldCnt == 1) && (m_dstVarDsc != nullptr) && (m_blockSize == genTypeSize(m_dstVarDsc->TypeGet()))) { // Check for type agreement @@ -1048,9 +995,9 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() { GenTreeOp* asgFields = nullptr; - GenTree* addrSpill = nullptr; - unsigned addrSpillTemp = BAD_VAR_NUM; - bool addrSpillIsStackDest = false; // true if 'addrSpill' represents the address in our local stack frame + GenTree* addrSpill = nullptr; + unsigned addrSpillSrcLclNum = BAD_VAR_NUM; + unsigned addrSpillTemp = BAD_VAR_NUM; GenTree* addrSpillAsg = nullptr; @@ -1095,7 +1042,8 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() // We will spill m_srcAddr (i.e. assign to a temp "BlockOp address local") // no need to clone a new copy as it is only used once // - addrSpill = m_srcAddr; // addrSpill represents the 'm_srcAddr' + addrSpill = m_srcAddr; // addrSpill represents the 'm_srcAddr' + addrSpillSrcLclNum = m_srcLclNum; } } } @@ -1144,28 +1092,13 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() // We will spill m_dstAddr (i.e. assign to a temp "BlockOp address local") // no need to clone a new copy as it is only used once // - addrSpill = m_dstAddr; // addrSpill represents the 'm_dstAddr' + addrSpill = m_dstAddr; // addrSpill represents the 'm_dstAddr' + addrSpillSrcLclNum = m_dstLclNum; } } } } - // TODO-CQ: this should be based on a more general - // "BaseAddress" method, that handles fields of structs, before or after - // morphing. - if ((addrSpill != nullptr) && addrSpill->OperIs(GT_ADDR)) - { - GenTree* addrSpillOp = addrSpill->AsOp()->gtGetOp1(); - if (addrSpillOp->IsLocal()) - { - // We will *not* consider this to define the local, but rather have each individual field assign - // be a definition. - addrSpillOp->gtFlags &= ~(GTF_LIVENESS_MASK); - addrSpillIsStackDest = true; // addrSpill represents the address of LclVar[varNum] in our - // local stack frame - } - } - if (addrSpill != nullptr) { // 'addrSpill' is already morphed @@ -1178,30 +1111,26 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() addrSpillDsc->lvType = TYP_BYREF; - if (addrSpillIsStackDest) + if (addrSpillSrcLclNum != BAD_VAR_NUM) { + // addrSpill represents the address of LclVar[varNum] in our local stack frame. addrSpillDsc->lvStackByref = true; } GenTreeLclVar* addrSpillNode = m_comp->gtNewLclvNode(addrSpillTemp, TYP_BYREF); addrSpillAsg = m_comp->gtNewAssignNode(addrSpillNode, addrSpill); - // If we are assigning the address of a LclVar here - // liveness does not account for this kind of address taken use. + // If we are assigning the address of a LclVar here liveness will not + // account for this kind of address taken use. Mark the local as + // address-exposed so that we don't do illegal optimizations with it. // - // We have to mark this local as address exposed so - // that we don't delete the definition for this LclVar - // as a dead store later on. + // TODO-CQ: usage of "addrSpill" for local addresses is a workaround + // for cases where we fail to use LCL_FLD nodes instead. Fix them and + // delete this code. // - if (addrSpill->OperGet() == GT_ADDR) + if (addrSpillSrcLclNum != BAD_VAR_NUM) { - GenTree* addrOp = addrSpill->AsOp()->gtOp1; - if (addrOp->IsLocal()) - { - unsigned lclVarNum = addrOp->AsLclVarCommon()->GetLclNum(); - m_comp->lvaGetDesc(lclVarNum)->SetAddressExposed(true DEBUGARG(AddressExposedReason::COPY_FLD_BY_FLD)); - m_comp->lvaSetVarDoNotEnregister(lclVarNum DEBUGARG(DoNotEnregisterReason::AddrExposed)); - } + m_comp->lvaSetVarAddrExposed(addrSpillSrcLclNum DEBUGARG(AddressExposedReason::COPY_FLD_BY_FLD)); } } @@ -1209,7 +1138,6 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() // So, beyond this point we cannot rely on the old values of 'm_srcVarDsc' and 'm_dstVarDsc'. for (unsigned i = 0; i < fieldCnt; ++i) { - GenTree* dstFld; if (m_dstDoFldAsg) { @@ -1278,7 +1206,7 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() // Is the address of a local? GenTreeLclVarCommon* lclVarTree = nullptr; bool isEntire = false; - bool* pIsEntire = (m_blockSizeIsConst ? &isEntire : nullptr); + bool* pIsEntire = &isEntire; if (dstAddrClone->DefinesLocalAddr(m_comp, m_blockSize, &lclVarTree, pIsEntire)) { lclVarTree->gtFlags |= GTF_VAR_DEF; @@ -1551,3 +1479,50 @@ GenTree* Compiler::fgMorphInitBlock(GenTree* tree) { return MorphInitBlockHelper::MorphInitBlock(this, tree); } + +//------------------------------------------------------------------------ +// fgMorphStoreDynBlock: Morph a dynamic block store (GT_STORE_DYN_BLK). +// +// Performs full (pre-order and post-order) morphing for a STORE_DYN_BLK. +// +// Arguments: +// tree - The GT_STORE_DYN_BLK tree to morph. +// +// Return Value: +// In case the size turns into a constant - the store, transformed +// into an "ordinary" ASG(BLK, Data()) one, and further morphed by +// "fgMorphInitBlock"/"fgMorphCopyBlock". Otherwise, the original +// tree (fully morphed). +// +GenTree* Compiler::fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree) +{ + tree->Addr() = fgMorphTree(tree->Addr()); + tree->Data() = fgMorphTree(tree->Data()); + tree->gtDynamicSize = fgMorphTree(tree->gtDynamicSize); + + if (tree->gtDynamicSize->IsIntegralConst()) + { + int64_t size = tree->gtDynamicSize->AsIntConCommon()->IntegralValue(); + assert(FitsIn(size)); + + if (size != 0) + { + GenTree* lhs = gtNewBlockVal(tree->Addr(), static_cast(size)); + lhs->SetIndirExceptionFlags(this); + + GenTree* asg = gtNewAssignNode(lhs, tree->Data()); + asg->gtFlags |= (tree->gtFlags & (GTF_ALL_EFFECT | GTF_BLK_VOLATILE | GTF_BLK_UNALIGNED)); + INDEBUG(asg->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + + JITDUMP("MorphStoreDynBlock: trasformed STORE_DYN_BLK into ASG(BLK, Data())\n"); + + return tree->OperIsCopyBlkOp() ? fgMorphCopyBlock(asg) : fgMorphInitBlock(asg); + } + } + + tree->SetAllEffectsFlags(tree->Addr(), tree->Data(), tree->gtDynamicSize); + tree->SetIndirExceptionFlags(this); + tree->gtFlags |= GTF_ASG; + + return tree; +} diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 25733a41a9c9e..68ea721ae4818 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -4,7 +4,10 @@ #ifndef _NAMEDINTRINSICLIST_H_ #define _NAMEDINTRINSICLIST_H_ -// Named jit intrinsics +// Named jit intrinsics. + +// When adding a new intrinsic that will use the GT_INTRINSIC node and can throw, make sure +// to update the "OperMayThrow" and "fgValueNumberAddExceptionSet" methods to account for that. enum NamedIntrinsic : unsigned short { @@ -78,6 +81,7 @@ enum NamedIntrinsic : unsigned short NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan, NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray, + NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant, NI_System_String_get_Chars, NI_System_String_get_Length, diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index f16fb917a589d..108fde7e98497 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -829,7 +829,8 @@ bool Compiler::optValnumCSE_Locate() continue; } - if (ValueNumStore::isReservedVN(tree->GetVN(VNK_Liberal))) + ValueNum valueVN = vnStore->VNNormalValue(tree->GetVN(VNK_Liberal)); + if (ValueNumStore::isReservedVN(valueVN) && (valueVN != ValueNumStore::VNForNull())) { continue; } @@ -2598,17 +2599,18 @@ class CSE_Heuristic cse_use_cost *= slotCount; } - // If this CSE is live across a call then we may need to spill an additional caller save register + // If this CSE is live across a call then we may have additional costs // if (candidate->LiveAcrossCall()) { - if (candidate->Expr()->IsCnsFltOrDbl() && (CNT_CALLEE_SAVED_FLOAT == 0) && - (candidate->CseDsc()->csdUseWtCnt <= 4)) + // If we have a floating-point CSE that is both live across a call and there + // are no callee-saved FP registers available, the RA will have to spill at + // the def site and reload at the (first) use site, if the variable is a register + // candidate. Account for that. + if (varTypeIsFloating(candidate->Expr()) && (CNT_CALLEE_SAVED_FLOAT == 0) && !candidate->IsConservative()) { - // Floating point constants are expected to be contained, so unless there are more than 4 uses - // we better not to CSE them, especially on platforms without callee-saved registers - // for values living across calls - return false; + cse_def_cost += 1; + cse_use_cost += 1; } // If we don't have a lot of variables to enregister or we have a floating point type diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 2d3aedc94ba0a..dd2f3a8246ede 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -302,7 +302,7 @@ void Compiler::optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk) } // We only consider back-edges that are BBJ_COND or BBJ_ALWAYS for loops. - if ((predBlock->bbJumpKind != BBJ_COND) && (predBlock->bbJumpKind != BBJ_ALWAYS)) + if (!predBlock->KindIs(BBJ_COND, BBJ_ALWAYS)) { continue; } @@ -402,16 +402,14 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar bool removeLoop = false; - /* If an unreachable block was part of a loop entry or bottom then the loop is unreachable */ - /* Special case: the block was the head of a loop - or pointing to a loop entry */ + // If an unreachable block is a loop entry or bottom then the loop is unreachable. + // Special case: the block was the head of a loop - or pointing to a loop entry. for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++) { LoopDsc& loop = optLoopTable[loopNum]; - /* Some loops may have been already removed by - * loop unrolling or conditional folding */ - + // Some loops may have been already removed by loop unrolling or conditional folding. if (loop.lpFlags & LPFLG_REMOVED) { continue; @@ -454,11 +452,9 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar continue; } - /* If the loop is still in the table - * any block in the loop must be reachable !!! */ + // If the loop is still in the table any block in the loop must be reachable. - noway_assert(loop.lpEntry != block); - noway_assert(loop.lpBottom != block); + noway_assert((loop.lpEntry != block) && (loop.lpBottom != block)); if (loop.lpExit == block) { @@ -468,27 +464,26 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar loop.lpExit = nullptr; } - /* If this points to the actual entry in the loop - * then the whole loop may become unreachable */ + // If `block` flows to the loop entry then the whole loop will become unreachable if it is the + // only non-loop predecessor. switch (block->bbJumpKind) { case BBJ_NONE: - case BBJ_COND: if (block->bbNext == loop.lpEntry) { removeLoop = true; - break; } - if (block->bbJumpKind == BBJ_NONE) + break; + + case BBJ_COND: + if ((block->bbNext == loop.lpEntry) || (block->bbJumpDest == loop.lpEntry)) { - break; + removeLoop = true; } - - FALLTHROUGH; + break; case BBJ_ALWAYS: - noway_assert(block->bbJumpDest); if (block->bbJumpDest == loop.lpEntry) { removeLoop = true; @@ -512,13 +507,12 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar if (removeLoop) { - /* Check if the entry has other predecessors outside the loop - * TODO: Replace this when predecessors are available */ + // Check if the entry has other predecessors outside the loop. + // TODO: Replace this when predecessors are available. for (BasicBlock* const auxBlock : Blocks()) { - /* Ignore blocks in the loop */ - + // Ignore blocks in the loop. if (loop.lpContains(auxBlock)) { continue; @@ -527,21 +521,20 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar switch (auxBlock->bbJumpKind) { case BBJ_NONE: - case BBJ_COND: if (auxBlock->bbNext == loop.lpEntry) { removeLoop = false; - break; } - if (auxBlock->bbJumpKind == BBJ_NONE) + break; + + case BBJ_COND: + if ((auxBlock->bbNext == loop.lpEntry) || (auxBlock->bbJumpDest == loop.lpEntry)) { - break; + removeLoop = false; } - - FALLTHROUGH; + break; case BBJ_ALWAYS: - noway_assert(auxBlock->bbJumpDest); if (auxBlock->bbJumpDest == loop.lpEntry) { removeLoop = false; @@ -580,18 +573,39 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar reportAfter(); } - if ((skipUnmarkLoop == false) && // - ((block->bbJumpKind == BBJ_ALWAYS) || (block->bbJumpKind == BBJ_COND)) && // - block->bbJumpDest->isLoopHead() && // - (block->bbJumpDest->bbNum <= block->bbNum) && // - fgDomsComputed && // - (fgCurBBEpochSize == fgDomBBcount + 1) && // + if ((skipUnmarkLoop == false) && // + block->KindIs(BBJ_ALWAYS, BBJ_COND) && // + block->bbJumpDest->isLoopHead() && // + (block->bbJumpDest->bbNum <= block->bbNum) && // + fgDomsComputed && // + (fgCurBBEpochSize == fgDomBBcount + 1) && // fgReachable(block->bbJumpDest, block)) { optUnmarkLoopBlocks(block->bbJumpDest, block); } } +//------------------------------------------------------------------------ +// optClearLoopIterInfo: Clear the info related to LPFLG_ITER loops in the loop table. +// The various fields related to iterators is known to be valid for loop cloning and unrolling, +// but becomes invalid afterwards. Clear the info that might be used incorrectly afterwards +// in JitDump or by subsequent phases. +// +void Compiler::optClearLoopIterInfo() +{ + for (unsigned lnum = 0; lnum < optLoopCount; lnum++) + { + LoopDsc& loop = optLoopTable[lnum]; + loop.lpFlags &= ~(LPFLG_ITER | LPFLG_VAR_INIT | LPFLG_CONST_INIT | LPFLG_SIMD_LIMIT | LPFLG_VAR_LIMIT | + LPFLG_CONST_LIMIT | LPFLG_ARRLEN_LIMIT); + + loop.lpIterTree = nullptr; + loop.lpInitBlock = nullptr; + loop.lpConstInit = -1; // union with loop.lpVarInit + loop.lpTestTree = nullptr; + } +} + #ifdef DEBUG /***************************************************************************** @@ -1685,9 +1699,7 @@ class LoopSearch return false; } - if ((bottom->bbJumpKind == BBJ_EHFINALLYRET) || (bottom->bbJumpKind == BBJ_EHFILTERRET) || - (bottom->bbJumpKind == BBJ_EHCATCHRET) || (bottom->bbJumpKind == BBJ_CALLFINALLY) || - (bottom->bbJumpKind == BBJ_SWITCH)) + if (bottom->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, BBJ_CALLFINALLY, BBJ_SWITCH)) { // 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. @@ -1829,7 +1841,7 @@ class LoopSearch } } // Can we fall through into the loop? - else if (head->bbJumpKind == BBJ_NONE || head->bbJumpKind == BBJ_COND) + else if (head->KindIs(BBJ_NONE, BBJ_COND)) { // The ENTRY is at the TOP (a do-while loop) return top; @@ -2139,7 +2151,7 @@ class LoopSearch return nullptr; } - if ((newMoveAfter->bbJumpKind == BBJ_ALWAYS) || (newMoveAfter->bbJumpKind == BBJ_COND)) + if (newMoveAfter->KindIs(BBJ_ALWAYS, BBJ_COND)) { unsigned int destNum = newMoveAfter->bbJumpDest->bbNum; if ((destNum >= top->bbNum) && (destNum <= bottom->bbNum) && !loopBlocks.IsMember(destNum)) @@ -2329,8 +2341,8 @@ class LoopSearch } // Make sure we don't leave around a goto-next unless it's marked KEEP_BBJ_ALWAYS. - assert(((block->bbJumpKind != BBJ_COND) && (block->bbJumpKind != BBJ_ALWAYS)) || - (block->bbJumpDest != newNext) || ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)); + assert(!block->KindIs(BBJ_COND, BBJ_ALWAYS) || (block->bbJumpDest != newNext) || + ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)); return newBlock; } @@ -7574,6 +7586,8 @@ void Compiler::fgCreateLoopPreHeader(unsigned lnum) fgAddRefPred(preHead, predBlock); } } while (++jumpTab, --jumpCnt); + + UpdateSwitchTableTarget(predBlock, entry, preHead); break; default: @@ -7850,24 +7864,16 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk) } else { - // We are only interested in IsFieldAddr()'s fldSeq out parameter. - // - GenTree* obj = nullptr; // unused - GenTree* staticOffset = nullptr; // unused - FieldSeqNode* fldSeq = nullptr; - - if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq) && - (fldSeq != FieldSeqStore::NotAField())) + GenTree* baseAddr = nullptr; + FieldSeqNode* fldSeq = nullptr; + if (arg->IsFieldAddr(this, &baseAddr, &fldSeq)) { - // Get the first (object) field from field seq. GcHeap[field] will yield the "field map". - assert(fldSeq != nullptr); - if (fldSeq->IsFirstElemFieldSeq()) - { - fldSeq = fldSeq->m_next; - assert(fldSeq != nullptr); - } + assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) && + !fldSeq->IsPseudoField()); - AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->m_fieldHnd); + FieldKindForVN fieldKind = + (baseAddr != nullptr) ? FieldKindForVN::WithBaseAddr : FieldKindForVN::SimpleStatic; + AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->GetFieldHandle(), fieldKind); // Conservatively assume byrefs may alias this object. memoryHavoc |= memoryKindSet(ByrefExposed); } @@ -7893,7 +7899,8 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk) } else if (lhs->OperGet() == GT_CLS_VAR) { - AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->AsClsVar()->gtClsVarHnd); + AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->AsClsVar()->gtClsVarHnd, + FieldKindForVN::SimpleStatic); // Conservatively assume byrefs may alias this static field memoryHavoc |= memoryKindSet(ByrefExposed); } @@ -7972,6 +7979,7 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk) case GT_XCHG: case GT_CMPXCHG: case GT_MEMORYBARRIER: + case GT_STORE_DYN_BLK: { memoryHavoc |= memoryKindSet(GcHeap, ByrefExposed); } @@ -8073,12 +8081,12 @@ void Compiler::AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock* } // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops. -void Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd) +void Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind) { assert(0 <= lnum && lnum < optLoopCount); while (lnum != BasicBlock::NOT_IN_LOOP) { - optLoopTable[lnum].AddModifiedField(this, fldHnd); + optLoopTable[lnum].AddModifiedField(this, fldHnd, fieldKind); lnum = optLoopTable[lnum].lpParent; } } diff --git a/src/coreclr/jit/phase.cpp b/src/coreclr/jit/phase.cpp index f08134bf11532..5f2e2172c6f4a 100644 --- a/src/coreclr/jit/phase.cpp +++ b/src/coreclr/jit/phase.cpp @@ -141,6 +141,8 @@ void Phase::PrePhase() // void Phase::PostPhase(PhaseStatus status) { + comp->EndPhase(m_phase); + #ifdef DEBUG // Don't dump or check post phase unless the phase made changes. @@ -162,16 +164,33 @@ void Phase::PostPhase(PhaseStatus status) // well as the new-style phases that have been updated to return // PhaseStatus from their DoPhase methods. // - static Phases s_allowlist[] = {PHASE_IMPORTATION, PHASE_IBCINSTR, - PHASE_IBCPREP, PHASE_INCPROFILE, - PHASE_INDXCALL, PHASE_MORPH_INLINE, - PHASE_ALLOCATE_OBJECTS, PHASE_EMPTY_TRY, - PHASE_EMPTY_FINALLY, PHASE_MERGE_FINALLY_CHAINS, - PHASE_CLONE_FINALLY, PHASE_MERGE_THROWS, - PHASE_MORPH_GLOBAL, PHASE_INVERT_LOOPS, - PHASE_OPTIMIZE_LAYOUT, PHASE_FIND_LOOPS, - PHASE_BUILD_SSA, PHASE_RATIONALIZE, - PHASE_LOWERING, PHASE_STACK_LEVEL_SETTER}; + // clang-format off + + static Phases s_allowlist[] = { + PHASE_INCPROFILE, + PHASE_IBCPREP, + PHASE_IMPORTATION, + PHASE_PATCHPOINTS, + PHASE_IBCINSTR, + PHASE_INDXCALL, + PHASE_MORPH_INLINE, + PHASE_ALLOCATE_OBJECTS, + PHASE_EMPTY_TRY, + PHASE_EMPTY_FINALLY, + PHASE_MERGE_FINALLY_CHAINS, + PHASE_CLONE_FINALLY, + PHASE_MERGE_THROWS, + PHASE_MORPH_GLOBAL, + PHASE_INVERT_LOOPS, + PHASE_OPTIMIZE_LAYOUT, + PHASE_FIND_LOOPS, + PHASE_BUILD_SSA, + PHASE_INSERT_GC_POLLS, + PHASE_RATIONALIZE, + PHASE_LOWERING, + PHASE_STACK_LEVEL_SETTER}; + + // clang-format on if (madeChanges) { @@ -234,6 +253,4 @@ void Phase::PostPhase(PhaseStatus status) #if DUMP_FLOWGRAPHS comp->fgDumpFlowGraph(m_phase, Compiler::PhasePosition::PostPhase); #endif // DUMP_FLOWGRAPHS - - comp->EndPhase(m_phase); } diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 4a475806148b7..56ad0323fd6de 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -869,7 +869,7 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE JITDUMP("Merge assertions from pred " FMT_BB " edge: ", pred->bbNum); Compiler::optDumpAssertionIndices(assertions, "\n"); } - else if ((pred->bbJumpKind == BBJ_COND || pred->bbJumpKind == BBJ_ALWAYS) && pred->bbJumpDest == block) + else if (pred->KindIs(BBJ_COND, BBJ_ALWAYS) && (pred->bbJumpDest == block)) { if (m_pCompiler->bbJtrueAssertionOut != nullptr) { diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index 5e54ca8bd94d4..72c1591c6d425 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -416,13 +416,10 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) } GenTreeSIMD* simdTree = comp->gtNewSIMDNode(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType)); - assignment->AsOp()->gtOp2 = simdTree; - value = simdTree; - initVal->gtNext = simdTree; - simdTree->gtPrev = initVal; + assignment->gtOp2 = simdTree; + value = simdTree; - simdTree->gtNext = location; - location->gtPrev = simdTree; + BlockRange().InsertAfter(initVal, simdTree); } } #endif // FEATURE_SIMD @@ -468,7 +465,6 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: { assert(varTypeIsStruct(location)); GenTreeBlk* storeBlk = location->AsBlk(); @@ -481,9 +477,6 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) case GT_OBJ: storeOper = GT_STORE_OBJ; break; - case GT_DYN_BLK: - storeOper = GT_STORE_DYN_BLK; - break; default: unreached(); } diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index 4646769263d37..48fe4d84d9aec 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -732,7 +732,7 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block) // This is perhaps temporary -- maybe should be done elsewhere. Label GT_INDs on LHS of assignments, so we // can skip these during (at least) value numbering. GenTree* lhs = asgNode->gtGetOp1()->gtEffectiveVal(/*commaOnly*/ true); - if (lhs->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK)) + if (lhs->OperIs(GT_IND, GT_OBJ, GT_BLK)) { lhs->gtFlags |= GTF_IND_ASG_LHS; } diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index cdab21582ffce..4cc6b63f73009 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -11,8 +11,10 @@ #define ROUND_FLOAT 0 // Do not round intermed float expression results #define CPU_HAS_BYTE_REGS 0 - #define CPBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll CpBlk. - #define INITBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll InitBlk. + #define CPBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll CpBlk + #define CPBLK_LCL_UNROLL_LIMIT 128 // Upper bound to let the code generator to loop unroll CpBlk (when both srcAddr and dstAddr point to the stack) + #define INITBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll InitBlk + #define INITBLK_LCL_UNROLL_LIMIT 128 // Upper bound to let the code generator to loop unroll InitBlk (when dstAddr points to the stack) #ifdef FEATURE_SIMD #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned diff --git a/src/coreclr/jit/typeinfo.cpp b/src/coreclr/jit/typeinfo.cpp index 07809e57268a2..6bc69965d097b 100644 --- a/src/coreclr/jit/typeinfo.cpp +++ b/src/coreclr/jit/typeinfo.cpp @@ -20,32 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX bool Compiler::tiCompatibleWith(const typeInfo& child, const typeInfo& parent, bool normalisedForStack) const { -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("Verifying compatibility against types: "); - child.Dump(); - printf(" and "); - parent.Dump(); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - bool compatible = typeInfo::tiCompatibleWith(info.compCompHnd, child, parent, normalisedForStack); - -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf(compatible ? " [YES]" : " [NO]"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - return compatible; + return typeInfo::tiCompatibleWith(info.compCompHnd, child, parent, normalisedForStack); } bool Compiler::tiMergeCompatibleWith(const typeInfo& child, const typeInfo& parent, bool normalisedForStack) const @@ -55,41 +30,7 @@ bool Compiler::tiMergeCompatibleWith(const typeInfo& child, const typeInfo& pare bool Compiler::tiMergeToCommonParent(typeInfo* pDest, const typeInfo* pSrc, bool* changed) const { -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("Attempting to merge types: "); - pDest->Dump(); - printf(" and "); - pSrc->Dump(); - printf("\n"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - bool mergeable = typeInfo::tiMergeToCommonParent(info.compCompHnd, pDest, pSrc, changed); - -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf(TI_DUMP_PADDING); - printf(mergeable ? "Merge successful" : "Couldn't merge types"); - if (*changed) - { - assert(mergeable); - printf(", destination type changed to: "); - pDest->Dump(); - } - printf("\n"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - return mergeable; + return typeInfo::tiMergeToCommonParent(info.compCompHnd, pDest, pSrc, changed); } static bool tiCompatibleWithByRef(COMP_HANDLE CompHnd, const typeInfo& child, const typeInfo& parent) diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 1c4341e147009..947f774fbdac0 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -1266,6 +1266,17 @@ bool ValueNumStore::VNExcIsSubset(ValueNum vnFullSet, ValueNum vnCandidateSet) } } +//---------------------------------------------------------------------------------------- +// VNPExcIsSubset - Given two exception sets, returns true when both the liberal and +// conservative value numbers of vnpCandidateSet represent subsets of +// the corresponding numbers in vnpFullSet (see VNExcIsSubset). +// +bool ValueNumStore::VNPExcIsSubset(ValueNumPair vnpFullSet, ValueNumPair vnpCandidateSet) +{ + return VNExcIsSubset(vnpFullSet.GetLiberal(), vnpCandidateSet.GetLiberal()) && + VNExcIsSubset(vnpFullSet.GetConservative(), vnpCandidateSet.GetConservative()); +} + //------------------------------------------------------------------------------------- // VNUnpackExc: - Given a ValueNum 'vnWx, return via write back parameters both // the normal and the exception set components. @@ -1423,6 +1434,64 @@ ValueNumPair ValueNumStore::VNPMakeNormalUniquePair(ValueNumPair vnp) return ValueNumPair(VNMakeNormalUnique(vnp.GetLiberal()), VNMakeNormalUnique(vnp.GetConservative())); } +//------------------------------------------------------------------------------------ +// VNUniqueWithExc: +// +// Arguments: +// type - The type for the unique Value Number +// vnExcSet - The Value Number for the exception set. +// +// Return Value: +// - VN representing a "new, unique" value, with +// the exceptions contained in "vnExcSet". +// +ValueNum ValueNumStore::VNUniqueWithExc(var_types type, ValueNum vnExcSet) +{ + ValueNum normVN = VNForExpr(m_pComp->compCurBB, type); + + if (vnExcSet == VNForEmptyExcSet()) + { + return normVN; + } + +#ifdef DEBUG + VNFuncApp excSetFunc; + assert(GetVNFunc(vnExcSet, &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons)); +#endif // DEBUG + + return VNWithExc(normVN, vnExcSet); +} + +//------------------------------------------------------------------------------------ +// VNPUniqueWithExc: +// +// Arguments: +// type - The type for the unique Value Numbers +// vnExcSet - The Value Number Pair for the exception set. +// +// Return Value: +// - VN Pair representing a "new, unique" value (liberal and conservative +// values will be equal), with the exceptions contained in "vnpExcSet". +// +// Notes: - We use the same unique value number both for liberal and conservative +// portions of the pair to save memory (it would not be useful to make +// them different). +// +ValueNumPair ValueNumStore::VNPUniqueWithExc(var_types type, ValueNumPair vnpExcSet) +{ +#ifdef DEBUG + VNFuncApp excSetFunc; + assert((GetVNFunc(vnpExcSet.GetLiberal(), &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons)) || + (vnpExcSet.GetLiberal() == VNForEmptyExcSet())); + assert((GetVNFunc(vnpExcSet.GetConservative(), &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons)) || + (vnpExcSet.GetConservative() == VNForEmptyExcSet())); +#endif // DEBUG + + ValueNum normVN = VNForExpr(m_pComp->compCurBB, type); + + return VNPWithExc(ValueNumPair(normVN, normVN), vnpExcSet); +} + //-------------------------------------------------------------------------------- // VNNormalValue: - Returns a Value Number that represents the result for the // normal (non-exceptional) evaluation for the expression. @@ -4338,21 +4407,21 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq, return vnStore->VNForMapStore(fgCurMemoryVN[GcHeap], elemTypeEqVN, newValAtArrType); } -ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* pFuncApp, ValueNum addrXvn) +ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* pFuncApp, ValueNumPair addrXvnp) { assert(vnStore->IsVNHandle(pFuncApp->m_args[0])); CORINFO_CLASS_HANDLE arrElemTypeEQ = CORINFO_CLASS_HANDLE(vnStore->ConstantValue(pFuncApp->m_args[0])); ValueNum arrVN = pFuncApp->m_args[1]; ValueNum inxVN = pFuncApp->m_args[2]; FieldSeqNode* fldSeq = vnStore->FieldSeqVNToFieldSeq(pFuncApp->m_args[3]); - return fgValueNumberArrIndexVal(tree, arrElemTypeEQ, arrVN, inxVN, addrXvn, fldSeq); + return fgValueNumberArrIndexVal(tree, arrElemTypeEQ, arrVN, inxVN, addrXvnp, fldSeq); } ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, CORINFO_CLASS_HANDLE elemTypeEq, ValueNum arrVN, ValueNum inxVN, - ValueNum excVN, + ValueNumPair addrXvnp, FieldSeqNode* fldSeq) { assert(tree == nullptr || tree->OperIsIndir()); @@ -4372,7 +4441,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, JITDUMP(" *** Not a proper arrray access encountered in fgValueNumberArrIndexVal\n"); // a new unique value number - selectedElem = vnStore->VNForExpr(compCurBB, elemTyp); + selectedElem = vnStore->VNForExpr(compCurBB, indType); #ifdef DEBUG if (verbose) @@ -4383,7 +4452,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, if (tree != nullptr) { - tree->gtVNPair.SetBoth(selectedElem); + tree->gtVNPair = vnStore->VNPWithExc(ValueNumPair(selectedElem, selectedElem), addrXvnp); } } else @@ -4422,7 +4491,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, elemTyp = vnStore->TypeOfVN(selectedElem); } selectedElem = vnStore->VNApplySelectorsTypeCheck(selectedElem, indType, elemStructSize); - selectedElem = vnStore->VNWithExc(selectedElem, excVN); + selectedElem = vnStore->VNWithExc(selectedElem, addrXvnp.GetLiberal()); #ifdef DEBUG if (verbose && (selectedElem != wholeElem)) @@ -4434,10 +4503,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, if (tree != nullptr) { tree->gtVNPair.SetLiberal(selectedElem); - - // TODO-CQ: what to do here about exceptions? We don't have the array and ind conservative - // values, so we don't have their exceptions. Maybe we should. - tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet())); + tree->gtVNPair.SetConservative(vnStore->VNUniqueWithExc(tree->TypeGet(), addrXvnp.GetConservative())); } } @@ -5952,8 +6018,7 @@ void ValueNumStore::vnDumpValWithExc(Compiler* comp, VNFuncApp* valWithExc) GetVNFunc(excVN, &excSeq); printf("norm="); - printf(FMT_VN, normVN); - vnDump(comp, normVN); + comp->vnPrint(normVN, 1); printf(", exc="); printf(FMT_VN, excVN); vnDumpExcSeq(comp, &excSeq, true); @@ -6143,7 +6208,7 @@ void ValueNumStore::vnDumpZeroObj(Compiler* comp, VNFuncApp* zeroObj) static UINT8 vnfOpAttribs[VNF_COUNT]; static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memory. GT_NULLCHECK, GT_QMARK, GT_COLON, GT_LOCKADD, GT_XADD, GT_XCHG, - GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, + GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_DYN_BLK, // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). @@ -6793,6 +6858,7 @@ void Compiler::fgValueNumber() #ifdef DEBUG JitTestCheckVN(); + fgDebugCheckExceptionSets(); #endif // DEBUG fgVNPassesCompleted++; @@ -6812,10 +6878,11 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk) assert(asg->OperIs(GT_ASG)); GenTreeLclVar* newSsaDef = asg->AsOp()->gtGetOp1()->AsLclVar(); + GenTreePhi* phiNode = asg->AsOp()->gtGetOp2()->AsPhi(); ValueNumPair phiVNP; ValueNumPair sameVNP; - for (GenTreePhi::Use& use : asg->AsOp()->gtGetOp2()->AsPhi()->Uses()) + for (GenTreePhi::Use& use : phiNode->Uses()) { GenTreePhiArg* phiArg = use.GetNode()->AsPhiArg(); ValueNum phiArgSsaNumVN = vnStore->VNForIntCon(phiArg->GetSsaNum()); @@ -6880,6 +6947,10 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk) printf(" %s.\n", sameVNP.BothDefined() ? "(all same)" : ""); } #endif // DEBUG + + newSsaDef->gtVNPair = vnStore->VNPForVoid(); + phiNode->gtVNPair = newSsaDefVNP; + asg->gtVNPair = vnStore->VNPForVoid(); } // Now do the same for each MemoryKind. @@ -7128,8 +7199,9 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind, for (Compiler::LoopDsc::FieldHandleSet::KeyIterator ki = fieldsMod->Begin(); !ki.Equal(fieldsMod->End()); ++ki) { - CORINFO_FIELD_HANDLE fldHnd = ki.Get(); - ValueNum fldHndVN = vnStore->VNForHandle(ssize_t(fldHnd), GTF_ICON_FIELD_HDL); + CORINFO_FIELD_HANDLE fldHnd = ki.Get(); + FieldKindForVN fieldKind = ki.GetValue(); + ValueNum fldHndVN = vnStore->VNForHandle(ssize_t(fldHnd), GTF_ICON_FIELD_HDL); #ifdef DEBUG if (verbose) @@ -7140,9 +7212,9 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind, } #endif // DEBUG - // Instance field maps get a placeholder type - they do not represent "singular" - // values. Static field maps, on the other hand, do, and so must be given proper types. - var_types fldMapType = eeIsFieldStatic(fldHnd) ? eeGetFieldType(fldHnd) : TYP_MEM; + // Instance fields and "complex" statics select "first field maps" + // with a placeholder type. "Simple" statics select their own types. + var_types fldMapType = (fieldKind == FieldKindForVN::WithBaseAddr) ? TYP_MEM : eeGetFieldType(fldHnd); newMemoryVN = vnStore->VNForMapStore(newMemoryVN, fldHndVN, vnStore->VNForExpr(entryBlock, fldMapType)); } @@ -7464,13 +7536,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) } // We have to handle the case where the LHS is a comma. In that case, we don't evaluate the comma, - // so we give it VNForVoid, and we're really interested in the effective value. - GenTree* lhsCommaIter = lhs; - while (lhsCommaIter->OperGet() == GT_COMMA) - { - lhsCommaIter->gtVNPair.SetBoth(vnStore->VNForVoid()); - lhsCommaIter = lhsCommaIter->AsOp()->gtOp2; - } + // and we're really just interested in the effective value. lhs = lhs->gtEffectiveVal(); // Now, record the new VN for an assignment (performing the indicated "state update"). @@ -7627,8 +7693,6 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) // Indicates whether the argument of the IND is the address of a local. bool wasLocal = false; - lhs->gtVNPair = rhsVNPair; - VNFuncApp funcApp; ValueNum argVN = arg->gtVNPair.GetLiberal(); @@ -7735,9 +7799,8 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) // Was the argument of the GT_IND the address of a local, handled above? if (!wasLocal) { - GenTree* obj = nullptr; - GenTree* staticOffset = nullptr; - FieldSeqNode* fldSeq = nullptr; + GenTree* baseAddr = nullptr; + FieldSeqNode* fldSeq = nullptr; // Is the LHS an array index expression? if (argIsVNFunc && funcApp.m_func == VNF_PtrToArrElem) @@ -7796,7 +7859,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) rhsVNPair.GetLiberal(), lhs->TypeGet()); recordGcHeapStore(tree, heapVN DEBUGARG("ArrIndexAssign (case 2)")); } - else if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq)) + else if (arg->IsFieldAddr(this, &baseAddr, &fldSeq)) { assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) && !fldSeq->IsPseudoField()); @@ -7807,11 +7870,10 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) // We will check that the final field in the sequence matches 'indType'. var_types indType = lhs->TypeGet(); - // when (obj != nullptr) we have an instance field, otherwise a static field - // when (staticOffset != nullptr) it represents a offset into a static or the call to - // Shared Static Base - if ((obj != nullptr) || (staticOffset != nullptr)) + if (baseAddr != nullptr) { + // Instance field / "complex" static: heap[field][baseAddr][struct fields...] = storeVal. + var_types firstFieldType; ValueNum firstFieldSelectorVN = vnStore->VNForFieldSelector(fldSeq->GetFieldHandle(), &firstFieldType); @@ -7821,15 +7883,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) ValueNum fldMapVN = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN); - ValueNum firstFieldValueSelectorVN = ValueNumStore::NoVN; - if (obj != nullptr) - { - firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(obj->gtVNPair); - } - else // (staticOffset != nullptr) - { - firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(staticOffset->gtVNPair); - } + ValueNum firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(baseAddr->gtVNPair); ValueNum newFirstFieldValueVN = ValueNumStore::NoVN; // Optimization: avoid traversting the maps for the value of the first field if @@ -7840,12 +7894,12 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) } else { - // Construct the ValueNumber for fldMap[obj/offset]. This (struct) + // Construct the ValueNumber for fldMap[baseAddr]. This (struct) // map represents the specific field we're looking to store to. ValueNum firstFieldValueVN = vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN, firstFieldValueSelectorVN); - // Construct the maps updating the rest of the fields in the sequence. + // Construct the maps updating the struct fields in the sequence. newFirstFieldValueVN = vnStore->VNApplySelectorsAssign(VNK_Liberal, firstFieldValueVN, fldSeq->m_next, storeVal, indType); } @@ -7859,15 +7913,11 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) } else { - // Plain static field. + // "Simple" static: heap[field][struct fields...] = storeVal. newHeapVN = vnStore->VNApplySelectorsAssign(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq, storeVal, indType); } - // It is not strictly necessary to set the lhs value number, - // but the dumps read better with it set to the 'storeVal' that we just computed - lhs->gtVNPair.SetBoth(storeVal); - // Update the GcHeap value. recordGcHeapStore(tree, newHeapVN DEBUGARG("StoreField")); } @@ -8165,7 +8215,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) else if (srcAddrFuncApp.m_func == VNF_PtrToArrElem) { ValueNum elemLib = - fgValueNumberArrIndexVal(nullptr, &srcAddrFuncApp, vnStore->VNForEmptyExcSet()); + fgValueNumberArrIndexVal(nullptr, &srcAddrFuncApp, vnStore->VNPForEmptyExcSet()); rhsVNPair.SetLiberal(elemLib); rhsVNPair.SetConservative(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet())); } @@ -8321,43 +8371,8 @@ bool Compiler::fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLcl void Compiler::fgValueNumberTree(GenTree* tree) { genTreeOps oper = tree->OperGet(); + var_types typ = tree->TypeGet(); -#ifdef FEATURE_SIMD - if ((JitConfig.JitDisableSimdVN() & 1) == 1) - { - // This Jit Config forces the previous behavior of value numbering for SIMD nodes - if (oper == GT_SIMD) - { - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_UNKNOWN)); - return; - } - } -#endif // FEATURE_SIMD - -#ifdef FEATURE_HW_INTRINSICS - if ((JitConfig.JitDisableSimdVN() & 2) == 2) - { - // This Jit Config forces the previous behavior of value numbering for HW Intrinsic nodes - if (oper == GT_HWINTRINSIC) - { - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_UNKNOWN)); - - GenTreeHWIntrinsic* hwIntrinsicNode = tree->AsHWIntrinsic(); - assert(hwIntrinsicNode != nullptr); - - // For safety/correctness we must mutate the global heap valuenumber - // for any HW intrinsic that performs a memory store operation - if (hwIntrinsicNode->OperIsMemoryStore()) - { - fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore")); - } - - return; - } - } -#endif // FEATURE_HW_INTRINSICS - - var_types typ = tree->TypeGet(); if (GenTree::OperIsConst(oper)) { // If this is a struct assignment, with a constant rhs, (i,.e. an initBlk), @@ -8514,19 +8529,18 @@ void Compiler::fgValueNumberTree(GenTree* tree) { // We have a Def (write) of the LclVar - // TODO-Review: For the short term, we have a workaround for copyblk/initblk. Those that use - // addrSpillTemp will have a statement like "addrSpillTemp = addr(local)." If we previously decided - // that this block operation defines the local, we will have labeled the "local" node as a DEF - // This flag propagates to the "local" on the RHS. So we'll assume that this is correct, - // and treat it as a def (to a new, unique VN). - // + // The below block ensures we give VNs to the fields of + // "CanBeReplacedWithItsField" struct locals. To the numbering + // of block assignments, those appear as untracked locals, but + // we need to give the SSA defs they represent a VN. if (lcl->GetSsaNum() != SsaConfig::RESERVED_SSA_NUM) { ValueNum uniqVN = vnStore->VNForExpr(compCurBB, lcl->TypeGet()); varDsc->GetPerSsaData(lcl->GetSsaNum())->m_vnPair.SetBoth(uniqVN); } - lcl->gtVNPair = ValueNumPair(); // Avoid confusion -- we don't set the VN of a lcl being defined. + // Location nodes get VNForVoid (no exceptions needed). + lcl->gtVNPair = vnStore->VNPForVoid(); } } break; @@ -8568,6 +8582,11 @@ void Compiler::fgValueNumberTree(GenTree* tree) tree->gtVNPair = vnStore->VNPairApplySelectors(lclVNPair, lclFld->GetFieldSeq(), indType); } } + else + { + // A location node (LHS). + lclFld->gtVNPair = vnStore->VNPForVoid(); + } } break; @@ -8652,6 +8671,11 @@ void Compiler::fgValueNumberTree(GenTree* tree) } tree->gtVNPair = clsVarVNPair; } + else + { + // Location nodes get the "Void" VN. + tree->gtVNPair = vnStore->VNPForVoid(); + } break; case GT_MEMORYBARRIER: // Leaf @@ -8731,38 +8755,42 @@ void Compiler::fgValueNumberTree(GenTree* tree) // Usually the ADDR and IND just cancel out... // except when this GT_ADDR has a valid zero-offset field sequence // + + ValueNumPair addrVNP = ValueNumPair(); FieldSeqNode* zeroOffsetFieldSeq = nullptr; if (GetZeroOffsetFieldMap()->Lookup(tree, &zeroOffsetFieldSeq) && (zeroOffsetFieldSeq != FieldSeqStore::NotAField())) { - ValueNum addrExtended = vnStore->ExtendPtrVN(arg->AsOp()->gtOp1, zeroOffsetFieldSeq); + ValueNum addrExtended = vnStore->ExtendPtrVN(arg->AsIndir()->Addr(), zeroOffsetFieldSeq); if (addrExtended != ValueNumStore::NoVN) { - tree->gtVNPair.SetBoth(addrExtended); // We don't care about lib/cons differences for addresses. + // We don't care about lib/cons differences for addresses. + addrVNP.SetBoth(addrExtended); } else { - // ExtendPtrVN returned a failure result - // So give this address a new unique value - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); + // ExtendPtrVN returned a failure result - give this address a new unique value. + addrVNP.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); } } else { // They just cancel, so fetch the ValueNumber from the op1 of the GT_IND node. // - GenTree* addr = arg->AsIndir()->Addr(); - tree->gtVNPair = addr->gtVNPair; + GenTree* addr = arg->AsIndir()->Addr(); + addrVNP = addr->gtVNPair; // For the CSE phase mark the address as GTF_DONT_CSE // because it will end up with the same value number as tree (the GT_ADDR). addr->gtFlags |= GTF_DONT_CSE; } + + tree->gtVNPair = vnStore->VNPWithExc(addrVNP, vnStore->VNPExceptionSet(arg->gtVNPair)); } else { // May be more cases to do here! But we'll punt for now. - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); + tree->gtVNPair = vnStore->VNPUniqueWithExc(TYP_BYREF, vnStore->VNPExceptionSet(arg->gtVNPair)); } } else if ((oper == GT_IND) || GenTree::OperIsBlk(oper)) @@ -8771,12 +8799,11 @@ void Compiler::fgValueNumberTree(GenTree* tree) // a pointer to an object field or array element. Other cases become uses of // the current ByrefExposed value and the pointer value, so that at least we // can recognize redundant loads with no stores between them. - GenTree* addr = tree->AsIndir()->Addr(); - GenTreeLclVarCommon* lclVarTree = nullptr; - FieldSeqNode* fldSeq2 = nullptr; - GenTree* obj = nullptr; - GenTree* staticOffset = nullptr; - bool isVolatile = (tree->gtFlags & GTF_IND_VOLATILE) != 0; + GenTree* addr = tree->AsIndir()->Addr(); + GenTreeLclVarCommon* lclVarTree = nullptr; + FieldSeqNode* fldSeq = nullptr; + GenTree* baseAddr = nullptr; + bool isVolatile = (tree->gtFlags & GTF_IND_VOLATILE) != 0; // See if the addr has any exceptional part. ValueNumPair addrNvnp; @@ -8849,61 +8876,65 @@ void Compiler::fgValueNumberTree(GenTree* tree) // Try to parse it. GenTree* arr = nullptr; addr->ParseArrayAddress(this, &arrInfo, &arr, &inxVN, &fldSeq); - if (arr == nullptr) - { - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); - return; - } - assert(fldSeq != FieldSeqStore::NotAField()); - - // Otherwise... - // Need to form H[arrType][arr][ind][fldSeq] - // Get the array element type equivalence class rep. - CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType); - ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL); - JITDUMP(" VNForHandle(arrElemType: %s) is " FMT_VN "\n", - (arrInfo.m_elemType == TYP_STRUCT) ? eeGetClassName(arrInfo.m_elemStructType) - : varTypeName(arrInfo.m_elemType), - elemTypeEqVN) - - // We take the "VNNormalValue"s here, because if either has exceptional outcomes, they will be captured - // as part of the value of the composite "addr" operation... - ValueNum arrVN = vnStore->VNLiberalNormalValue(arr->gtVNPair); - inxVN = vnStore->VNNormalValue(inxVN); - - // Additionally, relabel the address with a PtrToArrElem value number. - ValueNum fldSeqVN = vnStore->VNForFieldSeq(fldSeq); - ValueNum elemAddr = - vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem, elemTypeEqVN, arrVN, inxVN, fldSeqVN); - - // The aggregate "addr" VN should have had all the exceptions bubble up... - elemAddr = vnStore->VNWithExc(elemAddr, addrXvnp.GetLiberal()); - addr->gtVNPair.SetBoth(elemAddr); + if (arr != nullptr) + { + assert(fldSeq != FieldSeqStore::NotAField()); + + // Need to form H[arrType][arr][ind][fldSeq] + // Get the array element type equivalence class rep. + CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType); + ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL); + JITDUMP(" VNForHandle(arrElemType: %s) is " FMT_VN "\n", + (arrInfo.m_elemType == TYP_STRUCT) ? eeGetClassName(arrInfo.m_elemStructType) + : varTypeName(arrInfo.m_elemType), + elemTypeEqVN); + + // We take the "VNNormalValue"s here, because if either has exceptional outcomes, they will + // be captured as part of the value of the composite "addr" operation... + ValueNum arrVN = vnStore->VNLiberalNormalValue(arr->gtVNPair); + inxVN = vnStore->VNNormalValue(inxVN); + + // Additionally, relabel the address with a PtrToArrElem value number. + ValueNum fldSeqVN = vnStore->VNForFieldSeq(fldSeq); + ValueNum elemAddr = + vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem, elemTypeEqVN, arrVN, inxVN, fldSeqVN); + + // The aggregate "addr" VN should have had all the exceptions bubble up... + addr->gtVNPair = vnStore->VNPWithExc(ValueNumPair(elemAddr, elemAddr), addrXvnp); #ifdef DEBUG - if (verbose) - { - printf(" Relabeled IND_ARR_INDEX address node "); - Compiler::printTreeID(addr); - printf(" with l:" FMT_VN ": ", elemAddr); - vnStore->vnDump(this, elemAddr); - printf("\n"); - if (vnStore->VNNormalValue(elemAddr) != elemAddr) + ValueNum elemAddrWithExc = addr->gtVNPair.GetLiberal(); + if (verbose) { - printf(" [" FMT_VN " is: ", vnStore->VNNormalValue(elemAddr)); - vnStore->vnDump(this, vnStore->VNNormalValue(elemAddr)); - printf("]\n"); + printf(" Relabeled IND_ARR_INDEX address node "); + Compiler::printTreeID(addr); + printf(" with l:" FMT_VN ": ", elemAddrWithExc); + vnStore->vnDump(this, elemAddrWithExc); + printf("\n"); + if (elemAddrWithExc != elemAddr) + { + printf(" [" FMT_VN " is: ", elemAddr); + vnStore->vnDump(this, elemAddr); + printf("]\n"); + } } - } #endif // DEBUG - // We now need to retrieve the value number for the array element value - // and give this value number to the GT_IND node 'tree' - // We do this whenever we have an rvalue, but we don't do it for a - // normal LHS assignment into an array element. - // - if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0) + // We now need to retrieve the value number for the array element value + // and give this value number to the GT_IND node 'tree' + // We do this whenever we have an rvalue, but we don't do it for a + // normal LHS assignment into an array element. + // + if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0) + { + fgValueNumberArrIndexVal(tree, elemTypeEq, arrVN, inxVN, addrXvnp, fldSeq); + } + } + else // An unparseable array expression. { - fgValueNumberArrIndexVal(tree, elemTypeEq, arrVN, inxVN, addrXvnp.GetLiberal(), fldSeq); + if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0) + { + tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), addrXvnp); + } } } // In general we skip GT_IND nodes on that are the LHS of an assignment. (We labeled these earlier.) @@ -8962,43 +8993,44 @@ void Compiler::fgValueNumberTree(GenTree* tree) } else if (vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToArrElem)) { - fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp.GetLiberal()); + fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp); } - else if (addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2)) + else if (addr->IsFieldAddr(this, &baseAddr, &fldSeq)) { - assert((fldSeq2 != nullptr) && (fldSeq2 != FieldSeqStore::NotAField()) && - !fldSeq2->IsPseudoField()); + assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) && !fldSeq->IsPseudoField()); // The size of the ultimate value we will select, if it is of a struct type. - size_t structSize = 0; + size_t structSize = 0; + ValueNum valueVN = ValueNumStore::NoVN; - // Get the selector for the first field. - var_types firstFieldType; - ValueNum firstFieldSelectorVN = - vnStore->VNForFieldSelector(fldSeq2->GetFieldHandle(), &firstFieldType, &structSize); + if (baseAddr != nullptr) + { + // Instance field / "complex" static: heap[field][baseAddr][struct fields...]. - ValueNum fldMapVN = - vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN); + // Get the selector for the first field. + var_types firstFieldType; + ValueNum firstFieldSelectorVN = + vnStore->VNForFieldSelector(fldSeq->GetFieldHandle(), &firstFieldType, &structSize); - ValueNum firstFieldValueSelectorVN; - if (obj != nullptr) - { - firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(obj->gtVNPair); + ValueNum fldMapVN = + vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN); + + ValueNum firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(baseAddr->gtVNPair); + + // Construct the value number for fldMap[baseAddr]. + ValueNum firstFieldValueVN = + vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN, firstFieldValueSelectorVN); + + // Finally, account for the rest of the fields in the sequence. + valueVN = + vnStore->VNApplySelectors(VNK_Liberal, firstFieldValueVN, fldSeq->m_next, &structSize); } else { - assert(staticOffset != nullptr); - firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(staticOffset->gtVNPair); + // "Simple" static: heap[static][struct fields...]. + valueVN = vnStore->VNApplySelectors(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq, &structSize); } - // Construct the value number for fldMap[obj/offset]. - ValueNum firstFieldValueVN = - vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN, firstFieldValueSelectorVN); - - // Finally, account for the rest of the fields in the sequence. - ValueNum valueVN = - vnStore->VNApplySelectors(VNK_Liberal, firstFieldValueVN, fldSeq2->m_next, &structSize); - valueVN = vnStore->VNApplySelectorsTypeCheck(valueVN, tree->TypeGet(), structSize); tree->gtVNPair.SetLiberal(valueVN); @@ -9015,6 +9047,12 @@ void Compiler::fgValueNumberTree(GenTree* tree) tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp); } } + + // To be able to propagate exception sets, we give location nodes the "Void" VN. + if ((tree->gtFlags & GTF_IND_ASG_LHS) != 0) + { + tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), addrXvnp); + } } else if (tree->OperGet() == GT_CAST) { @@ -9111,8 +9149,7 @@ void Compiler::fgValueNumberTree(GenTree* tree) if (newVN != ValueNumStore::NoVN) { // We don't care about differences between liberal and conservative for pointer values. - newVN = vnStore->VNWithExc(newVN, excSetPair.GetLiberal()); - tree->gtVNPair.SetBoth(newVN); + tree->gtVNPair = vnStore->VNPWithExc(ValueNumPair(newVN, newVN), excSetPair); } else { @@ -9131,28 +9168,8 @@ void Compiler::fgValueNumberTree(GenTree* tree) { case GT_COMMA: { - ValueNumPair op1vnp; - ValueNumPair op1Xvnp; - vnStore->VNPUnpackExc(tree->AsOp()->gtOp1->gtVNPair, &op1vnp, &op1Xvnp); - ValueNumPair op2vnp; - ValueNumPair op2Xvnp = ValueNumStore::VNPForEmptyExcSet(); - GenTree* op2 = tree->gtGetOp2(); - - if (op2->OperIsIndir() && ((op2->gtFlags & GTF_IND_ASG_LHS) != 0)) - { - // If op2 represents the lhs of an assignment then we give a VNForVoid for the lhs - op2vnp = ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid()); - } - else if ((op2->OperGet() == GT_CLS_VAR) && (op2->gtFlags & GTF_CLS_VAR_ASG_LHS)) - { - // If op2 represents the lhs of an assignment then we give a VNForVoid for the lhs - op2vnp = ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid()); - } - else - { - vnStore->VNPUnpackExc(op2->gtVNPair, &op2vnp, &op2Xvnp); - } - tree->gtVNPair = vnStore->VNPWithExc(op2vnp, vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp)); + ValueNumPair op1Xvnp = vnStore->VNPExceptionSet(tree->AsOp()->gtOp1->gtVNPair); + tree->gtVNPair = vnStore->VNPWithExc(tree->AsOp()->gtOp2->gtVNPair, op1Xvnp); } break; @@ -9183,18 +9200,6 @@ void Compiler::fgValueNumberTree(GenTree* tree) } break; - case GT_NULLCHECK: - { - // An Explicit null check, produces no value - // But we do persist any execeptions produced by op1 - // - tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), - vnStore->VNPExceptionSet(tree->AsOp()->gtOp1->gtVNPair)); - // The exception set with VNF_NullPtrExc will be added below - // by fgValueNumberAddExceptionSet - } - break; - case GT_LOCKADD: // Binop noway_assert("LOCKADD should not appear before lowering"); break; @@ -9229,20 +9234,41 @@ void Compiler::fgValueNumberTree(GenTree* tree) break; } + // These unary nodes do not produce values. Note that for NULLCHECK the + // additional exception will be added below by "fgValueNumberAddExceptionSet". case GT_JTRUE: - // These nodes never need to have a ValueNumber - tree->gtVNPair.SetBoth(ValueNumStore::NoVN); + case GT_SWITCH: + case GT_RETURN: + case GT_RETFILT: + case GT_NULLCHECK: + if (tree->gtGetOp1() != nullptr) + { + tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), + vnStore->VNPExceptionSet(tree->gtGetOp1()->gtVNPair)); + } + else + { + tree->gtVNPair = vnStore->VNPForVoid(); + } break; + // BOX and CKFINITE are passthrough nodes (like NOP). We'll add the exception for the latter later. case GT_BOX: - // BOX doesn't do anything at this point, the actual object allocation - // and initialization happens separately (and not numbering BOX correctly - // prevents seeing allocation related assertions through it) + case GT_CKFINITE: tree->gtVNPair = tree->gtGetOp1()->gtVNPair; break; + // These unary nodes will receive a unique VN. + // TODO-CQ: model INIT_VAL properly. + case GT_LCLHEAP: + case GT_INIT_VAL: + tree->gtVNPair = + vnStore->VNPUniqueWithExc(tree->TypeGet(), + vnStore->VNPExceptionSet(tree->gtGetOp1()->gtVNPair)); + break; + default: - // The default action is to give the node a new, unique VN. + assert(!"Unhandled node in fgValueNumberTree"); tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); break; } @@ -9275,6 +9301,30 @@ void Compiler::fgValueNumberTree(GenTree* tree) break; #endif // FEATURE_HW_INTRINSICS + case GT_STORE_DYN_BLK: + { + // Conservatively, mutate the heaps - we don't analyze these rare stores. + // Likewise, any locals possibly defined by them we mark as address-exposed. + fgMutateGcHeap(tree DEBUGARG("dynamic block store")); + + GenTreeStoreDynBlk* store = tree->AsStoreDynBlk(); + ValueNumPair vnpExcSet = ValueNumStore::VNPForEmptyExcSet(); + + // Propagate the exceptions... + vnpExcSet = vnStore->VNPUnionExcSet(store->Addr()->gtVNPair, vnpExcSet); + vnpExcSet = vnStore->VNPUnionExcSet(store->Data()->gtVNPair, vnpExcSet); + vnpExcSet = vnStore->VNPUnionExcSet(store->gtDynamicSize->gtVNPair, vnpExcSet); + + // This is a store, it produces no value. Thus we use VNPForVoid(). + store->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), vnpExcSet); + + // Note that we are only adding the exception for the destination address. + // Currently, "Data()" is an explicit indirection in case this is a "cpblk". + assert(store->Data()->gtEffectiveVal()->OperIsIndir() || store->OperIsInitBlkOp()); + fgValueNumberAddExceptionSetForIndirection(store, store->Addr()); + break; + } + case GT_CMPXCHG: // Specialop { // For CMPXCHG and other intrinsics add an arbitrary side effect on GcHeap/ByrefExposed. @@ -9309,8 +9359,38 @@ void Compiler::fgValueNumberTree(GenTree* tree) break; } + // ARR_ELEM is a bounds-checked address. TODO-CQ: model it precisely. + case GT_ARR_ELEM: + { + GenTreeArrElem* arrElem = tree->AsArrElem(); + + ValueNumPair vnpExcSet = vnStore->VNPExceptionSet(arrElem->gtArrObj->gtVNPair); + for (size_t i = 0; i < arrElem->gtArrRank; i++) + { + vnpExcSet = vnStore->VNPUnionExcSet(arrElem->gtArrInds[i]->gtVNPair, vnpExcSet); + } + + arrElem->gtVNPair = vnStore->VNPUniqueWithExc(arrElem->TypeGet(), vnpExcSet); + + // TODO: model the IndexOutOfRangeException for this node. + fgValueNumberAddExceptionSetForIndirection(arrElem, arrElem->gtArrObj); + } + break; + + // FIELD_LIST is an R-value that we currently don't model. + case GT_FIELD_LIST: + tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); + for (GenTreeFieldList::Use& use : tree->AsFieldList()->Uses()) + { + tree->gtVNPair = + vnStore->VNPWithExc(tree->gtVNPair, vnStore->VNPExceptionSet(use.GetNode()->gtVNPair)); + } + break; + default: + assert(!"Unhandled special node in fgValueNumberTree"); tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); + break; } } #ifdef DEBUG @@ -9384,19 +9464,25 @@ void Compiler::fgValueNumberSimd(GenTreeSIMD* tree) ValueNumPair excSetPair; ValueNumPair normalPair; + if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 1) == 1)) + { + // We have a SIMD node with 3 or more args. To retain the + // previous behavior, we will generate a unique VN for this case. + excSetPair = ValueNumStore::VNPForEmptyExcSet(); + for (GenTree* operand : tree->Operands()) + { + excSetPair = vnStore->VNPUnionExcSet(operand->gtVNPair, excSetPair); + } + tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), excSetPair); + return; + } + // There are some SIMD operations that have zero args, i.e. NI_Vector128_Zero if (tree->GetOperandCount() == 0) { excSetPair = ValueNumStore::VNPForEmptyExcSet(); normalPair = vnStore->VNPairForFunc(tree->TypeGet(), simdFunc); } - else if (tree->GetOperandCount() > 2) - { - // We have a SIMD node with 3 or more args. To retain the - // previous behavior, we will generate a unique VN for this case. - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); - return; - } else // SIMD unary or binary operator. { ValueNumPair resvnp = ValueNumPair(); @@ -9521,12 +9607,17 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree) fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore")); } - if (tree->GetOperandCount() > 2) + if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 2) == 2)) { // 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 previois behavior. - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); + // Generate unique VN for now to retaing previous behavior. + ValueNumPair vnpExcSet = vnStore->VNPForEmptyExcSet(); + for (GenTree* operand : tree->Operands()) + { + vnpExcSet = vnStore->VNPUnionExcSet(operand->gtVNPair, vnpExcSet); + } + tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), vnpExcSet); return; } @@ -9538,15 +9629,13 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree) // if (isMemoryLoad) { - ValueNumPair op1vnp; - ValueNumPair op1Xvnp; - vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp); + ValueNumPair op1vnp = vnStore->VNPNormalPair(tree->Op(1)->gtVNPair); // 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()); // The address could point anywhere, so it is an ByrefExposed load. @@ -9554,7 +9643,11 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree) ValueNum loadVN = fgValueNumberByrefExposedLoad(tree->TypeGet(), addrVN); tree->gtVNPair.SetLiberal(loadVN); tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet())); - tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, op1Xvnp); + + for (GenTree* operand : tree->Operands()) + { + tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, vnStore->VNPExceptionSet(operand->gtVNPair)); + } fgValueNumberAddExceptionSetForIndirection(tree, tree->Op(1)); return; } @@ -9941,14 +10034,12 @@ void Compiler::fgValueNumberCall(GenTreeCall* call) { // First: do value numbering of any argument placeholder nodes in the argument list // (by transferring from the VN of the late arg that they are standing in for...) - unsigned i = 0; - for (GenTreeCall::Use& use : call->Args()) - { - GenTree* arg = use.GetNode(); + + auto updateArgVN = [=](GenTree* arg, unsigned argIndex) { if (arg->OperGet() == GT_ARGPLACE) { // Find the corresponding late arg. - GenTree* lateArg = call->fgArgInfo->GetArgNode(i); + GenTree* lateArg = call->fgArgInfo->GetArgNode(argIndex); assert(lateArg->gtVNPair.BothDefined()); arg->gtVNPair = lateArg->gtVNPair; #ifdef DEBUG @@ -9962,7 +10053,19 @@ void Compiler::fgValueNumberCall(GenTreeCall* call) } #endif } - i++; + }; + + unsigned argIndex = 0; + if (call->gtCallThisArg != nullptr) + { + updateArgVN(call->gtCallThisArg->GetNode(), argIndex); + argIndex++; + } + + for (GenTreeCall::Use& use : call->Args()) + { + updateArgVN(use.GetNode(), argIndex); + argIndex++; } if (call->gtCallType == CT_HELPER) @@ -10506,27 +10609,16 @@ void Compiler::fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree // Create baseVNP, from the values we just computed, baseVNP = ValueNumPair(baseLVN, baseCVN); - // Unpack, Norm,Exc for the tree's op1 VN - ValueNumPair vnpBaseNorm; - ValueNumPair vnpBaseExc; - vnStore->VNPUnpackExc(baseVNP, &vnpBaseNorm, &vnpBaseExc); + // The exceptions in "baseVNP" should have been added to the "tree"'s set already. + assert(vnStore->VNPExcIsSubset(vnStore->VNPExceptionSet(tree->gtVNPair), vnStore->VNPExceptionSet(baseVNP))); - // The Norm VN for op1 is used to create the NullPtrExc - ValueNumPair excChkSet = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm)); - - // Combine the excChkSet with exception set of op1 - ValueNumPair excSetBoth = vnStore->VNPExcSetUnion(excChkSet, vnpBaseExc); + // The normal VN for base address is used to create the NullPtrExc + ValueNumPair vnpBaseNorm = vnStore->VNPNormalPair(baseVNP); - // Retrieve the Normal VN for tree, note that it may be NoVN, so we handle that case - ValueNumPair vnpNorm = vnStore->VNPNormalPair(tree->gtVNPair); + ValueNumPair excChkSet = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm)); - // For as GT_IND on the lhs of an assignment we will get a NoVN value - if (vnpNorm.GetLiberal() == ValueNumStore::NoVN) - { - // Use the special Void VN value instead. - vnpNorm = vnStore->VNPForVoid(); - } - tree->gtVNPair = vnStore->VNPWithExc(vnpNorm, excSetBoth); + // Add the NullPtrExc to "tree"'s value numbers. + tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, excChkSet); } //-------------------------------------------------------------------------------- @@ -10904,20 +10996,13 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree) break; case GT_INTRINSIC: - // ToDo: model the exceptions for Intrinsics + assert(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType); + fgValueNumberAddExceptionSetForIndirection(tree, tree->AsIntrinsic()->gtGetOp1()); break; - case GT_IND: // Implicit null check. - if ((tree->gtFlags & GTF_IND_ASG_LHS) != 0) - { - // Don't add exception set on LHS of assignment - break; - } - FALLTHROUGH; - + case GT_IND: case GT_BLK: case GT_OBJ: - case GT_DYN_BLK: case GT_NULLCHECK: fgValueNumberAddExceptionSetForIndirection(tree, tree->AsIndir()->Addr()); break; @@ -10956,6 +11041,61 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree) } #ifdef DEBUG +//------------------------------------------------------------------------ +// fgDebugCheckExceptionSets: Verify the exception sets on trees. +// +// This function checks that the node's exception set is a superset of +// the exception sets of its operands. +// +void Compiler::fgDebugCheckExceptionSets() +{ + struct ExceptionSetsChecker + { + static void CheckTree(GenTree* tree, ValueNumStore* vnStore) + { + // We will fail to VN some PHI_ARGs - their values may not + // be known at the point we number them because of loops. + assert(tree->gtVNPair.BothDefined() || tree->OperIs(GT_PHI_ARG)); + + ValueNumPair operandsExcSet = vnStore->VNPForEmptyExcSet(); + tree->VisitOperands([&](GenTree* operand) -> GenTree::VisitResult { + + CheckTree(operand, vnStore); + + ValueNumPair operandVNP = operand->gtVNPair.BothDefined() ? operand->gtVNPair : vnStore->VNPForVoid(); + operandsExcSet = vnStore->VNPUnionExcSet(operandVNP, operandsExcSet); + + return GenTree::VisitResult::Continue; + }); + + // Currently, we fail to properly maintain the exception sets for trees with user + // calls or assignments. + if ((tree->gtFlags & (GTF_ASG | GTF_CALL)) != 0) + { + return; + } + + ValueNumPair nodeExcSet = vnStore->VNPExceptionSet(tree->gtVNPair); + assert(vnStore->VNExcIsSubset(nodeExcSet.GetLiberal(), operandsExcSet.GetLiberal())); + assert(vnStore->VNExcIsSubset(nodeExcSet.GetConservative(), operandsExcSet.GetConservative())); + } + }; + + for (BasicBlock* const block : Blocks()) + { + for (Statement* const stmt : block->Statements()) + { + // Exclude statements VN hasn't visited for whichever reason... + if (stmt->GetRootNode()->GetVN(VNK_Liberal) == ValueNumStore::NoVN) + { + continue; + } + + ExceptionSetsChecker::CheckTree(stmt->GetRootNode(), vnStore); + } + } +} + // This method asserts that SSA name constraints specified are satisfied. // Until we figure out otherwise, all VN's are assumed to be liberal. // TODO-Cleanup: new JitTestLabels for lib vs cons vs both VN classes? diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 289e09fb688b1..6c19327c80037 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -494,6 +494,8 @@ class ValueNumStore // Both arguments must be either VNForEmptyExcSet() or applications of VNF_ExcSetCons. bool VNExcIsSubset(ValueNum vnFullSet, ValueNum vnCandidateSet); + bool VNPExcIsSubset(ValueNumPair vnpFullSet, ValueNumPair vnpCandidateSet); + // Returns "true" iff "vn" is an application of "VNF_ValWithExc". bool VNHasExc(ValueNum vn) { @@ -528,6 +530,12 @@ class ValueNumStore // Keeps any Exception set values ValueNumPair VNPMakeNormalUniquePair(ValueNumPair vnp); + // A new unique value with the given exception set. + ValueNum VNUniqueWithExc(var_types type, ValueNum vnExcSet); + + // A new unique VN pair with the given exception set pair. + ValueNumPair VNPUniqueWithExc(var_types type, ValueNumPair vnpExcSet); + // If "vn" is a "VNF_ValWithExc(norm, excSet)" value, returns the "norm" argument; otherwise, // just returns "vn". // The Normal value is the value number of the expression when no exceptions occurred diff --git a/src/coreclr/md/enc/metamodelrw.cpp b/src/coreclr/md/enc/metamodelrw.cpp index 34fe8b84e95c8..3fde673faa5c4 100644 --- a/src/coreclr/md/enc/metamodelrw.cpp +++ b/src/coreclr/md/enc/metamodelrw.cpp @@ -309,16 +309,15 @@ ULONG CMiniMdRW::m_TruncatedEncTables[] = ULONG CMiniMdRW::GetTableForToken( // Table index, or -1. mdToken tkn) // Token to find. { - ULONG ixTbl; // Loop control. ULONG type = TypeFromToken(tkn); // Get the type -- if a string, no associated table. if (type >= mdtString) return (ULONG) -1; // Table number is same as high-byte of token. - ixTbl = type >> 24; + ULONG ixTbl = type >> 24; // Make sure. - _ASSERTE(g_TblIndex[ixTbl].m_Token == type); + _ASSERTE(ixTbl < TBL_COUNT); return ixTbl; } // CMiniMdRW::GetTableForToken diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets index 67efba61efde9..ae6229a0a7afe 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -48,12 +48,14 @@ - + + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 501384a4c0c6c..529de6be54f55 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -31,6 +31,7 @@ The .NET Foundation licenses this file to you under the MIT license. false true + false @@ -39,8 +40,6 @@ The .NET Foundation licenses this file to you under the MIT license. true true - true - copyused @@ -131,13 +130,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - - true - - - @@ -199,35 +191,6 @@ The .NET Foundation licenses this file to you under the MIT license. Outputs="%(ManagedBinary.IlcRspFile)" DependsOnTargets="$(IlcCompileDependsOn)"> - - - true - - - - - - - <__SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <__SingleWarnIntermediateAssembly Remove="@(IntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <_SingleWarnIntermediateAssembly Remove="@(__SingleWarnIntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly> - false - - - - - - - - false - - - <_IlcRootedAssemblies Include="@(TrimmerRootAssembly)" /> <_IlcRootedAssemblies Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimMode) == 'copy'" /> @@ -246,6 +209,7 @@ The .NET Foundation licenses this file to you under the MIT license. + @@ -278,6 +242,7 @@ The .NET Foundation licenses this file to you under the MIT license. + @@ -285,9 +250,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - @@ -304,8 +266,8 @@ The .NET Foundation licenses this file to you under the MIT license. - - + + diff --git a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp index e1025ce27e664..991f67bb9b227 100644 --- a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp +++ b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp @@ -109,7 +109,8 @@ struct DotNetRuntimeDebugHeader #ifdef TARGET_WINDOWS #pragma comment (linker, "/EXPORT:DotNetRuntimeDebugHeader,DATA") #endif -extern "C" DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader = {}; +extern "C" struct DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader; +struct DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader = {}; #define MAKE_DEBUG_ENTRY(TypeName, FieldName, Value) \ do \ @@ -138,8 +139,8 @@ extern "C" void PopulateDebugHeaders() size_t currentDebugPos = 0; size_t currentGlobalPos = 0; - ZeroMemory(s_DebugEntries, DebugTypeEntriesArraySize); - ZeroMemory(s_GlobalEntries, GlobalEntriesArraySize); + ZeroMemory(s_DebugEntries, sizeof(s_DebugEntries)); + ZeroMemory(s_GlobalEntries, sizeof(s_GlobalEntries)); MAKE_SIZE_ENTRY(GcDacVars); MAKE_DEBUG_FIELD_ENTRY(GcDacVars, major_version_number); diff --git a/src/coreclr/nativeaot/Runtime/MethodTable.cpp b/src/coreclr/nativeaot/Runtime/MethodTable.cpp index 4197cd8ba3623..4d3ace8dcf089 100644 --- a/src/coreclr/nativeaot/Runtime/MethodTable.cpp +++ b/src/coreclr/nativeaot/Runtime/MethodTable.cpp @@ -20,10 +20,6 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) { #define REPORT_FAILURE() do { if (assertOnFail) { ASSERT_UNCONDITIONALLY("MethodTable::Validate check failed"); } return false; } while (false) - // Deal with the most common case of a bad pointer without an exception. - if (this == NULL) - REPORT_FAILURE(); - // MethodTable structures should be at least pointer aligned. if (dac_cast(this) & (sizeof(TADDR)-1)) REPORT_FAILURE(); diff --git a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S index f66851461f278..4d3fbbbce2216 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S +++ b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S @@ -188,7 +188,7 @@ NoAbort: EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 0xA0 EPILOG_RETURN - NESTED_END RhpReversePInvokeTrapThread + NESTED_END RhpReversePInvokeAttachOrTrapThread, _TEXT // // RhpPInvoke diff --git a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm index 7692bfa8341be..4bc165aef0450 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm @@ -180,7 +180,7 @@ NoAbort EPILOG_RESTORE_REG_PAIR fp, lr, #0xA0! EPILOG_RETURN - NESTED_END RhpReversePInvokeTrapThread + NESTED_END RhpReversePInvokeAttachOrTrapThread ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/coreclr/nativeaot/Runtime/eventtrace.cpp b/src/coreclr/nativeaot/Runtime/eventtrace.cpp index 23dd9726b5ed2..0f4646152165b 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace.cpp @@ -35,9 +35,9 @@ #define Win32EventWrite EventWrite // Flags used to store some runtime information for Event Tracing -BOOL g_fEEOtherStartup=FALSE; -BOOL g_fEEComActivatedStartup=FALSE; -LPCGUID g_fEEComObjectGuid=&GUID_NULL; +BOOL g_fEEOtherStartup = FALSE; +BOOL g_fEEComActivatedStartup = FALSE; +LPCGUID g_fEEComObjectGuid = &GUID_NULL; BOOL g_fEEHostedStartup = FALSE; @@ -188,16 +188,16 @@ BOOL IsRuntimeNgenKeywordEnabledAndNotSuppressed() LIMITED_METHOD_CONTRACT; return - ( - ETW_TRACING_CATEGORY_ENABLED( - MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_NGEN_KEYWORD) - && ! ( ETW_TRACING_CATEGORY_ENABLED( + ( + ETW_TRACING_CATEGORY_ENABLED( MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, - CLR_OVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD) ) - ); + CLR_NGEN_KEYWORD) + && !(ETW_TRACING_CATEGORY_ENABLED( + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_OVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD)) + ); } // Same as above, but for the rundown provider @@ -206,16 +206,16 @@ BOOL IsRundownNgenKeywordEnabledAndNotSuppressed() LIMITED_METHOD_CONTRACT; return - ( - ETW_TRACING_CATEGORY_ENABLED( - MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNNGEN_KEYWORD) - && ! ( ETW_TRACING_CATEGORY_ENABLED( + ( + ETW_TRACING_CATEGORY_ENABLED( + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNNGEN_KEYWORD) + && !(ETW_TRACING_CATEGORY_ENABLED( MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNOVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD) ) - ); + CLR_RUNDOWNOVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD)) + ); } /*******************************************************/ @@ -226,7 +226,7 @@ extern "C" { CallStackFrame* GetEbp() { - CallStackFrame *frame=NULL; + CallStackFrame* frame = NULL; __asm { mov frame, ebp @@ -244,8 +244,8 @@ extern "C" void ETW::SamplingLog::Append(SIZE_T currentFrame) { LIMITED_METHOD_CONTRACT; - if(m_FrameCount < (ETW::SamplingLog::s_MaxStackSize-1) && - currentFrame != 0) + if (m_FrameCount < (ETW::SamplingLog::s_MaxStackSize - 1) && + currentFrame != 0) { m_EBPStack[m_FrameCount] = currentFrame; m_FrameCount++; @@ -255,7 +255,7 @@ void ETW::SamplingLog::Append(SIZE_T currentFrame) /********************************************************/ /* Function to get the callstack on the current thread */ /********************************************************/ -ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack) +ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStack(UINT32* frameCount, PVOID** Stack) { CONTRACTL { @@ -278,17 +278,17 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStac // this not really needed, but let's do it // because we use the framecount while dumping the stack event - for(int i=m_FrameCount; im_Next; // Skip the top N frames - if(skipTopNFrames) { + if (skipTopNFrames) { skipTopNFrames--; continue; } @@ -358,16 +358,16 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip Append(lastEBP->m_ReturnAddress); // Check for stack limits - if((SIZE_T)currentEBP < (SIZE_T)Thread::GetStackLowerBound() || (SIZE_T)currentEBP > (SIZE_T)Thread::GetStackUpperBound()) + if ((SIZE_T)currentEBP < (SIZE_T)Thread::GetStackLowerBound() || (SIZE_T)currentEBP >(SIZE_T)Thread::GetStackUpperBound()) { break; } // If we have a too small address, we are probably bad - if((SIZE_T)currentEBP < (SIZE_T)0x10000) + if ((SIZE_T)currentEBP < (SIZE_T)0x10000) break; - if((SIZE_T)currentEBP < (SIZE_T)lastEBP) + if ((SIZE_T)currentEBP < (SIZE_T)lastEBP) { break; } @@ -378,7 +378,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip UINT_PTR ControlPc = 0; UINT_PTR CurrentSP = 0, PrevSP = 0; - while(1) + while (1) { // Unwind to the caller ControlPc = Thread::VirtualUnwindCallFrame(&ctx); @@ -387,13 +387,13 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip CurrentSP = (UINT_PTR)GetSP(&ctx); // when to break from this loop - if ( ControlPc == 0 || ( PrevSP == CurrentSP ) ) + if (ControlPc == 0 || (PrevSP == CurrentSP)) { break; } // Skip the top N frames - if ( skipTopNFrames ) { + if (skipTopNFrames) { skipTopNFrames--; continue; } @@ -404,7 +404,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip PrevSP = CurrentSP; } #endif //TARGET_X86 - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); pThread->MarkEtwStackWalkCompleted(); #endif //!DACCESS_COMPILE @@ -431,7 +431,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip /***************************************************************************/ /* This function should be called from the event tracing callback routine when the private CLR provider is enabled */ -/***************************************************************************/ + /***************************************************************************/ #ifndef FEATURE_REDHAWK @@ -440,13 +440,13 @@ void ETW::GCLog::GCSettingsEvent() if (GCHeapUtilities::IsGCHeapInitialized()) { if (ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - GCSettings)) + GCSettings)) { ETW::GCLog::ETW_GC_INFO Info; - Info.GCSettings.ServerGC = GCHeapUtilities::IsServerHeap (); - Info.GCSettings.SegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (FALSE); - Info.GCSettings.LargeObjectSegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (TRUE); + Info.GCSettings.ServerGC = GCHeapUtilities::IsServerHeap(); + Info.GCSettings.SegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(FALSE); + Info.GCSettings.LargeObjectSegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(TRUE); FireEtwGCSettings_V1(Info.GCSettings.SegmentSize, Info.GCSettings.LargeObjectSegmentSize, Info.GCSettings.ServerGC, GetClrInstanceId()); } GCHeapUtilities::GetGCHeap()->TraceGCSegments(); @@ -518,13 +518,13 @@ struct EtwGcMovementContext // else, a new EtwGcMovementContext is allocated, stored in that pointer, and // then returned. Callers should test for NULL, which can be returned if out of // memory - static EtwGcMovementContext * GetOrCreateInGCContext(EtwGcMovementContext ** ppContext) + static EtwGcMovementContext* GetOrCreateInGCContext(EtwGcMovementContext** ppContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(ppContext != NULL); - EtwGcMovementContext * pContext = *ppContext; + EtwGcMovementContext* pContext = *ppContext; if (pContext == NULL) { pContext = new (nothrow) EtwGcMovementContext; @@ -597,13 +597,13 @@ struct MovedReferenceContextForEtwAndProfapi // returned; else, a new MovedReferenceContextForEtwAndProfapi is allocated, stored // in that pointer, and then returned. Callers should test for NULL, which can be // returned if out of memory - static MovedReferenceContextForEtwAndProfapi * CreateInGCContext(LPVOID pvContext) + static MovedReferenceContextForEtwAndProfapi* CreateInGCContext(LPVOID pvContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(pvContext != NULL); - MovedReferenceContextForEtwAndProfapi * pContext = *(MovedReferenceContextForEtwAndProfapi **) pvContext; + MovedReferenceContextForEtwAndProfapi* pContext = *(MovedReferenceContextForEtwAndProfapi**)pvContext; // Shouldn't be called if the context was already created. Perhaps someone made // one too many BeginMovedReferences calls, or didn't have an EndMovedReferences @@ -611,7 +611,7 @@ struct MovedReferenceContextForEtwAndProfapi _ASSERTE(pContext == NULL); pContext = new (nothrow) MovedReferenceContextForEtwAndProfapi; - *(MovedReferenceContextForEtwAndProfapi **) pvContext = pContext; + *(MovedReferenceContextForEtwAndProfapi**)pvContext = pContext; return pContext; } @@ -626,7 +626,7 @@ struct MovedReferenceContextForEtwAndProfapi } LPVOID pctxProfAPI; - EtwGcMovementContext * pctxEtw; + EtwGcMovementContext* pctxEtw; }; @@ -648,8 +648,8 @@ struct MovedReferenceContextForEtwAndProfapi // static void ETW::GCLog::MovedReference( - BYTE * pbMemBlockStart, - BYTE * pbMemBlockEnd, + BYTE* pbMemBlockStart, + BYTE* pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, @@ -665,8 +665,8 @@ void ETW::GCLog::MovedReference( } CONTRACTL_END; - MovedReferenceContextForEtwAndProfapi * pCtxForEtwAndProfapi = - (MovedReferenceContextForEtwAndProfapi *) profilingContext; + MovedReferenceContextForEtwAndProfapi* pCtxForEtwAndProfapi = + (MovedReferenceContextForEtwAndProfapi*)profilingContext; if (pCtxForEtwAndProfapi == NULL) { _ASSERTE(!"MovedReference() encountered a NULL profilingContext"); @@ -678,10 +678,10 @@ void ETW::GCLog::MovedReference( { BEGIN_PIN_PROFILER(CORProfilerTrackGC()); g_profControlBlock.pProfInterface->MovedReference(pbMemBlockStart, - pbMemBlockEnd, - cbRelocDistance, - &(pCtxForEtwAndProfapi->pctxProfAPI), - fCompacting); + pbMemBlockEnd, + cbRelocDistance, + &(pCtxForEtwAndProfapi->pctxProfAPI), + fCompacting); END_PIN_PROFILER(); } #endif // PROFILING_SUPPORTED @@ -691,7 +691,7 @@ void ETW::GCLog::MovedReference( if (!ShouldTrackMovementForEtw()) return; - EtwGcMovementContext * pContext = + EtwGcMovementContext* pContext = EtwGcMovementContext::GetOrCreateInGCContext(&pCtxForEtwAndProfapi->pctxEtw); if (pContext == NULL) return; @@ -701,7 +701,7 @@ void ETW::GCLog::MovedReference( // Moved references _ASSERTE(pContext->cBulkMovedObjectRanges < _countof(pContext->rgGCBulkMovedObjectRanges)); - EventStructGCBulkMovedObjectRangesValue * pValue = + EventStructGCBulkMovedObjectRangesValue* pValue = &pContext->rgGCBulkMovedObjectRanges[pContext->cBulkMovedObjectRanges]; pValue->OldRangeBase = pbMemBlockStart; pValue->NewRangeBase = pbMemBlockStart + cbRelocDistance; @@ -727,7 +727,7 @@ void ETW::GCLog::MovedReference( // Surviving references _ASSERTE(pContext->cBulkSurvivingObjectRanges < _countof(pContext->rgGCBulkSurvivingObjectRanges)); - EventStructGCBulkSurvivingObjectRangesValue * pValue = + EventStructGCBulkSurvivingObjectRangesValue* pValue = &pContext->rgGCBulkSurvivingObjectRanges[pContext->cBulkSurvivingObjectRanges]; pValue->RangeBase = pbMemBlockStart; pValue->RangeLength = pbMemBlockEnd - pbMemBlockStart; @@ -763,7 +763,7 @@ void ETW::GCLog::MovedReference( // // static -void ETW::GCLog::BeginMovedReferences(size_t * pProfilingContext) +void ETW::GCLog::BeginMovedReferences(size_t* pProfilingContext) { LIMITED_METHOD_CONTRACT; @@ -794,7 +794,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext, } CONTRACTL_END; - MovedReferenceContextForEtwAndProfapi * pCtxForEtwAndProfapi = (MovedReferenceContextForEtwAndProfapi *) profilingContext; + MovedReferenceContextForEtwAndProfapi* pCtxForEtwAndProfapi = (MovedReferenceContextForEtwAndProfapi*)profilingContext; if (pCtxForEtwAndProfapi == NULL) { _ASSERTE(!"EndMovedReferences() encountered a NULL profilingContext"); @@ -817,7 +817,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext, // If context isn't already set up for us, then we haven't been collecting any data // for ETW events. - EtwGcMovementContext * pContext = pCtxForEtwAndProfapi->pctxEtw; + EtwGcMovementContext* pContext = pCtxForEtwAndProfapi->pctxEtw; if (pContext == NULL) return; @@ -893,7 +893,7 @@ void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) // // static -void ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo) +void ETW::GCLog::FireGcStart(ETW_GC_INFO* pGcInfo) { LIMITED_METHOD_CONTRACT; @@ -924,7 +924,7 @@ void ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo) FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog); #elif defined(FEATURE_DTRACE) - FireEtwGCStart(pGcInfo->GCStart.Count,pGcInfo->GCStart.Reason); + FireEtwGCStart(pGcInfo->GCStart.Count, pGcInfo->GCStart.Reason); #endif } @@ -990,7 +990,7 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() _ASSERTE(GCHeapUtilities::IsGCHeapInitialized()); ThreadStore::AttachCurrentThread(); - Thread * pThread = ThreadStore::GetCurrentThread(); + Thread* pThread = ThreadStore::GetCurrentThread(); // Doing this prevents the GC from trying to walk this thread's stack for roots. pThread->SetGCSpecial(true); @@ -1011,11 +1011,11 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() pThread->EnablePreemptiveMode(); #else // !FEATURE_REDHAWK } - EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions); +EX_CATCH{ } +EX_END_CATCH(RethrowCorruptingExceptions); #endif // FEATURE_REDHAWK - return hr; +return hr; } @@ -1142,7 +1142,7 @@ void BulkTypeEventLogger::FireBulkTypeEvent() #ifdef FEATURE_REDHAWK ((m_rgBulkTypeValues[iTypeData].cTypeParameters == 1) ? &(m_rgBulkTypeValues[iTypeData].ullSingleTypeParameter) : - (ULONGLONG *) (m_rgBulkTypeValues[iTypeData].rgTypeParameters)), + (ULONGLONG*)(m_rgBulkTypeValues[iTypeData].rgTypeParameters)), #else m_rgBulkTypeValues[iTypeData].rgTypeParameters.GetElements(), #endif @@ -1200,7 +1200,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) return -1; } - BulkTypeValue * pVal = &m_rgBulkTypeValues[m_nBulkTypeValueCount]; + BulkTypeValue* pVal = &m_rgBulkTypeValues[m_nBulkTypeValueCount]; // Clear out pVal before filling it out (array elements can get reused if there // are enough types that we need to flush to multiple events). Clearing the @@ -1211,7 +1211,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) pVal->Clear(); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1219,11 +1219,11 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) if (!fSucceeded) return -1; - pVal->fixedSizedData.TypeID = (ULONGLONG) th.AsTAddr(); - pVal->fixedSizedData.ModuleID = (ULONGLONG) (TADDR) th.GetModule(); + pVal->fixedSizedData.TypeID = (ULONGLONG)th.AsTAddr(); + pVal->fixedSizedData.ModuleID = (ULONGLONG)(TADDR)th.GetModule(); pVal->fixedSizedData.TypeNameID = (th.GetMethodTable() == NULL) ? 0 : th.GetCl(); pVal->fixedSizedData.Flags = 0; - pVal->fixedSizedData.CorElementType = (BYTE) th.GetInternalCorElementType(); + pVal->fixedSizedData.CorElementType = (BYTE)th.GetInternalCorElementType(); if (th.IsArray()) { @@ -1234,10 +1234,10 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - pVal->rgTypeParameters.Append((ULONGLONG) th.AsArray()->GetArrayElementTypeHandle().AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)th.AsArray()->GetArrayElementTypeHandle().AsTAddr()); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1254,10 +1254,10 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - pVal->rgTypeParameters.Append((ULONGLONG) pTypeDesc->GetTypeParam().AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)pTypeDesc->GetTypeParam().AsTAddr()); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1290,13 +1290,13 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - for (DWORD i=0; i < cTypeParameters; i++) + for (DWORD i = 0; i < cTypeParameters; i++) { - pVal->rgTypeParameters.Append((ULONGLONG) inst[i].AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)inst[i].AsTAddr()); } fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1332,7 +1332,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) } pVal->sName.Normalize(); } - EX_CATCH + EX_CATCH { // If this failed, the name remains empty, which is ok; the event just // won't have a name in it. @@ -1397,7 +1397,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } CONTRACTL_END; - TypeHandle th = TypeHandle::FromTAddr((TADDR) thAsAddr); + TypeHandle th = TypeHandle::FromTAddr((TADDR)thAsAddr); // Batch up this type. This grabs useful info about the type, including any // type parameters it may have, and sticks it in m_rgBulkTypeValues @@ -1410,7 +1410,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } // Look at the type info we just batched, so we can get the type parameters - BulkTypeValue * pVal = &m_rgBulkTypeValues[iBulkTypeEventData]; + BulkTypeValue* pVal = &m_rgBulkTypeValues[iBulkTypeEventData]; // We're about to recursively call ourselves for the type parameters, so make a // local copy of their type handles first (else, as we log them we could flush @@ -1428,7 +1428,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1443,7 +1443,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst typeLogBehavior = ETW::TypeSystemLog::kTypeLogBehaviorAssumeLockAndLogIfFirstTime; // Recursively log any referenced parameter types - for (COUNT_T i=0; i < cParams; i++) + for (COUNT_T i = 0; i < cParams; i++) { ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(this, rgTypeParameters[i], typeLogBehavior); } @@ -1463,13 +1463,13 @@ class EtwGcHeapDumpContext // ProfilerWalkHeapContext::pvEtwContext; if non-NULL it gets returned; else, a new // EtwGcHeapDumpContext is allocated, stored in that pointer, and then returned. // Callers should test for NULL, which can be returned if out of memory - static EtwGcHeapDumpContext * GetOrCreateInGCContext(LPVOID * ppvEtwContext) + static EtwGcHeapDumpContext* GetOrCreateInGCContext(LPVOID* ppvEtwContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(ppvEtwContext != NULL); - EtwGcHeapDumpContext * pContext = (EtwGcHeapDumpContext *) *ppvEtwContext; + EtwGcHeapDumpContext* pContext = (EtwGcHeapDumpContext*)*ppvEtwContext; if (pContext == NULL) { pContext = new (nothrow) EtwGcHeapDumpContext; @@ -1644,10 +1644,10 @@ class EtwGcHeapDumpContext // static void ETW::GCLog::RootReference( LPVOID pvHandle, - Object * pRootedNode, - Object * pSecondaryNodeForDependentHandle, + Object* pRootedNode, + Object* pSecondaryNodeForDependentHandle, BOOL fDependentHandle, - ProfilingScanContext * profilingScanContext, + ProfilingScanContext* profilingScanContext, DWORD dwGCFlags, DWORD rootFlags) { @@ -1657,14 +1657,14 @@ void ETW::GCLog::RootReference( if (pRootedNode == NULL) return; - EtwGcHeapDumpContext * pContext = + EtwGcHeapDumpContext* pContext = EtwGcHeapDumpContext::GetOrCreateInGCContext(&profilingScanContext->pvEtwContext); if (pContext == NULL) return; // Determine root kind, root ID, and handle-specific flags LPVOID pvRootID = NULL; - BYTE nRootKind = (BYTE) profilingScanContext->dwEtwRootKind; + BYTE nRootKind = (BYTE)profilingScanContext->dwEtwRootKind; switch (nRootKind) { case kEtwGCRootKindStack: @@ -1699,7 +1699,7 @@ void ETW::GCLog::RootReference( { _ASSERTE(pContext->cGCBulkRootConditionalWeakTableElementEdges < _countof(pContext->rgGCBulkRootConditionalWeakTableElementEdges)); - EventStructGCBulkRootConditionalWeakTableElementEdgeValue * pRCWTEEdgeValue = + EventStructGCBulkRootConditionalWeakTableElementEdgeValue* pRCWTEEdgeValue = &pContext->rgGCBulkRootConditionalWeakTableElementEdges[pContext->cGCBulkRootConditionalWeakTableElementEdges]; pRCWTEEdgeValue->GCKeyNodeID = pRootedNode; pRCWTEEdgeValue->GCValueNodeID = pSecondaryNodeForDependentHandle; @@ -1724,7 +1724,7 @@ void ETW::GCLog::RootReference( else { _ASSERTE(pContext->cGcBulkRootEdges < _countof(pContext->rgGcBulkRootEdges)); - EventStructGCBulkRootEdgeValue * pBulkRootEdgeValue = &pContext->rgGcBulkRootEdges[pContext->cGcBulkRootEdges]; + EventStructGCBulkRootEdgeValue* pBulkRootEdgeValue = &pContext->rgGcBulkRootEdges[pContext->cGcBulkRootEdges]; pBulkRootEdgeValue->RootedNodeAddress = pRootedNode; pBulkRootEdgeValue->GCRootKind = nRootKind; pBulkRootEdgeValue->GCRootFlag = rootFlags; @@ -1765,11 +1765,11 @@ void ETW::GCLog::RootReference( // static void ETW::GCLog::ObjectReference( - ProfilerWalkHeapContext * profilerWalkHeapContext, - Object * pObjReferenceSource, + ProfilerWalkHeapContext* profilerWalkHeapContext, + Object* pObjReferenceSource, ULONGLONG typeID, ULONGLONG cRefs, - Object ** rgObjReferenceTargets) + Object** rgObjReferenceTargets) { #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT CONTRACTL @@ -1783,7 +1783,7 @@ void ETW::GCLog::ObjectReference( } CONTRACTL_END; - EtwGcHeapDumpContext * pContext = + EtwGcHeapDumpContext* pContext = EtwGcHeapDumpContext::GetOrCreateInGCContext(&profilerWalkHeapContext->pvEtwContext); if (pContext == NULL) return; @@ -1794,7 +1794,7 @@ void ETW::GCLog::ObjectReference( // Add Node (pObjReferenceSource) to buffer _ASSERTE(pContext->cGcBulkNodeValues < _countof(pContext->rgGcBulkNodeValues)); - EventStructGCBulkNodeValue * pBulkNodeValue = &pContext->rgGcBulkNodeValues[pContext->cGcBulkNodeValues]; + EventStructGCBulkNodeValue* pBulkNodeValue = &pContext->rgGcBulkNodeValues[pContext->cGcBulkNodeValues]; pBulkNodeValue->Address = pObjReferenceSource; pBulkNodeValue->Size = pObjReferenceSource->GetSize(); pBulkNodeValue->TypeID = typeID; @@ -1830,7 +1830,7 @@ void ETW::GCLog::ObjectReference( // During heap walk, GC holds the lock for us, so we can directly enter the // hash to see if the type has already been logged ETW::TypeSystemLog::kTypeLogBehaviorAssumeLockAndLogIfFirstTime - ); + ); } //--------------------------------------------------------------------------------------- @@ -1842,10 +1842,10 @@ void ETW::GCLog::ObjectReference( // a lot of edges), so empty Edge buffer into ETW as we go along, as many times as we // need. - for (ULONGLONG i=0; i < cRefs; i++) + for (ULONGLONG i = 0; i < cRefs; i++) { _ASSERTE(pContext->cGcBulkEdgeValues < _countof(pContext->rgGcBulkEdgeValues)); - EventStructGCBulkEdgeValue * pBulkEdgeValue = &pContext->rgGcBulkEdgeValues[pContext->cGcBulkEdgeValues]; + EventStructGCBulkEdgeValue* pBulkEdgeValue = &pContext->rgGcBulkEdgeValues[pContext->cGcBulkEdgeValues]; pBulkEdgeValue->Value = rgObjReferenceTargets[i]; // FUTURE: ReferencingFieldID pBulkEdgeValue->ReferencingFieldID = 0; @@ -1878,14 +1878,14 @@ void ETW::GCLog::ObjectReference( // // static -void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext) +void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext* profilerWalkHeapContext) { #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT LIMITED_METHOD_CONTRACT; // If context isn't already set up for us, then we haven't been collecting any data // for ETW events. - EtwGcHeapDumpContext * pContext = (EtwGcHeapDumpContext *) profilerWalkHeapContext->pvEtwContext; + EtwGcHeapDumpContext* pContext = (EtwGcHeapDumpContext*)profilerWalkHeapContext->pvEtwContext; if (pContext == NULL) return; @@ -1969,7 +1969,7 @@ void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext) // // static -void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) +void ETW::GCLog::SendFinalizeObjectEvent(MethodTable* pMT, Object* pObj) { CONTRACTL { @@ -1991,12 +1991,12 @@ void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) // finalized object's type (and parameter types, if any) ETW::TypeSystemLog::LogTypeAndParametersIfNecessary( NULL, // Not batching this type with others - (TADDR) pMT, + (TADDR)pMT, // Don't spend the time entering the lock and checking the hash table to see // if we've already logged the type; just log it (if type events are enabled). ETW::TypeSystemLog::kTypeLogBehaviorAlwaysLog - ); + ); } // Send private finalize object event, if it's enabled @@ -2007,14 +2007,14 @@ void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) DefineFullyQualifiedNameForClassWOnStack(); FireEtwPrvFinalizeObject(pMT, pObj, GetClrInstanceId(), GetFullyQualifiedNameForClassNestedAwareW(pMT)); } - EX_CATCH + EX_CATCH { } EX_END_CATCH(RethrowCorruptingExceptions); } } -DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread * pThread) +DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2037,7 +2037,7 @@ DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread * pThread) return dwEtwThreadFlags; } -void ETW::ThreadLog::FireThreadCreated(Thread * pThread) +void ETW::ThreadLog::FireThreadCreated(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2050,7 +2050,7 @@ void ETW::ThreadLog::FireThreadCreated(Thread * pThread) GetClrInstanceId()); } -void ETW::ThreadLog::FireThreadDC(Thread * pThread) +void ETW::ThreadLog::FireThreadDC(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2088,7 +2088,7 @@ class LoggedTypesFromModuleTraits : public NoRemoveSHashTraits< DefaultSHashTrai typedef TypeHandle key_t; - static key_t GetKey(const element_t &e) + static key_t GetKey(const element_t& e) { LIMITED_METHOD_CONTRACT; return e.th; @@ -2103,10 +2103,10 @@ class LoggedTypesFromModuleTraits : public NoRemoveSHashTraits< DefaultSHashTrai static count_t Hash(key_t k) { LIMITED_METHOD_CONTRACT; - return (count_t) k.AsTAddr(); + return (count_t)k.AsTAddr(); } - static bool IsNull(const element_t &e) + static bool IsNull(const element_t& e) { LIMITED_METHOD_CONTRACT; return (e.th.AsTAddr() == NULL); @@ -2125,23 +2125,23 @@ typedef SHash LoggedTypesFromModuleHash; class ETW::LoggedTypesFromModule { public: - Module * pModule; + Module* pModule; LoggedTypesFromModuleHash loggedTypesFromModuleHash; // These are used by the outer hash table (mapping Module*'s to instances of // LoggedTypesFromModule). - static COUNT_T Hash(Module * pModule) + static COUNT_T Hash(Module* pModule) { LIMITED_METHOD_CONTRACT; - return (COUNT_T) (SIZE_T) pModule; + return (COUNT_T)(SIZE_T)pModule; } - Module * GetKey() + Module* GetKey() { LIMITED_METHOD_CONTRACT; return pModule; } - LoggedTypesFromModule(Module * pModuleParam) : loggedTypesFromModuleHash() + LoggedTypesFromModule(Module* pModuleParam) : loggedTypesFromModuleHash() { LIMITED_METHOD_CONTRACT; pModule = pModuleParam; @@ -2156,19 +2156,19 @@ class ETW::LoggedTypesFromModule // The following define the outer hash table (mapping Module*'s to instances of // LoggedTypesFromModule). -class AllLoggedTypesTraits : public DefaultSHashTraits +class AllLoggedTypesTraits : public DefaultSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused - typedef DefaultSHashTraits PARENT; + typedef DefaultSHashTraits PARENT; typedef PARENT::element_t element_t; typedef PARENT::count_t count_t; - typedef Module * key_t; + typedef Module* key_t; - static key_t GetKey(const element_t &e) + static key_t GetKey(const element_t& e) { LIMITED_METHOD_CONTRACT; return e->pModule; @@ -2183,10 +2183,10 @@ class AllLoggedTypesTraits : public DefaultSHashTraitsloggedTypesFromModuleHash.AddOrReplace(*pTypeLoggingInfo); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2447,7 +2447,7 @@ BOOL ETW::TypeSystemLog::AddOrReplaceTypeLoggingInfo(ETW::LoggedTypesFromModule // // static -void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) +void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object* pObject) { CONTRACTL { @@ -2465,7 +2465,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) TypeHandle th = pObject->GetTypeHandle(); SIZE_T size = pObject->GetSize(); - if(size < MIN_OBJECT_SIZE) + if (size < MIN_OBJECT_SIZE) { size = PtrAlign(size); } @@ -2481,7 +2481,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Get stats for type TypeLoggingInfo typeLoggingInfo(NULL); - LoggedTypesFromModule * pLoggedTypesFromModule = NULL; + LoggedTypesFromModule* pLoggedTypesFromModule = NULL; BOOL fCreatedNew = FALSE; typeLoggingInfo = LookupOrCreateTypeLoggingInfo(th, &fCreatedNew, &pLoggedTypesFromModule); if (typeLoggingInfo.th.IsNull()) @@ -2524,19 +2524,19 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) int nMinAllocPerMSec = typeLoggingInfo.dwAllocCountInCurrentBucket / 16; // This is an underestimation of the true rate. if (delta >= 16 || (nMinAllocPerMSec > 2 && nMinAllocPerMSec > typeLoggingInfo.flAllocPerMSec * 1.5F)) { - float flNewAllocPerMSec = 0; + float flNewAllocPerMSec = 0; if (delta >= 16) { // This is the normal case, our allocation rate is under control with the current throttling. - flNewAllocPerMSec = ((float) typeLoggingInfo.dwAllocCountInCurrentBucket) / delta; + flNewAllocPerMSec = ((float)typeLoggingInfo.dwAllocCountInCurrentBucket) / delta; // Do a exponential decay window that is 5 * max(16, AllocationInterval) - typeLoggingInfo.flAllocPerMSec = 0.8F * typeLoggingInfo.flAllocPerMSec + 0.2F * flNewAllocPerMSec; + typeLoggingInfo.flAllocPerMSec = 0.8F * typeLoggingInfo.flAllocPerMSec + 0.2F * flNewAllocPerMSec; typeLoggingInfo.dwTickOfCurrentTimeBucket = dwTickNow; typeLoggingInfo.dwAllocCountInCurrentBucket = 0; } else { - flNewAllocPerMSec = (float) nMinAllocPerMSec; + flNewAllocPerMSec = (float)nMinAllocPerMSec; // This means the second clause above is true, which means our sampling rate is too low // so we need to throttle quickly. typeLoggingInfo.flAllocPerMSec = flNewAllocPerMSec; @@ -2546,7 +2546,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Obey the desired sampling rate, but don't ignore > 1000 allocations per second // per type int nDesiredMsBetweenEvents = (s_nCustomMsBetweenEvents == 0) ? GetDefaultMsBetweenEvents() : s_nCustomMsBetweenEvents; - typeLoggingInfo.dwAllocsToSkipPerSample = min((int) (typeLoggingInfo.flAllocPerMSec * nDesiredMsBetweenEvents), 1000); + typeLoggingInfo.dwAllocsToSkipPerSample = min((int)(typeLoggingInfo.flAllocPerMSec * nDesiredMsBetweenEvents), 1000); if (typeLoggingInfo.dwAllocsToSkipPerSample == 1) typeLoggingInfo.dwAllocsToSkipPerSample = 0; } @@ -2586,11 +2586,11 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Now log the allocation if (s_fHeapAllocHighEventEnabledNow) { - FireEtwGCSampledObjectAllocationHigh(pObject, (LPVOID) th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); + FireEtwGCSampledObjectAllocationHigh(pObject, (LPVOID)th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); } else { - FireEtwGCSampledObjectAllocationLow(pObject, (LPVOID) th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); + FireEtwGCSampledObjectAllocationLow(pObject, (LPVOID)th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); } } @@ -2603,7 +2603,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // // static -CrstBase * ETW::TypeSystemLog::GetHashCrst() +CrstBase* ETW::TypeSystemLog::GetHashCrst() { LIMITED_METHOD_CONTRACT; return &AllLoggedTypes::s_cs; @@ -2629,7 +2629,7 @@ CrstBase * ETW::TypeSystemLog::GetHashCrst() // // static -void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * pLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior) +void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger* pLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior) { CONTRACTL { @@ -2650,7 +2650,7 @@ void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * p return; } - TypeHandle th = TypeHandle::FromTAddr((TADDR) thAsAddr); + TypeHandle th = TypeHandle::FromTAddr((TADDR)thAsAddr); if (!th.IsRestored()) { return; @@ -2661,11 +2661,11 @@ void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * p // through to the logging code below. If caller doesn't care, then don't even // check; just log the type BOOL fShouldLogType = ((typeLogBehavior == kTypeLogBehaviorAlwaysLog) || - (typeLogBehavior == kTypeLogBehaviorAssumeLockAndAlwaysLogTopLevelType)) ? - TRUE : - ((typeLogBehavior == kTypeLogBehaviorTakeLockAndLogIfFirstTime) ? - ShouldLogType(th) : - ShouldLogTypeNoLock(th)); + (typeLogBehavior == kTypeLogBehaviorAssumeLockAndAlwaysLogTopLevelType)) ? + TRUE : + ((typeLogBehavior == kTypeLogBehaviorTakeLockAndLogIfFirstTime) ? + ShouldLogType(th) : + ShouldLogTypeNoLock(th)); if (!fShouldLogType) return; @@ -2767,7 +2767,7 @@ BOOL ETW::TypeSystemLog::ShouldLogTypeNoLock(TypeHandle th) // // static -ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL * pfCreatedNew, LoggedTypesFromModule ** ppLoggedTypesFromModule /* = NULL */) +ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL* pfCreatedNew, LoggedTypesFromModule** ppLoggedTypesFromModule /* = NULL */) { LIMITED_METHOD_CONTRACT; @@ -2794,9 +2794,9 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl // Step 1: go from LoaderModule to hash of types. - Module * pLoaderModule = th.GetLoaderModule(); + Module* pLoaderModule = th.GetLoaderModule(); _ASSERTE(pLoaderModule != NULL); - LoggedTypesFromModule * pLoggedTypesFromModule = s_pAllLoggedTypes->allLoggedTypesHash.Lookup(pLoaderModule); + LoggedTypesFromModule* pLoggedTypesFromModule = s_pAllLoggedTypes->allLoggedTypesHash.Lookup(pLoaderModule); if (pLoggedTypesFromModule == NULL) { pLoggedTypesFromModule = new (nothrow) LoggedTypesFromModule(pLoaderModule); @@ -2813,7 +2813,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl s_pAllLoggedTypes->allLoggedTypesHash.Add(pLoggedTypesFromModule); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2850,7 +2850,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl pLoggedTypesFromModule->loggedTypesFromModuleHash.Add(typeLoggingInfoNew); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2876,7 +2876,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl // // static -void ETW::TypeSystemLog::OnModuleUnload(Module * pModule) +void ETW::TypeSystemLog::OnModuleUnload(Module* pModule) { CONTRACTL { @@ -2895,7 +2895,7 @@ void ETW::TypeSystemLog::OnModuleUnload(Module * pModule) return; } - LoggedTypesFromModule * pLoggedTypesFromModule = NULL; + LoggedTypesFromModule* pLoggedTypesFromModule = NULL; { CrstHolder _crst(GetHashCrst()); @@ -2943,12 +2943,12 @@ void ETW::TypeSystemLog::OnTypesKeywordTurnedOff() return; // Destruct each of the per-module TypesHashes - AllLoggedTypesHash * pLoggedTypesHash = &s_pAllLoggedTypes->allLoggedTypesHash; + AllLoggedTypesHash* pLoggedTypesHash = &s_pAllLoggedTypes->allLoggedTypesHash; for (AllLoggedTypesHash::Iterator iter = pLoggedTypesHash->Begin(); - iter != pLoggedTypesHash->End(); - ++iter) + iter != pLoggedTypesHash->End(); + ++iter) { - LoggedTypesFromModule * pLoggedTypesFromModule = *iter; + LoggedTypesFromModule* pLoggedTypesFromModule = *iter; delete pLoggedTypesFromModule; } @@ -2962,10 +2962,10 @@ void ETW::TypeSystemLog::OnTypesKeywordTurnedOff() /****************************************************************************/ /* Called when ETW is turned ON on an existing process and ModuleRange events are to be fired */ -/****************************************************************************/ + /****************************************************************************/ void ETW::EnumerationLog::ModuleRangeRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -2978,7 +2978,7 @@ void ETW::EnumerationLog::ModuleRangeRundown() { ETW::EnumerationLog::EnumerationHelper(NULL, NULL, ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -2986,7 +2986,7 @@ void ETW::EnumerationLog::ModuleRangeRundown() /****************************************************************************/ void ETW::EnumerationLog::StartRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -3004,7 +3004,7 @@ void ETW::EnumerationLog::StartRundown() TRACE_LEVEL_INFORMATION, CLR_RUNDOWNTHREADING_KEYWORD); - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD) || @@ -3028,30 +3028,30 @@ void ETW::EnumerationLog::StartRundown() FireEtwDCStartInit_V1(GetClrInstanceId()); // The rundown flag is expected to be checked in the caller, so no need to check here again - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNLOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart; } - if(IsRundownNgenKeywordEnabledAndNotSuppressed()) + if (IsRundownNgenKeywordEnabledAndNotSuppressed()) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJITTEDMETHODILTONATIVEMAP_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::MethodDCStartILToNativeMap; } - if(bIsPerfTrackRundownEnabled) + if (bIsPerfTrackRundownEnabled) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart; } @@ -3076,7 +3076,7 @@ void ETW::EnumerationLog::StartRundown() // end marker event will go to the rundown provider FireEtwDCStartComplete_V1(GetClrInstanceId()); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } //--------------------------------------------------------------------------------------- @@ -3094,26 +3094,26 @@ DWORD ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords() { LIMITED_METHOD_CONTRACT; - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_LOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD) && ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_ENDENUMERATION_KEYWORD)) + TRACE_LEVEL_INFORMATION, + CLR_ENDENUMERATION_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodUnload; } - if(IsRuntimeNgenKeywordEnabledAndNotSuppressed() && + if (IsRuntimeNgenKeywordEnabledAndNotSuppressed() && ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_ENDENUMERATION_KEYWORD)) + TRACE_LEVEL_INFORMATION, + CLR_ENDENUMERATION_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload; } @@ -3149,7 +3149,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); @@ -3165,7 +3165,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() SendThreadRundownEvent(); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**************************************************************************************/ @@ -3173,7 +3173,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() /**************************************************************************************/ void ETW::EnumerationLog::EndRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -3187,7 +3187,7 @@ void ETW::EnumerationLog::EndRundown() MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNTHREADING_KEYWORD); - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD) || @@ -3210,30 +3210,30 @@ void ETW::EnumerationLog::EndRundown() FireEtwDCEndInit_V1(GetClrInstanceId()); // The rundown flag is expected to be checked in the caller, so no need to check here again - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNLOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd; } - if(IsRundownNgenKeywordEnabledAndNotSuppressed()) + if (IsRundownNgenKeywordEnabledAndNotSuppressed()) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJITTEDMETHODILTONATIVEMAP_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap; } - if(bIsPerfTrackRundownEnabled) + if (bIsPerfTrackRundownEnabled) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd; } @@ -3248,7 +3248,7 @@ void ETW::EnumerationLog::EndRundown() // end marker event will go to the rundown provider FireEtwDCEndComplete_V1(GetClrInstanceId()); } - } EX_CATCH { + } EX_CATCH{ STRESS_LOG1(LF_ALWAYS, LL_ERROR, "Exception during Rundown Enumeration, EIP of last AV = %p", g_LastAccessViolationEIP); } EX_END_CATCH(SwallowAllExceptions); } @@ -3290,9 +3290,9 @@ void InitializeEventTracing() // Register CLR providers with the OS if (g_pEtwTracer == NULL) { - NewHolder tempEtwTracer (new (nothrow) ETW::CEtwTracer()); - if (tempEtwTracer != NULL && tempEtwTracer->Register () == ERROR_SUCCESS) - g_pEtwTracer = tempEtwTracer.Extract (); + NewHolder tempEtwTracer(new (nothrow) ETW::CEtwTracer()); + if (tempEtwTracer != NULL && tempEtwTracer->Register() == ERROR_SUCCESS) + g_pEtwTracer = tempEtwTracer.Extract(); } g_nClrInstanceId = GetRuntimeId() & 0x0000FFFF; // This will give us duplicate ClrInstanceId after UINT16_MAX @@ -3375,37 +3375,44 @@ HRESULT ETW::CEtwTracer::UnRegister() extern "C" { ETW_INLINE - void EtwCallout(REGHANDLE RegHandle, - PCEVENT_DESCRIPTOR Descriptor, - ULONG ArgumentCount, - PEVENT_DATA_DESCRIPTOR EventData) + void EtwCallout(REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR Descriptor, + ULONG ArgumentCount, + PEVENT_DATA_DESCRIPTOR EventData) { WRAPPER_NO_CONTRACT; UINT8 providerIndex = 0; - if(RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { + if (RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { providerIndex = 0; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { providerIndex = 1; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { providerIndex = 2; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { providerIndex = 3; - } else { + } + else { _ASSERTE(!"Provider not one of Runtime, Rundown, Private and Stress"); return; } // stacks are supposed to be fired for only the events with a bit set in the etwStackSupportedEvents bitmap - if(((etwStackSupportedEvents[providerIndex][Descriptor->Id/8]) & - (1<<(Descriptor->Id%8))) != 0) + if (((etwStackSupportedEvents[providerIndex][Descriptor->Id / 8]) & + (1 << (Descriptor->Id % 8))) != 0) { - if(RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { + if (RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, &CLRStackWalk, &CLRStackId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, &CLRStackWalkDCStart, &CLRStackRundownId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, &CLRStackWalkPrivate, &CLRStackPrivateId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_Context, &CLRStackWalkStress, &CLRStackStressId); } } @@ -3430,22 +3437,23 @@ extern "C" // action in this class, we pass "this" during provider registration and modify the // context to the relevant context in the C callback later. ETW_INLINE - void EtwCallback( - _In_ LPCGUID SourceId, - _In_ ULONG ControlCode, - _In_ UCHAR Level, - _In_ ULONGLONG MatchAnyKeyword, - _In_ ULONGLONG MatchAllKeyword, - _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, - _Inout_opt_ PVOID CallbackContext) - { - CONTRACTL { + void EtwCallback( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext) + { + CONTRACTL{ NOTHROW; - if(g_fEEStarted) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}; - MODE_ANY; - CAN_TAKE_LOCK; - STATIC_CONTRACT_FAULT; - SO_NOT_MAINLINE; + if (g_fEEStarted) { GC_TRIGGERS; } + else { DISABLED(GC_NOTRIGGER); }; +MODE_ANY; +CAN_TAKE_LOCK; +STATIC_CONTRACT_FAULT; +SO_NOT_MAINLINE; } CONTRACTL_END; // Mark that we are the special ETWRundown thread. Currently all this does @@ -3459,21 +3467,21 @@ extern "C" BOOLEAN bIsPublicTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimeHandle); BOOLEAN bIsPrivateTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimePrivateHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimePrivateHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimePrivateHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimePrivateHandle); BOOLEAN bIsRundownTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeRundownHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeRundownHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeRundownHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimeRundownHandle); // A manifest based provider can be enabled to multiple event tracing sessions @@ -3482,8 +3490,8 @@ extern "C" // IsEnabled will be TRUE when it is enabled and FALSE when disabled BOOL bEnabled = ((ControlCode == EVENT_CONTROL_CODE_ENABLE_PROVIDER) || - (ControlCode == EVENT_CONTROL_CODE_CAPTURE_STATE)); - if(bEnabled) + (ControlCode == EVENT_CONTROL_CODE_CAPTURE_STATE)); + if (bEnabled) { // TypeSystemLog needs a notification when certain keywords are modified, so // give it a hook here. @@ -3495,7 +3503,7 @@ extern "C" if (bIsPrivateTraceHandle) { ETW::GCLog::GCSettingsEvent(); - if(g_fEEStarted && !g_fEEShutDown) + if (g_fEEStarted && !g_fEEShutDown) { ETW::EnumerationLog::ModuleRangeRundown(); } @@ -3505,10 +3513,10 @@ extern "C" // If we have turned on the JIT keyword to the VERBOSE setting (needed to get JIT names) then // we assume that we also want good stack traces so we need to publish unwind information so // ETW can get at it - if(bIsPublicTraceHandle && ETW_CATEGORY_ENABLED((*context), TRACE_LEVEL_VERBOSE, CLR_RUNDOWNJIT_KEYWORD)) + if (bIsPublicTraceHandle && ETW_CATEGORY_ENABLED((*context), TRACE_LEVEL_VERBOSE, CLR_RUNDOWNJIT_KEYWORD)) UnwindInfoTable::PublishUnwindInfo(g_fEEStarted != FALSE); #endif - if(g_fEEStarted && !g_fEEShutDown && bIsRundownTraceHandle) + if (g_fEEStarted && !g_fEEShutDown && bIsRundownTraceHandle) { // Fire the runtime information event ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Callback); @@ -3516,15 +3524,15 @@ extern "C" // Start and End Method/Module Rundowns // Used to fire events that we missed since we started the controller after the process started // flags for immediate start rundown - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNSTART_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNSTART_KEYWORD)) ETW::EnumerationLog::StartRundown(); // flags delayed end rundown - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNEND_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNEND_KEYWORD)) ETW::EnumerationLog::EndRundown(); } @@ -3545,7 +3553,7 @@ extern "C" (FilterData->Type == 1) && (FilterData->Size == sizeof(l64ClientSequenceNumber))) { - l64ClientSequenceNumber = *(LONGLONG *) (FilterData->Ptr); + l64ClientSequenceNumber = *(LONGLONG*)(FilterData->Ptr); } ETW::GCLog::ForceGC(l64ClientSequenceNumber); } @@ -3566,7 +3574,7 @@ extern "C" /* in its printf API, we cast the unicode string to UFT8 string and then output them. */ /**************************************************************************************/ #define DTRACE_OUTPUT_STRING_LEN 512 -const CHAR szDtraceOutputNULL[]="NULL"; +const CHAR szDtraceOutputNULL[] = "NULL"; INT32 WideCharToMultiByte(LPCWSTR wszSrcStr, LPSTR szDstStr); #include @@ -3586,7 +3594,7 @@ ULONG ETW::CEtwTracer::Register() // Get Env Var COMPlus_ETWEnabled char szETWEnabled[SIZE_ETWEnabled]; DWORD newLen = GetEnvironmentVariableA("COMPlus_ETWEnabled", szETWEnabled, SIZE_ETWEnabled); - if (newLen == 0 || newLen >= SIZE_ETWEnabled || strcmp(szETWEnabled, "1") != 0) + if (newLen == 0 || newLen >= SIZE_ETWEnabled || strcmp(szETWEnabled, "1") != 0) return 0; // Get Env Var COMPlus_EventInfo @@ -3621,12 +3629,12 @@ INT32 WideCharToMultiByte(LPCWSTR wszSrcStr, LPSTR szDstStr) { return 0; } - if (nSize > DTRACE_OUTPUT_STRING_LEN-1) + if (nSize > DTRACE_OUTPUT_STRING_LEN - 1) { - nSize = DTRACE_OUTPUT_STRING_LEN-1; + nSize = DTRACE_OUTPUT_STRING_LEN - 1; } - INT32 nSize2 = WideCharToMultiByte(CP_UTF8, 0, wszSrcStr, -1, szDstStr, nSize, NULL, NULL); - if(nSize2 != nSize || nSize2 <=0 ) + INT32 nSize2 = WideCharToMultiByte(CP_UTF8, 0, wszSrcStr, -1, szDstStr, nSize, NULL, NULL); + if (nSize2 != nSize || nSize2 <= 0) { return 0; } @@ -3801,20 +3809,20 @@ void SecurityCatchCallEnd_V1() /****************************************************************************/ /* This is called by the runtime when an exception is thrown */ /****************************************************************************/ -void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) +void ETW::ExceptionLog::ExceptionThrown(CrawlFrame* pCf, BOOL bIsReThrownException, BOOL bIsNewException) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(GetThread() != NULL); PRECONDITION(GetThread()->GetThrowable() != NULL); } CONTRACTL_END; - if(!(bIsReThrownException || bIsNewException)) + if (!(bIsReThrownException || bIsNewException)) { return; } - if(!ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ExceptionThrown_V1)) + if (!ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ExceptionThrown_V1)) { return; } @@ -3822,11 +3830,11 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept { SString exceptionType(L""); LPWSTR exceptionMessage = NULL; - BOOL bIsCLSCompliant=FALSE, bIsCSE=FALSE, bIsNestedException=FALSE, bHasInnerException=FALSE; - UINT16 exceptionFlags=0; - PVOID exceptionEIP=0; + BOOL bIsCLSCompliant = FALSE, bIsCSE = FALSE, bIsNestedException = FALSE, bHasInnerException = FALSE; + UINT16 exceptionFlags = 0; + PVOID exceptionEIP = 0; - Thread *pThread = GetThread(); + Thread* pThread = GetThread(); struct { @@ -3840,7 +3848,7 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept gc.exceptionObj = pThread->GetThrowable(); gc.innerExceptionObj = ((EXCEPTIONREF)gc.exceptionObj)->GetInnerException(); - ThreadExceptionState *pExState = pThread->GetExceptionState(); + ThreadExceptionState* pExState = pThread->GetExceptionState(); #ifndef WIN64EXCEPTIONS PTR_ExInfo pExInfo = NULL; #else @@ -3855,7 +3863,7 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept // A rethrown exception is also a nested exception // but since we have a separate flag for it, lets unset the nested flag - if(bIsReThrownException) + if (bIsReThrownException) { bIsNestedException = FALSE; } @@ -3887,12 +3895,12 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept exceptionEIP = (PVOID)((UINT_PTR)exceptionEIP - 1); } - gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); + gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); TypeHandle exceptionTypeHandle = (gc.exceptionObj)->GetTypeHandle(); exceptionTypeHandle.GetName(exceptionType); - WCHAR *exceptionTypeName = (WCHAR *)exceptionType.GetUnicode(); + WCHAR* exceptionTypeName = (WCHAR*)exceptionType.GetUnicode(); - if(gc.exceptionMessageRef != NULL) + if (gc.exceptionMessageRef != NULL) { exceptionMessage = (gc.exceptionMessageRef)->GetBuffer(); } @@ -3906,53 +3914,53 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept exceptionFlags, GetClrInstanceId()); GCPROTECT_END(); - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when a domain is loaded */ /****************************************************************************/ -void ETW::LoaderLog::DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName) +void ETW::LoaderLog::DomainLoadReal(BaseDomain* pDomain, _In_opt_ LPWSTR wszFriendlyName) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_LOADER_KEYWORD)) { DWORD dwEventOptions = ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad; ETW::LoaderLog::SendDomainEvent(pDomain, dwEventOptions, wszFriendlyName); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when an AppDomain is unloaded */ /****************************************************************************/ -void ETW::LoaderLog::DomainUnload(AppDomain *pDomain) +void ETW::LoaderLog::DomainUnload(AppDomain* pDomain) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { - if(!pDomain->NoAccessToHandleTable()) + if (!pDomain->NoAccessToHandleTable()) { DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords(); // Domain unload also causes type unload events - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_TYPE_KEYWORD)) { @@ -3962,29 +3970,29 @@ void ETW::LoaderLog::DomainUnload(AppDomain *pDomain) ETW::EnumerationLog::EnumerationHelper(NULL, pDomain, enumerationOptions); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when a LoaderAllocator is unloaded */ /****************************************************************************/ -void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) +void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator* pLoaderAllocator) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords(); // Collectible Loader Allocator unload also causes type unload events - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_TYPE_KEYWORD)) { @@ -3993,23 +4001,23 @@ void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *p ETW::EnumerationLog::IterateCollectibleLoaderAllocator(pLoaderAllocator, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when the runtime is loaded Function gets called by both the Callback mechanism and regular ETW events. Type is used to differentiate whether its a callback or a normal call*/ -/****************************************************************************/ + /****************************************************************************/ void ETW::InfoLog::RuntimeInformation(INT32 type) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; - EX_TRY { - if((type == ETW::InfoLog::InfoStructs::Normal && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, RuntimeInformationStart)) + EX_TRY{ + if ((type == ETW::InfoLog::InfoStructs::Normal && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, RuntimeInformationStart)) #ifndef FEATURE_PAL || (type == ETW::InfoLog::InfoStructs::Callback && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, RuntimeInformationDCStart)) @@ -4017,21 +4025,21 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) ) { #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L""; + PCWSTR szDtraceOutput1 = L"",szDtraceOutput2 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE UINT8 startupMode = 0; UINT startupFlags = 0; - WCHAR dllPath[MAX_PATH+1] = {0}; + WCHAR dllPath[MAX_PATH + 1] = {0}; UINT8 Sku = 0; _ASSERTE(g_fEEManagedEXEStartup || //CLR started due to a managed exe g_fEEIJWStartup || //CLR started as a mixed mode Assembly CLRHosted() || g_fEEHostedStartup || //CLR started through one of the Hosting API CLRHosted() returns true if CLR started through the V2 Interface while // g_fEEHostedStartup is true if CLR is hosted through the V1 API. g_fEEComActivatedStartup || //CLR started as a COM object - g_fEEOtherStartup ); //In case none of the 4 above mentioned cases are true for example ngen, ildasm then we asssume its a "other" startup + g_fEEOtherStartup); //In case none of the 4 above mentioned cases are true for example ngen, ildasm then we asssume its a "other" startup #ifdef FEATURE_CORECLR Sku = ETW::InfoLog::InfoStructs::CoreCLR; @@ -4052,9 +4060,9 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) USHORT bclQfeVersion = VER_ASSEMBLYBUILD_QFE; #ifndef FEATURE_PAL - LPCGUID comGUID=g_fEEComObjectGuid; + LPCGUID comGUID = g_fEEComObjectGuid; #else - unsigned int comGUID=0; + unsigned int comGUID = 0; #endif //!FEATURE_PAL #ifndef FEATURE_DTRACE @@ -4070,12 +4078,12 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) #endif //!FEATURE_CORECLR // Determine the startupmode - if(g_fEEIJWStartup) + if (g_fEEIJWStartup) { //IJW Mode startupMode = ETW::InfoLog::InfoStructs::IJW; } - else if(g_fEEManagedEXEStartup) + else if (g_fEEManagedEXEStartup) { //managed exe startupMode = ETW::InfoLog::InfoStructs::ManagedExe; @@ -4083,7 +4091,7 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) lpwszCommandLine = WszGetCommandLine(); #else INT32 nSize = WideCharToMultiByte(WszGetCommandLine(), szDtraceOutput1); - if(nSize > 0) { + if (nSize > 0) { lpwszCommandLine = (SIZE_T)szDtraceOutput1; } #endif //!FEATURE_DTRACE @@ -4093,34 +4101,34 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) //Hosted CLR startupMode = ETW::InfoLog::InfoStructs::HostedCLR; } - else if(g_fEEComActivatedStartup) + else if (g_fEEComActivatedStartup) { //com activated startupMode = ETW::InfoLog::InfoStructs::COMActivated; } - else if(g_fEEOtherStartup) + else if (g_fEEOtherStartup) { //startup type is other startupMode = ETW::InfoLog::InfoStructs::Other; } - _ASSERTE (NumItems(dllPath) > MAX_PATH); + _ASSERTE(NumItems(dllPath) > MAX_PATH); // if WszGetModuleFileName fails, we return an empty string if (!WszGetModuleFileName(GetCLRModule(), dllPath, MAX_PATH)) { dllPath[0] = 0; } dllPath[MAX_PATH] = 0; #ifdef FEATURE_DTRACE - _ASSERTE (NumItems(szDtraceOutput2) >= NumItems(dllPath)); + _ASSERTE(NumItems(szDtraceOutput2) >= NumItems(dllPath)); INT32 nSize = WideCharToMultiByte(dllPath, szDtraceOutput2); - if(nSize > 0) { + if (nSize > 0) { lpwszRuntimeDllPath = (SIZE_T)szDtraceOutput2; } #endif // FEATURE_DTRACE - if(type == ETW::InfoLog::InfoStructs::Callback) + if (type == ETW::InfoLog::InfoStructs::Callback) { - FireEtwRuntimeInformationDCStart( GetClrInstanceId(), + FireEtwRuntimeInformationDCStart(GetClrInstanceId(), Sku, bclMajorVersion, bclMinorVersion, @@ -4134,11 +4142,11 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) startupMode, lpwszCommandLine, comGUID, - lpwszRuntimeDllPath ); + lpwszRuntimeDllPath); } else { - FireEtwRuntimeInformationStart( GetClrInstanceId(), + FireEtwRuntimeInformationStart(GetClrInstanceId(), Sku, bclMajorVersion, bclMinorVersion, @@ -4152,32 +4160,32 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) startupMode, lpwszCommandLine, comGUID, - lpwszRuntimeDllPath ); + lpwszRuntimeDllPath); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /*******************************************************/ /* This is called by the runtime when a method is jitted completely */ /*******************************************************/ -void ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +void ETW::MethodLog::MethodJitted(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature, SIZE_T pCode, ReJITID rejitID) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD)) { ETW::MethodLog::SendMethodEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodLoad, TRUE, namespaceOrClassName, methodName, methodSignature, pCode, rejitID); } #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JITTEDMETHODILTONATIVEMAP_KEYWORD)) { @@ -4192,15 +4200,15 @@ void ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC ETW::MethodLog::SendMethodILToNativeMapEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodILToNativeMap, rejitID); } #endif // WINXP_AND_WIN2K3_BUILD_SUPPORT - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /*************************************************/ /* This is called by the runtime when method jitting started */ /*************************************************/ -void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +void ETW::MethodLog::MethodJitting(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(pMethodDesc != NULL); @@ -4208,14 +4216,14 @@ void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_VERBOSE, CLR_JIT_KEYWORD)) { pMethodDesc->GetMethodInfo(*namespaceOrClassName, *methodName, *methodSignature); ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, namespaceOrClassName, methodName, methodSignature); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**********************************************************************/ @@ -4223,7 +4231,7 @@ void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr /**********************************************************************/ void ETW::MethodLog::StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(ullHelperStartAddress != 0); @@ -4231,31 +4239,31 @@ void ETW::MethodLog::StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pH EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD)) { - DWORD dwHelperSize=0; + DWORD dwHelperSize = 0; Stub::RecoverStubAndSize((TADDR)ullHelperStartAddress, &dwHelperSize); ETW::MethodLog::SendHelperEvent(ullHelperStartAddress, dwHelperSize, pHelperName); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**********************************************************/ /* This is called by the runtime when helpers with stubs are initialized */ /**********************************************************/ -void ETW::MethodLog::StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG lNoOfHelpers) +void ETW::MethodLog::StubsInitialized(PVOID* pHelperStartAddresss, PVOID* pHelperNames, LONG lNoOfHelpers) { WRAPPER_NO_CONTRACT; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_JIT_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_JIT_KEYWORD)) { - for(int i=0; iIsThunking()) + if (!pMethodTable->IsThunking()) #endif { MethodTable::MethodIterator iter(pMethodTable); for (; iter.IsValid(); iter.Next()) { - MethodDesc *pMD = (MethodDesc *)(iter.GetMethodDesc()); - if(pMD && pMD->IsRestored() && pMD->GetMethodTable_NoLogging() == pMethodTable) + MethodDesc* pMD = (MethodDesc*)(iter.GetMethodDesc()); + if (pMD && pMD->IsRestored() && pMD->GetMethodTable_NoLogging() == pMethodTable) ETW::MethodLog::SendMethodEvent(pMD, ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad, FALSE); } } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } @@ -4362,7 +4370,7 @@ void ETW::SecurityLog::StrongNameVerificationStart(DWORD dwInFlags, _In_ LPWSTR /****************************************************************************/ /* This is called by the runtime when a Strong Name Verification Ends */ /****************************************************************************/ -void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_ LPWSTR strFullyQualifiedAssemblyName) +void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags, ULONG result, _In_ LPWSTR strFullyQualifiedAssemblyName) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_CORECLR @@ -4382,8 +4390,8 @@ void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags,ULONG result, /* This is called by the runtime when field transparency calculations begin */ /****************************************************************************/ void ETW::SecurityLog::FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4404,10 +4412,10 @@ void ETW::SecurityLog::FireFieldTransparencyComputationStart(LPCWSTR wszFieldNam /* This is called by the runtime when field transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4428,8 +4436,8 @@ void ETW::SecurityLog::FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, /* This is called by the runtime when method transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4450,10 +4458,10 @@ void ETW::SecurityLog::FireMethodTransparencyComputationStart(LPCWSTR wszMethodN /* This is called by the runtime when method transparency calculations end */ /********************************************(********************************/ void ETW::SecurityLog::FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4474,7 +4482,7 @@ void ETW::SecurityLog::FireMethodTransparencyComputationEnd(LPCWSTR wszMethodNam /* This is called by the runtime when module transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, - DWORD dwAppDomain) + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4493,12 +4501,12 @@ void ETW::SecurityLog::FireModuleTransparencyComputationStart(LPCWSTR wszModuleN /* This is called by the runtime when module transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsAllCritical, - BOOL fIsAllTransparent, - BOOL fIsTreatAsSafe, - BOOL fIsOpportunisticallyCritical, - DWORD dwSecurityRuleSet) + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4517,8 +4525,8 @@ void ETW::SecurityLog::FireModuleTransparencyComputationEnd(LPCWSTR wszModuleNam /* This is called by the runtime when token transparency calculations begin */ /****************************************************************************/ void ETW::SecurityLog::FireTokenTransparencyComputationStart(DWORD dwToken, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4537,10 +4545,10 @@ void ETW::SecurityLog::FireTokenTransparencyComputationStart(DWORD dwToken, /* This is called by the runtime when token transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireTokenTransparencyComputationEnd(DWORD dwToken, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4559,8 +4567,8 @@ void ETW::SecurityLog::FireTokenTransparencyComputationEnd(DWORD dwToken, /* This is called by the runtime when type transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4581,12 +4589,12 @@ void ETW::SecurityLog::FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, /* This is called by the runtime when type transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsAllCritical, - BOOL fIsAllTransparent, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4607,9 +4615,9 @@ void ETW::SecurityLog::FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, /* This is called by the runtime when a module is loaded */ /* liReportedSharedModule will be 0 when this module is reported for the 1st time */ /**********************************************************************************/ -void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) +void ETW::LoaderLog::ModuleLoad(Module* pModule, LONG liReportedSharedModule) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -4617,7 +4625,7 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) EX_TRY { DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { @@ -4632,27 +4640,27 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) TRACE_LEVEL_INFORMATION, CLR_PERFTRACK_KEYWORD); - if(liReportedSharedModule == 0) + if (liReportedSharedModule == 0) { - if(bTraceFlagLoaderSet) + if (bTraceFlagLoaderSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad; if (bTraceFlagPerfTrackSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad; - if(bTraceFlagNgenMethodSet && bTraceFlagStartRundownSet) + if (bTraceFlagNgenMethodSet && bTraceFlagStartRundownSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad; - if(pModule->IsManifest() && bTraceFlagLoaderSet) + if (pModule->IsManifest() && bTraceFlagLoaderSet) ETW::LoaderLog::SendAssemblyEvent(pModule->GetAssembly(), enumerationOptions); - if(bTraceFlagLoaderSet || bTraceFlagPerfTrackSet) + if (bTraceFlagLoaderSet || bTraceFlagPerfTrackSet) ETW::LoaderLog::SendModuleEvent(pModule, ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad | ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad); ETW::EnumerationLog::EnumerationHelper(pModule, NULL, enumerationOptions); } // we want to report domainmodule events whenever they are loaded in any AppDomain - if(bTraceFlagLoaderSet) + if (bTraceFlagLoaderSet) ETW::LoaderLog::SendModuleEvent(pModule, ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad, TRUE); } @@ -4668,7 +4676,7 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) } } #endif - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -4676,14 +4684,14 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) /****************************************************************************/ void ETW::EnumerationLog::ProcessShutdown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); @@ -4691,7 +4699,7 @@ void ETW::EnumerationLog::ProcessShutdown() // default domain. ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, NULL /* domain filter */, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -4703,18 +4711,18 @@ void ETW::EnumerationLog::ProcessShutdown() /****************************************************************************/ /* This routine is used to send a domain load/unload or rundown event */ /****************************************************************************/ -void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName) +void ETW::LoaderLog::SendDomainEvent(BaseDomain* pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pBaseDomain) + if (!pBaseDomain) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE @@ -4722,22 +4730,22 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio BOOL bIsAppDomain = pBaseDomain->IsAppDomain(); BOOL bIsExecutable = bIsAppDomain ? !(pBaseDomain->AsAppDomain()->IsPassiveDomain()) : FALSE; BOOL bIsSharedDomain = pBaseDomain->IsSharedDomain(); - UINT32 uSharingPolicy = bIsAppDomain?(pBaseDomain->AsAppDomain()->GetSharePolicy()):0; + UINT32 uSharingPolicy = bIsAppDomain ? (pBaseDomain->AsAppDomain()->GetSharePolicy()) : 0; ULONGLONG ullDomainId = (ULONGLONG)pBaseDomain; ULONG ulDomainFlags = ((bIsDefaultDomain ? ETW::LoaderLog::LoaderStructs::DefaultDomain : 0) | - (bIsExecutable ? ETW::LoaderLog::LoaderStructs::ExecutableDomain : 0) | - (bIsSharedDomain ? ETW::LoaderLog::LoaderStructs::SharedDomain : 0) | - (uSharingPolicy<<28)); + (bIsExecutable ? ETW::LoaderLog::LoaderStructs::ExecutableDomain : 0) | + (bIsSharedDomain ? ETW::LoaderLog::LoaderStructs::SharedDomain : 0) | + (uSharingPolicy << 28)); LPCWSTR wsEmptyString = L""; LPCWSTR wsSharedString = L"SharedDomain"; LPWSTR lpswzDomainName = (LPWSTR)wsEmptyString; - if(bIsAppDomain) + if (bIsAppDomain) { - if(wszFriendlyName) + if (wszFriendlyName) lpswzDomainName = (PWCHAR)wszFriendlyName; else lpswzDomainName = (PWCHAR)pBaseDomain->AsAppDomain()->GetFriendlyName(); @@ -4755,28 +4763,28 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio return; #endif // !FEATURE_DTRACE - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwAppDomainLoad_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwAppDomainUnload_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwAppDomainDCStart_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwAppDomainDCEnd_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } @@ -4785,13 +4793,13 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio /********************************************************/ void ETW::EnumerationLog::SendThreadRundownEvent() { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; #ifndef DACCESS_COMPILE - Thread *pThread = NULL; + Thread* pThread = NULL; // Take the thread store lock while we enumerate threads. ThreadStoreLockHolder tsl; @@ -4811,24 +4819,24 @@ void ETW::EnumerationLog::SendThreadRundownEvent() /****************************************************************************/ /* This routine is used to send an assembly load/unload or rundown event ****/ /****************************************************************************/ -void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions) +void ETW::LoaderLog::SendAssemblyEvent(Assembly* pAssembly, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pAssembly) + if (!pAssembly) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE BOOL bIsDynamicAssembly = pAssembly->IsDynamic(); BOOL bIsCollectibleAssembly = pAssembly->IsCollectible(); - BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral() ; + BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); BOOL bHasNativeImage = pAssembly->GetManifestFile()->HasNativeImage(); ULONGLONG ullAssemblyId = (ULONGLONG)pAssembly; @@ -4838,15 +4846,15 @@ void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions ullBindingID = pAssembly->GetManifestFile()->GetBindingID(); #endif ULONG ulAssemblyFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralAssembly : 0) | - (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicAssembly : 0) | - (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeAssembly : 0) | - (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0)); + (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicAssembly : 0) | + (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeAssembly : 0) | + (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0)); SString sAssemblyPath; pAssembly->GetDisplayName(sAssemblyPath); LPWSTR lpszAssemblyPath = (LPWSTR)sAssemblyPath.GetUnicode(); -/* prepare events args for ETW and ETM */ + /* prepare events args for ETW and ETM */ #ifndef FEATURE_DTRACE szDtraceOutput1 = (PCWSTR)lpszAssemblyPath; #else // !FEATURE_DTRACE @@ -4856,36 +4864,36 @@ void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions return; #endif // !FEATURE_DTRACE - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwAssemblyLoad_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwAssemblyUnload_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwAssemblyDCStart_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwAssemblyDCEnd_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } #if !defined(FEATURE_PAL) ETW_INLINE - ULONG - ETW::LoaderLog::SendModuleRange( - _In_ Module *pModule, +ULONG +ETW::LoaderLog::SendModuleRange( + _In_ Module* pModule, _In_ DWORD dwEventOptions) { @@ -4895,22 +4903,22 @@ ETW_INLINE // do not fire the ETW event when: // 1. We did not load the native image // 2. We do not have IBC data for the native image - if( !pModule || !pModule->HasNativeImage() || !pModule->IsIbcOptimized() ) + if (!pModule || !pModule->HasNativeImage() || !pModule->IsIbcOptimized()) { return Result; } // get information about the hot sections from the native image that has been loaded COUNT_T cbSizeOfSectionTable; - CORCOMPILE_VIRTUAL_SECTION_INFO* pVirtualSectionsTable = (CORCOMPILE_VIRTUAL_SECTION_INFO* )pModule->GetNativeImage()->GetVirtualSectionsTable(&cbSizeOfSectionTable); + CORCOMPILE_VIRTUAL_SECTION_INFO* pVirtualSectionsTable = (CORCOMPILE_VIRTUAL_SECTION_INFO*)pModule->GetNativeImage()->GetVirtualSectionsTable(&cbSizeOfSectionTable); - COUNT_T RangeCount = cbSizeOfSectionTable/sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); + COUNT_T RangeCount = cbSizeOfSectionTable / sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); // if we do not have any hot ranges, we do not fire the ETW event // Figure out the rest of the event data UINT16 ClrInstanceId = GetClrInstanceId(); - UINT64 ModuleID = (ULONGLONG)(TADDR) pModule; + UINT64 ModuleID = (ULONGLONG)(TADDR)pModule; for (COUNT_T i = 0; i < RangeCount; ++i) { @@ -4972,13 +4980,13 @@ ETW_INLINE // untrusted, and reported sizes of buffers are verified against their data. // -static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO_PDB70 * pCvInfoNative) +static void GetCodeViewInfo(Module* pModule, CV_INFO_PDB70* pCvInfoIL, CV_INFO_PDB70* pCvInfoNative) { LIMITED_METHOD_CONTRACT; - _ASSERTE (pModule != NULL); - _ASSERTE (pCvInfoIL != NULL); - _ASSERTE (pCvInfoNative != NULL); + _ASSERTE(pModule != NULL); + _ASSERTE(pCvInfoIL != NULL); + _ASSERTE(pCvInfoNative != NULL); ZeroMemory(pCvInfoIL, sizeof(*pCvInfoIL)); ZeroMemory(pCvInfoNative, sizeof(*pCvInfoNative)); @@ -5013,8 +5021,8 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO return; COUNT_T cbDebugEntries; - IMAGE_DEBUG_DIRECTORY * rgDebugEntries = - (IMAGE_DEBUG_DIRECTORY *) pLayout->GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &cbDebugEntries); + IMAGE_DEBUG_DIRECTORY* rgDebugEntries = + (IMAGE_DEBUG_DIRECTORY*)pLayout->GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &cbDebugEntries); if (cbDebugEntries < sizeof(IMAGE_DEBUG_DIRECTORY)) return; @@ -5028,15 +5036,15 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO // sizeof(CV_INFO_PDB70); see below). struct PdbInfo { - CV_INFO_PDB70 * m_pPdb70; + CV_INFO_PDB70* m_pPdb70; ULONG m_cbPdb70; }; // Iterate through all debug directory entries. The very last one will be the // managed PDB entry. The next to last one (if it exists) will be the (native) NGEN // PDB entry. Treat raw bytes we read as untrusted. - PdbInfo pdbInfoLast = {0}; - PdbInfo pdbInfoNextToLast = {0}; + PdbInfo pdbInfoLast = { 0 }; + PdbInfo pdbInfoNextToLast = { 0 }; int cEntries = cbDebugEntries / sizeof(IMAGE_DEBUG_DIRECTORY); for (int i = 0; i < cEntries; i++) { @@ -5068,7 +5076,7 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO } // Verify the magic number is as expected - CV_INFO_PDB70 * pPdb70 = (CV_INFO_PDB70 *) pLayout->GetRvaData(rvaOfRawData); + CV_INFO_PDB70* pPdb70 = (CV_INFO_PDB70*)pLayout->GetRvaData(rvaOfRawData); if (pPdb70->magic != CV_SIGNATURE_RSDS) { // Unrecognized magic number. Skip @@ -5143,18 +5151,18 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO // * bFireDomainModuleEvents - nonzero if we are to fire DomainModule events; zero // if we are to fire Module events // -void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents) +void ETW::LoaderLog::SendModuleEvent(Module* pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pModule) + if (!pModule) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; @@ -5166,35 +5174,35 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL #endif // FEATURE_PREJIT BOOL bIsManifestModule = pModule->IsManifest(); ULONGLONG ullAppDomainId = 0; // This is used only with DomainModule events - ULONGLONG ullModuleId = (ULONGLONG)(TADDR) pModule; + ULONGLONG ullModuleId = (ULONGLONG)(TADDR)pModule; ULONGLONG ullAssemblyId = (ULONGLONG)pModule->GetAssembly(); BOOL bIsDomainNeutral = pModule->GetAssembly()->IsDomainNeutral(); BOOL bIsIbcOptimized = FALSE; - if(bHasNativeImage) + if (bHasNativeImage) { bIsIbcOptimized = pModule->IsIbcOptimized(); } ULONG ulReservedFlags = 0; ULONG ulFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralModule : 0) | - (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeModule : 0) | - (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicModule : 0) | - (bIsManifestModule ? ETW::LoaderLog::LoaderStructs::ManifestModule : 0) | - (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0)); + (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeModule : 0) | + (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicModule : 0) | + (bIsManifestModule ? ETW::LoaderLog::LoaderStructs::ManifestModule : 0) | + (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0)); #ifndef FEATURE_DTRACE // Grab PDB path, guid, and age for managed PDB and native (NGEN) PDB when // available. Any failures are not fatal. The corresponding PDB info will remain // zeroed out, and that's what we'll include in the event. - CV_INFO_PDB70 cvInfoIL = {0}; - CV_INFO_PDB70 cvInfoNative = {0}; + CV_INFO_PDB70 cvInfoIL = { 0 }; + CV_INFO_PDB70 cvInfoNative = { 0 }; GetCodeViewInfo(pModule, &cvInfoIL, &cvInfoNative); #endif // FEATURE_DTRACE - PWCHAR ModuleILPath=L"", ModuleNativePath=L""; + PWCHAR ModuleILPath = L"", ModuleNativePath = L""; - if(bFireDomainModuleEvents) + if (bFireDomainModuleEvents) { - if(pModule->GetDomain()->IsSharedDomain()) // for shared domains, we do not fire domainmodule event + if (pModule->GetDomain()->IsSharedDomain()) // for shared domains, we do not fire domainmodule event return; ullAppDomainId = (ULONGLONG)pModule->FindDomainAssembly(pModule->GetDomain()->AsAppDomain())->GetAppDomain(); } @@ -5205,19 +5213,19 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL #else // !FEATURE_PAL SString moduleName; #endif // !FEATURE_PAL - if(!bIsDynamicAssembly) + if (!bIsDynamicAssembly) { ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetILimage()->GetPath().GetUnicode(); ModuleNativePath = (PWCHAR)pEmptyString; #ifdef FEATURE_PREJIT - if(bHasNativeImage) + if (bHasNativeImage) ModuleNativePath = (PWCHAR)pModule->GetNativeImage()->GetPath().GetUnicode(); #endif // FEATURE_PREJIT } // if we do not have a module path yet, we put the module name - if(bIsDynamicAssembly || ModuleILPath==NULL || wcslen(ModuleILPath) <= 2) + if (bIsDynamicAssembly || ModuleILPath == NULL || wcslen(ModuleILPath) <= 2) { moduleName.SetUTF8(pModule->GetSimpleName()); ModuleILPath = (PWCHAR)moduleName.GetUnicode(); @@ -5242,52 +5250,52 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL return; #endif // !FEATURE_DTRACE - if(bFireDomainModuleEvents) + if (bFireDomainModuleEvents) { - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwDomainModuleLoad_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwDomainModuleDCStart_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwDomainModuleDCEnd_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } else { - if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad)) + if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad)) { FireEtwModuleLoad_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwModuleUnload_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) { FireEtwModuleDCStart_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) { FireEtwModuleDCEnd_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeEnabledAny)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeEnabledAny)); } #if !defined(FEATURE_PAL) @@ -5303,55 +5311,55 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL /*****************************************************************/ /* This routine is used to send an ETW event just before a method starts jitting*/ /*****************************************************************/ -void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - Module *pModule = NULL; - Module *pLoaderModule = NULL; // This must not be used except for getting the ModuleID + Module* pModule = NULL; + Module* pLoaderModule = NULL; // This must not be used except for getting the ModuleID - ULONGLONG ullMethodIdentifier=0; - ULONGLONG ullModuleID=0; - ULONG ulMethodToken=0; - ULONG ulMethodILSize=0; + ULONGLONG ullMethodIdentifier = 0; + ULONGLONG ullModuleID = 0; + ULONG ulMethodToken = 0; + ULONG ulMethodILSize = 0; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L"",szDtraceOutput3=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L"", szDtraceOutput3 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput3[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE - if(pMethodDesc) { + if (pMethodDesc) { pModule = pMethodDesc->GetModule_NoLogging(); - if(!pMethodDesc->IsRestored()) { - return; + if (!pMethodDesc->IsRestored()) { + return; } bool bIsDynamicMethod = pMethodDesc->IsDynamicMethod(); BOOL bIsGenericMethod = FALSE; - if(pMethodDesc->GetMethodTable_NoLogging()) + if (pMethodDesc->GetMethodTable_NoLogging()) bIsGenericMethod = pMethodDesc->HasClassOrMethodInstantiation_NoLogging(); - ullModuleID = (ULONGLONG)(TADDR) pModule; + ullModuleID = (ULONGLONG)(TADDR)pModule; ullMethodIdentifier = (ULONGLONG)pMethodDesc; // Use MethodDesc if Dynamic or Generic methods - if( bIsDynamicMethod || bIsGenericMethod) + if (bIsDynamicMethod || bIsGenericMethod) { - if(bIsGenericMethod) + if (bIsGenericMethod) ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 + if (bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 ulMethodToken = (ULONG)0; } else ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(pMethodDesc->IsIL()) + if (pMethodDesc->IsIL()) { COR_ILMETHOD_DECODER::DecoderStatus decoderstatus = COR_ILMETHOD_DECODER::FORMAT_ERROR; COR_ILMETHOD_DECODER ILHeader(pMethodDesc->GetILHeader(), pMethodDesc->GetMDImport(), &decoderstatus); @@ -5359,7 +5367,7 @@ void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n } SString tNamespace, tMethodName, tMethodSignature; - if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) + if (!namespaceOrClassName || !methodName || !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) { pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); namespaceOrClassName = &tNamespace; @@ -5387,35 +5395,35 @@ void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n #endif // !FEATURE_DTRACE FireEtwMethodJittingStarted_V1(ullMethodIdentifier, - ullModuleID, - ulMethodToken, - ulMethodILSize, - szDtraceOutput1, - szDtraceOutput2, - szDtraceOutput3, - GetClrInstanceId()); + ullModuleID, + ulMethodToken, + ulMethodILSize, + szDtraceOutput1, + szDtraceOutput2, + szDtraceOutput3, + GetClrInstanceId()); } } /****************************************************************************/ /* This routine is used to send a method load/unload or rundown event */ /****************************************************************************/ -void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +void ETW::MethodLog::SendMethodEvent(MethodDesc* pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString* namespaceOrClassName, SString* methodName, SString* methodSignature, SIZE_T pCode, ReJITID rejitID) { - CONTRACTL { + CONTRACTL{ THROWS; GC_NOTRIGGER; SO_NOT_MAINLINE; } CONTRACTL_END; - Module *pModule = NULL; - Module *pLoaderModule = NULL; // This must not be used except for getting the ModuleID - ULONGLONG ullMethodStartAddress=0, ullColdMethodStartAddress=0, ullModuleID=0, ullMethodIdentifier=0; - ULONG ulMethodSize=0, ulColdMethodSize=0, ulMethodToken=0, ulMethodFlags=0, ulColdMethodFlags=0; - PWCHAR pMethodName=NULL, pNamespaceName=NULL, pMethodSignature=NULL; + Module* pModule = NULL; + Module* pLoaderModule = NULL; // This must not be used except for getting the ModuleID + ULONGLONG ullMethodStartAddress = 0, ullColdMethodStartAddress = 0, ullModuleID = 0, ullMethodIdentifier = 0; + ULONG ulMethodSize = 0, ulColdMethodSize = 0, ulMethodToken = 0, ulMethodFlags = 0, ulColdMethodFlags = 0; + PWCHAR pMethodName = NULL, pNamespaceName = NULL, pMethodSignature = NULL; BOOL bHasNativeImage = FALSE, bShowVerboseOutput = FALSE, bIsDynamicMethod = FALSE, bHasSharedGenericCode = FALSE, bIsGenericMethod = FALSE; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L"",szDtraceOutput3=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L"", szDtraceOutput3 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; @@ -5423,25 +5431,25 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio #endif // !FEATURE_DTRACE BOOL bIsRundownProvider = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)); BOOL bIsRuntimeProvider = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)); if (pMethodDesc == NULL) return; - if(!pMethodDesc->IsRestored()) + if (!pMethodDesc->IsRestored()) { // Forcibly restoring ngen methods can cause all sorts of deadlocks and contract violations // These events are therefore put under the private provider - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_PRIVATENGENFORCERESTORE_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_PRIVATENGENFORCERESTORE_KEYWORD)) { PERMANENT_CONTRACT_VIOLATION(GCViolation, ReasonNonShippingCode); pMethodDesc->CheckRestore(); @@ -5453,13 +5461,13 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } - if(bIsRundownProvider) + if (bIsRundownProvider) { bShowVerboseOutput = ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_VERBOSE, KEYWORDZERO); } - else if(bIsRuntimeProvider) + else if (bIsRuntimeProvider) { bShowVerboseOutput = ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_VERBOSE, @@ -5473,7 +5481,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio bIsDynamicMethod = (BOOL)pMethodDesc->IsDynamicMethod(); bHasSharedGenericCode = pMethodDesc->IsSharedByGenericInstantiations(); - if(pMethodDesc->GetMethodTable_NoLogging()) + if (pMethodDesc->GetMethodTable_NoLogging()) bIsGenericMethod = pMethodDesc->HasClassOrMethodInstantiation_NoLogging(); ulMethodFlags = ((ulMethodFlags | @@ -5489,7 +5497,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // MethodDesc ==> Code Address ==>JitMananger TADDR start = pCode ? pCode : PCODEToPINSTR(pMethodDesc->GetNativeCode()); - if(start == 0) { + if (start == 0) { // this method hasn't been jitted return; } @@ -5505,22 +5513,22 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ullMethodStartAddress = (ULONGLONG)methodRegionInfo.hotStartAddress; ulMethodSize = (ULONG)methodRegionInfo.hotSize; - ullModuleID = (ULONGLONG)(TADDR) pModule; + ullModuleID = (ULONGLONG)(TADDR)pModule; ullMethodIdentifier = (ULONGLONG)pMethodDesc; // Use MethodDesc if Dynamic or Generic methods - if( bIsDynamicMethod || bIsGenericMethod) + if (bIsDynamicMethod || bIsGenericMethod) { bShowVerboseOutput = TRUE; - if(bIsGenericMethod) + if (bIsGenericMethod) ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 + if (bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 ulMethodToken = (ULONG)0; } else ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bHasNativeImage) + if (bHasNativeImage) { ullColdMethodStartAddress = (ULONGLONG)methodRegionInfo.coldStartAddress; ulColdMethodSize = (ULONG)methodRegionInfo.coldSize; // methodRegionInfo.coldSize is size_t and info.MethodLoadInfo.MethodSize is 32 bit; will give incorrect values on a 64-bit machine @@ -5530,9 +5538,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // if verbose method load info needed, only then // find method name and signature and fire verbose method load info - if(bShowVerboseOutput) + if (bShowVerboseOutput) { - if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) + if (!namespaceOrClassName || !methodName || !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) { pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); namespaceOrClassName = &tNamespace; @@ -5564,10 +5572,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio return; #endif // !FEATURE_DTRACE - if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || + if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5592,9 +5600,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5621,10 +5629,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5649,9 +5657,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5678,10 +5686,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5706,9 +5714,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5735,10 +5743,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5763,9 +5771,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5822,7 +5830,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // // static -void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, ReJITID rejitID) +void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc* pMethodDesc, DWORD dwEventOptions, ReJITID rejitID) { CONTRACTL { @@ -5899,42 +5907,42 @@ void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWOR void ETW::MethodLog::SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName) { WRAPPER_NO_CONTRACT; - if(pHelperName) + if (pHelperName) { #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else - CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; + CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE - ULONG methodFlags = ETW::MethodLog::MethodStructs::JitHelperMethod; // helper flag set + ULONG methodFlags = ETW::MethodLog::MethodStructs::JitHelperMethod; // helper flag set #ifndef FEATURE_DTRACE - FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, - 0, - ullHelperStartAddress, - ulHelperSize, - 0, - methodFlags, - NULL, - pHelperName, - NULL, - GetClrInstanceId()); + FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, + 0, + ullHelperStartAddress, + ulHelperSize, + 0, + methodFlags, + NULL, + pHelperName, + NULL, + GetClrInstanceId()); #else // !FEATURE_DTRACE // since DTrace do not support UNICODE string, they need to be converted to ANSI string - INT32 nTempHelperName = WideCharToMultiByte(pHelperName, szDtraceOutput1); - if (nTempHelperName == 0) - return; - // in the action, printf, of DTtrace, it cannot print an arg with value NULL when the format is set %s. - // Dtrace does not provide the condition statement so that we give a string "NULL" to it. - FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, - 0, - ullHelperStartAddress, - ulHelperSize, - 0, - methodFlags, - szDtraceOutputNULL, - szDtraceOutput1, - szDtraceOutputNULL, - GetClrInstanceId()); + INT32 nTempHelperName = WideCharToMultiByte(pHelperName, szDtraceOutput1); + if (nTempHelperName == 0) + return; + // in the action, printf, of DTtrace, it cannot print an arg with value NULL when the format is set %s. + // Dtrace does not provide the condition statement so that we give a string "NULL" to it. + FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, + 0, + ullHelperStartAddress, + ulHelperSize, + 0, + methodFlags, + szDtraceOutputNULL, + szDtraceOutput1, + szDtraceOutputNULL, + GetClrInstanceId()); #endif // !FEATURE_DTRACE } } @@ -5943,23 +5951,23 @@ void ETW::MethodLog::SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHe /****************************************************************************/ /* This routine sends back method events of type 'dwEventOptions', for all NGEN methods in pModule */ -/****************************************************************************/ -void ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions) + /****************************************************************************/ +void ETW::MethodLog::SendEventsForNgenMethods(Module* pModule, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; #ifdef FEATURE_PREJIT - if(!pModule || !pModule->HasNativeImage()) + if (!pModule || !pModule->HasNativeImage()) return; MethodIterator mi(pModule); - while(mi.Next()) + while (mi.Next()) { - MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc(); + MethodDesc* hotDesc = (MethodDesc*)mi.GetMethodDesc(); ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE); } #endif // FEATURE_PREJIT @@ -5970,10 +5978,10 @@ void ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOpti JITed methods in either a given LoaderAllocator (if pLoaderAllocatorFilter is non NULL) or in a given Domain (if pDomainFilter is non NULL) or for all methods (if both filters are null) */ -/****************************************************************************/ -void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions) + /****************************************************************************/ +void ETW::MethodLog::SendEventsForJitMethods(BaseDomain* pDomainFilter, LoaderAllocator* pLoaderAllocatorFilter, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; @@ -5983,19 +5991,19 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // This is only called for JITted methods loading xor unloading BOOL fLoadOrDCStart = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) != 0); BOOL fUnloadOrDCEnd = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) != 0); - _ASSERTE((fLoadOrDCStart || fUnloadOrDCEnd) && !(fLoadOrDCStart && fUnloadOrDCEnd)); + _ASSERTE((fLoadOrDCStart || fUnloadOrDCEnd) && !(fLoadOrDCStart&& fUnloadOrDCEnd)); BOOL fSendMethodEvent = (dwEventOptions & (ETW::EnumerationLog::EnumerationStructs::JitMethodLoad | - ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart | - ETW::EnumerationLog::EnumerationStructs::JitMethodUnload | - ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd)) != 0; + ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart | + ETW::EnumerationLog::EnumerationStructs::JitMethodUnload | + ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd)) != 0; BOOL fSendILToNativeMapEvent = (dwEventOptions & (ETW::EnumerationLog::EnumerationStructs::MethodDCStartILToNativeMap | - ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap)) != 0; + ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap)) != 0; BOOL fCollectibleLoaderAllocatorFilter = ((pLoaderAllocatorFilter != NULL) && (pLoaderAllocatorFilter->IsCollectible())); @@ -6014,9 +6022,9 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl #endif // WINXP_AND_WIN2K3_BUILD_SUPPORT EEJitManager::CodeHeapIterator heapIterator(pDomainFilter, pLoaderAllocatorFilter); - while(heapIterator.Next()) + while (heapIterator.Next()) { - MethodDesc * pMD = heapIterator.GetMethod(); + MethodDesc* pMD = heapIterator.GetMethod(); if (pMD == NULL) continue; @@ -6103,7 +6111,7 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // enumerationOptions - Flags indicating what to enumerate. Just passed // straight through to IterateDomain // -void ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions) +void ETW::EnumerationLog::IterateAppDomain(AppDomain* pAppDomain, DWORD enumerationOptions) { CONTRACTL { @@ -6143,10 +6151,10 @@ void ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumera JIT methods in them, and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateDomain(BaseDomain* pDomain, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pDomain != NULL); @@ -6166,86 +6174,86 @@ void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp EX_TRY { // DC Start events for Domain - if(enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); } - // DC End or Unload Jit Method events - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) - { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); - } + // DC End or Unload Jit Method events + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) + { + ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + } - if (pDomain->IsAppDomain()) + if (pDomain->IsAppDomain()) + { + AppDomain::AssemblyIterator assemblyIterator = pDomain->AsAppDomain()->IterateAssembliesEx( + (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); + CollectibleAssemblyHolder pDomainAssembly; + while (assemblyIterator.Next(pDomainAssembly.This())) { - AppDomain::AssemblyIterator assemblyIterator = pDomain->AsAppDomain()->IterateAssembliesEx( - (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); - CollectibleAssemblyHolder pDomainAssembly; - while (assemblyIterator.Next(pDomainAssembly.This())) + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); + if (bIsDomainNeutral) + continue; + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); - BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); - if (bIsDomainNeutral) - continue; - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); + } - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); + while (domainModuleIterator.Next()) + { + Module* pModule = domainModuleIterator.GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); + } - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } } - else + } + else + { + SharedDomain::SharedAssemblyIterator sharedDomainIterator; + while (sharedDomainIterator.Next()) { - SharedDomain::SharedAssemblyIterator sharedDomainIterator; - while (sharedDomainIterator.Next()) + Assembly* pAssembly = sharedDomainIterator.GetAssembly(); + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { - Assembly * pAssembly = sharedDomainIterator.GetAssembly(); - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); + } - ModuleIterator domainModuleIterator = pAssembly->IterateModules(); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + ModuleIterator domainModuleIterator = pAssembly->IterateModules(); + while (domainModuleIterator.Next()) + { + Module* pModule = domainModuleIterator.GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); + } - if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } } + } - // DC Start or Load Jit Method events - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) - { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); - } + // DC Start or Load Jit Method events + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) + { + ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + } - // DC End or Unload events for Domain - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // DC End or Unload events for Domain + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } @@ -6257,10 +6265,10 @@ void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp JIT methods in them, and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator* pLoaderAllocator, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pLoaderAllocator != NULL); @@ -6274,13 +6282,13 @@ void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); } - Assembly *pAssembly = pLoaderAllocator->Id()->GetDomainAssembly()->GetAssembly(); + Assembly* pAssembly = pLoaderAllocator->Id()->GetDomainAssembly()->GetAssembly(); _ASSERTE(!pAssembly->IsDomainNeutral()); // Collectible Assemblies are not domain neutral. DomainModuleIterator domainModuleIterator = pLoaderAllocator->Id()->GetDomainAssembly()->IterateModules(kModIterIncludeLoaded); while (domainModuleIterator.Next()) { - Module *pModule = domainModuleIterator.GetModule(); + Module* pModule = domainModuleIterator.GetModule(); ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); } @@ -6294,16 +6302,16 @@ void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca { ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /********************************************************************************/ /* This routine fires ETW events for Assembly and the DomainModule's in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateAssembly(Assembly* pAssembly, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pAssembly != NULL); @@ -6312,41 +6320,41 @@ void ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumeration EX_TRY { // DC Start events for Assembly - if(enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); } - // DC Start, DCEnd, events for DomainModule - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart)) + // DC Start, DCEnd, events for DomainModule + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart)) + { + if (pAssembly->GetDomain()->IsAppDomain()) { - if(pAssembly->GetDomain()->IsAppDomain()) + DomainModuleIterator dmIterator = pAssembly->FindDomainAssembly(pAssembly->GetDomain()->AsAppDomain())->IterateModules(kModIterIncludeLoaded); + while (dmIterator.Next()) { - DomainModuleIterator dmIterator = pAssembly->FindDomainAssembly(pAssembly->GetDomain()->AsAppDomain())->IterateModules(kModIterIncludeLoaded); - while (dmIterator.Next()) - { - ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); - } + ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); } } + } - // DC End or Unload events for Assembly - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // DC End or Unload events for Assembly + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /********************************************************************************/ /* This routine fires ETW events for Module, their range information and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateModule(Module* pModule, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pModule != NULL); @@ -6355,45 +6363,45 @@ void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOption EX_TRY { // DC Start events for Module - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) { ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); } - // DC Start or Load or DC End or Unload Ngen Method events - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) - { - ETW::MethodLog::SendEventsForNgenMethods(pModule, enumerationOptions); - } + // DC Start or Load or DC End or Unload Ngen Method events + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) + { + ETW::MethodLog::SendEventsForNgenMethods(pModule, enumerationOptions); + } - // DC End or Unload events for Module - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) - { - ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); - } + // DC End or Unload events for Module + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) + { + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); + } - // If we're logging types, then update the internal Type hash table to account - // for the module's unloading - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::TypeUnload) - { - ETW::TypeSystemLog::OnModuleUnload(pModule); - } + // If we're logging types, then update the internal Type hash table to account + // for the module's unloading + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::TypeUnload) + { + ETW::TypeSystemLog::OnModuleUnload(pModule); + } - // ModuleRangeLoadPrivate events for module range information from attach/detach scenarios - if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_PERFTRACK_PRIVATE_KEYWORD) && - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate)) - { - ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // ModuleRangeLoadPrivate events for module range information from attach/detach scenarios + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_PERFTRACK_PRIVATE_KEYWORD) && + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate)) + { + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } //--------------------------------------------------------------------------------------- @@ -6429,9 +6437,9 @@ void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOption // // static -void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions) +void ETW::EnumerationLog::EnumerationHelper(Module* moduleFilter, BaseDomain* domainFilter, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; @@ -6444,7 +6452,7 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrSharedDomain(SharedDomain::GetDomain()->GetReJitManager()); - if(moduleFilter) + if (moduleFilter) { // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrModule(moduleFilter->GetReJitManager()); @@ -6466,12 +6474,12 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do } else { - if(domainFilter) + if (domainFilter) { // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrAD(domainFilter->GetReJitManager()); - if(domainFilter->IsAppDomain()) + if (domainFilter->IsAppDomain()) { ETW::EnumerationLog::IterateAppDomain(domainFilter->AsAppDomain(), enumerationOptions); } @@ -6483,9 +6491,9 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do else { AppDomainIterator appDomainIterator(FALSE); - while(appDomainIterator.Next()) + while (appDomainIterator.Next()) { - AppDomain *pDomain = appDomainIterator.GetDomain(); + AppDomain* pDomain = appDomainIterator.GetDomain(); if (pDomain != NULL) { // See code:#TableLockHolder diff --git a/src/coreclr/nativeaot/Runtime/eventtracebase.h b/src/coreclr/nativeaot/Runtime/eventtracebase.h index 79b8fac860612..e4a16fd87d6e0 100644 --- a/src/coreclr/nativeaot/Runtime/eventtracebase.h +++ b/src/coreclr/nativeaot/Runtime/eventtracebase.h @@ -147,13 +147,6 @@ struct ProfilingScanContext; #ifndef FEATURE_REDHAWK -#if defined(FEATURE_CORECLR) && !defined(FEATURE_CORESYSTEM) -// For Silverlight non-CoreSys builds we still use an older toolset, -// headers/libs, and a different value for WINVER. We use this symbol -// to distinguish between whether we built the ETW header files from -// the ETW manifest using the -mof command line or not. -#define WINXP_AND_WIN2K3_BUILD_SUPPORT -#endif #include "corprof.h" // g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index 2f6f6ea4f7c0c..0001de5370c1d 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -585,7 +585,8 @@ void RedhawkGCInterface::UnregisterFrozenSegment(GcSegmentHandle segment) GCHeapUtilities::GetGCHeap()->UnregisterFrozenSegment((segment_handle)segment); } -EXTERN_C UInt32_BOOL g_fGcStressStarted = UInt32_FALSE; // UInt32_BOOL because asm code reads it +EXTERN_C UInt32_BOOL g_fGcStressStarted; +UInt32_BOOL g_fGcStressStarted = UInt32_FALSE; // UInt32_BOOL because asm code reads it #ifdef FEATURE_GC_STRESS // static void RedhawkGCInterface::StressGc() diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index ada010f8a573e..9f82aebdbf39e 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -45,14 +45,17 @@ static bool DetectCPUFeatures(); extern RhConfig * g_pRhConfig; -EXTERN_C bool g_fHasFastFxsave = false; +EXTERN_C bool g_fHasFastFxsave; +bool g_fHasFastFxsave = false; CrstStatic g_CastCacheLock; CrstStatic g_ThunkPoolLock; #if defined(HOST_X86) || defined(HOST_AMD64) || defined(HOST_ARM64) // This field is inspected from the generated code to determine what intrinsics are available. -EXTERN_C int g_cpuFeatures = 0; +EXTERN_C int g_cpuFeatures; +int g_cpuFeatures = 0; + // This field is defined in the generated code and sets the ISA expectations. EXTERN_C int g_requiredCpuFeatures; #endif diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index e0a7d528358ab..36bf43c1a359f 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -27,7 +27,8 @@ #include "slist.inl" #include "GCMemoryHelpers.h" -EXTERN_C volatile uint32_t RhpTrapThreads = (uint32_t)TrapThreadsFlags::None; +EXTERN_C volatile uint32_t RhpTrapThreads; +volatile uint32_t RhpTrapThreads = (uint32_t)TrapThreadsFlags::None; GVAL_IMPL_INIT(PTR_Thread, RhpSuspendingThread, 0); @@ -373,7 +374,8 @@ COOP_PINVOKE_HELPER(void, RhpCancelThreadAbort, (void* thread)) C_ASSERT(sizeof(Thread) == sizeof(ThreadBuffer)); -EXTERN_C DECLSPEC_THREAD ThreadBuffer tls_CurrentThread = +EXTERN_C DECLSPEC_THREAD ThreadBuffer tls_CurrentThread; +DECLSPEC_THREAD ThreadBuffer tls_CurrentThread = { { 0 }, // m_rgbAllocContextBuffer Thread::TSF_Unknown, // m_ThreadStateFlags diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 2cc2f40a841f8..198172362464a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -1091,5 +1091,10 @@ public static bool IsPrimitive(RuntimeTypeHandle typeHandle) { return typeHandle.ToEETypePtr().IsPrimitive && !typeHandle.ToEETypePtr().IsEnum; } + + public static byte[] ComputePublicKeyToken(byte[] publicKey) + { + return System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(publicKey); + } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index cf0cab0700eba..2284e13f66135 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -123,15 +123,12 @@ - - - - + + - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs index 8a53e1588b83d..15b629dbee219 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs @@ -16,18 +16,6 @@ namespace System { public static partial class Math { - [Intrinsic] - public static float Abs(float value) - { - return RuntimeImports.fabsf(value); - } - - [Intrinsic] - public static double Abs(double value) - { - return RuntimeImports.fabs(value); - } - [Intrinsic] public static double Acos(double d) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs index 3714e7ce510fb..d1bb831f34772 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -6,7 +6,7 @@ namespace System { - public struct ModuleHandle + public struct ModuleHandle : IEquatable { public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs deleted file mode 100644 index bc3ef37804315..0000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs +++ /dev/null @@ -1,34 +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.Runtime.Serialization; - -namespace System.Reflection -{ - public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable - { - public AssemblyName(string assemblyName) - : this() - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - RuntimeAssemblyName runtimeAssemblyName = AssemblyNameParser.Parse(_name); - runtimeAssemblyName.CopyToAssemblyName(this); - } - - private byte[] ComputePublicKeyToken() - { - return AssemblyNameHelpers.ComputePublicKeyToken(_publicKey); - } - - private static AssemblyName GetFileInformationCore(string assemblyFile) - { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_AssemblyName_GetAssemblyName); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs index b259e2b6bfbdc..a79f9f7f65307 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs @@ -9,41 +9,8 @@ namespace System.Reflection { - [System.Runtime.CompilerServices.ReflectionBlocked] - public static partial class AssemblyNameHelpers + internal static partial class AssemblyNameHelpers { - // - // Converts an AssemblyName to a RuntimeAssemblyName that is free from any future mutations on the AssemblyName. - // - public static RuntimeAssemblyName ToRuntimeAssemblyName(this AssemblyName assemblyName) - { - if (assemblyName.Name == null) - throw new ArgumentException(); - - AssemblyNameFlags flags = assemblyName.Flags; - AssemblyContentType contentType = assemblyName.ContentType; -#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - ProcessorArchitecture processorArchitecture = assemblyName.ProcessorArchitecture; -#pragma warning restore SYSLIB0037 - AssemblyNameFlags combinedFlags = CombineAssemblyNameFlags(flags, contentType, processorArchitecture); - byte[]? pkOriginal; - if (0 != (flags & AssemblyNameFlags.PublicKey)) - pkOriginal = assemblyName.GetPublicKey(); - else - pkOriginal = assemblyName.GetPublicKeyToken(); - - // AssemblyName's PKT property getters do NOT copy the array before giving it out. Make our own copy - // as the original is wide open to tampering by anyone. - byte[]? pkCopy = null; - if (pkOriginal != null) - { - pkCopy = new byte[pkOriginal.Length]; - ((ICollection)pkOriginal).CopyTo(pkCopy, 0); - } - - return new RuntimeAssemblyName(assemblyName.Name, assemblyName.Version, assemblyName.CultureName, combinedFlags, pkCopy); - } - // // These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts. // @@ -55,19 +22,9 @@ internal static AssemblyContentType ExtractAssemblyContentType(this AssemblyName return (AssemblyContentType)((((int)flags) >> 9) & 0x7); } - internal static ProcessorArchitecture ExtractProcessorArchitecture(this AssemblyNameFlags flags) - { - return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); - } - - public static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags) + internal static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags) { return combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); } - - internal static AssemblyNameFlags CombineAssemblyNameFlags(AssemblyNameFlags flags, AssemblyContentType contentType, ProcessorArchitecture processorArchitecture) - { - return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4)); - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs deleted file mode 100644 index 84555ab310d45..0000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs +++ /dev/null @@ -1,136 +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.IO; -using System.Text; -using System.Globalization; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace System.Reflection -{ - // - // A simple lexer for assembly display names. - // - internal struct AssemblyNameLexer - { - internal AssemblyNameLexer(string s) - { - // Convert string to char[] with NUL terminator. (An actual NUL terminator in the input string will be treated - // as an actual end of string: this is compatible with desktop behavior.) - char[] chars = new char[s.Length + 1]; - s.CopyTo(0, chars, 0, s.Length); - _chars = chars; - _index = 0; - } - - // - // Return the next token in assembly name. If you expect the result to be DisplayNameToken.String, - // use GetNext(out String) instead. - // - internal Token GetNext() - { - return GetNext(out _); - } - - // - // Return the next token in assembly name. If the result is DisplayNameToken.String, - // sets "tokenString" to the tokenized string. - // - internal Token GetNext(out string tokenString) - { - tokenString = null; - while (char.IsWhiteSpace(_chars[_index])) - _index++; - - char c = _chars[_index++]; - if (c == 0) - return Token.End; - if (c == ',') - return Token.Comma; - if (c == '=') - return Token.Equals; - - StringBuilder sb = new StringBuilder(); - - char quoteChar = (char)0; - if (c == '\'' || c == '\"') - { - quoteChar = c; - c = _chars[_index++]; - } - - for (;;) - { - if (c == 0) - { - _index--; - break; // Terminate: End of string (desktop compat: if string was quoted, permitted to terminate without end-quote.) - } - - if (quoteChar != 0 && c == quoteChar) - break; // Terminate: Found closing quote of quoted string. - - if (quoteChar == 0 && (c == ',' || c == '=')) - { - _index--; - break; // Terminate: Found start of a new ',' or '=' token. - } - - if (quoteChar == 0 && (c == '\'' || c == '\"')) - throw new FileLoadException(); // Desktop compat: Unescaped quote illegal unless entire string is quoted. - - if (c == '\\') - { - c = _chars[_index++]; - - switch (c) - { - case '\\': - case ',': - case '=': - case '\'': - case '"': - sb.Append(c); - break; - case 't': - sb.Append('\t'); - break; - case 'r': - sb.Append('\r'); - break; - case 'n': - sb.Append('\n'); - break; - default: - throw new FileLoadException(); // Unrecognized escape - } - } - else - { - sb.Append(c); - } - - c = _chars[_index++]; - } - - tokenString = sb.ToString(); - if (quoteChar == 0) - tokenString = tokenString.Trim(); // Unless quoted, whitespace at beginning or end doesn't count. - return Token.String; - } - - // Token categories for display name lexer. - internal enum Token - { - Equals = 1, - Comma = 2, - String = 3, - End = 4, - } - - private readonly char[] _chars; - private int _index; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs deleted file mode 100644 index 5d8f2ef1c34b0..0000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs +++ /dev/null @@ -1,230 +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.IO; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace System.Reflection -{ - // - // Parses an assembly name. - // - [System.Runtime.CompilerServices.ReflectionBlocked] - public static class AssemblyNameParser - { - public static void Parse(AssemblyName blank, string s) - { - if (s == null) - throw new ArgumentNullException(nameof(s)); - RuntimeAssemblyName runtimeAssemblyName = Parse(s); - runtimeAssemblyName.CopyToAssemblyName(blank); - } - - public static RuntimeAssemblyName Parse(string s) - { - Debug.Assert(s != null); - - int indexOfNul = s.IndexOf((char)0); - if (indexOfNul != -1) - s = s.Substring(0, indexOfNul); - if (s.Length == 0) - throw new ArgumentException(SR.Format_StringZeroLength); - - AssemblyNameLexer lexer = new AssemblyNameLexer(s); - - // Name must come first. - string name; - AssemblyNameLexer.Token token = lexer.GetNext(out name); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - - if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1) - throw new FileLoadException(SR.InvalidAssemblyName); - - Version? version = null; - string? cultureName = null; - byte[]? pkt = null; - AssemblyNameFlags flags = 0; - - LowLevelList alreadySeen = new LowLevelList(); - token = lexer.GetNext(); - while (token != AssemblyNameLexer.Token.End) - { - if (token != AssemblyNameLexer.Token.Comma) - throw new FileLoadException(SR.InvalidAssemblyName); - string attributeName; - - token = lexer.GetNext(out attributeName); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - token = lexer.GetNext(); - - // Compat note: Inside AppX apps, the desktop CLR's AssemblyName parser skips past any elements that don't follow the "=" pattern. - // (when running classic Windows apps, such an illegal construction throws an exception as expected.) - // Naturally, at least one app unwittingly takes advantage of this. - if (token == AssemblyNameLexer.Token.Comma || token == AssemblyNameLexer.Token.End) - continue; - - if (token != AssemblyNameLexer.Token.Equals) - throw new FileLoadException(SR.InvalidAssemblyName); - string attributeValue; - token = lexer.GetNext(out attributeValue); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - - if (attributeName == string.Empty) - throw new FileLoadException(SR.InvalidAssemblyName); - - for (int i = 0; i < alreadySeen.Count; i++) - { - if (alreadySeen[i].Equals(attributeName, StringComparison.OrdinalIgnoreCase)) - throw new FileLoadException(SR.InvalidAssemblyName); // Cannot specify the same attribute twice. - } - alreadySeen.Add(attributeName); - - if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase)) - { - version = ParseVersion(attributeValue); - } - - if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase)) - { - cultureName = ParseCulture(attributeValue); - } - - if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase)) - { - pkt = ParsePKT(attributeValue); - } - - if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase)) - { - flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4); - } - - if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase)) - { - if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) - flags |= AssemblyNameFlags.Retargetable; - else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) - { - // nothing to do - } - else - throw new FileLoadException(SR.InvalidAssemblyName); - } - - if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase)) - { - if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) - flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); - else - throw new FileLoadException(SR.InvalidAssemblyName); - } - - // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it (as long it's not duplicated.) - token = lexer.GetNext(); - } - return new RuntimeAssemblyName(name, version, cultureName, flags, pkt); - } - - private static Version ParseVersion(string attributeValue) - { - string[] parts = attributeValue.Split('.'); - if (parts.Length > 4) - throw new FileLoadException(SR.InvalidAssemblyName); - ushort[] versionNumbers = new ushort[4]; - for (int i = 0; i < versionNumbers.Length; i++) - { - if (i >= parts.Length) - versionNumbers[i] = ushort.MaxValue; - else - { - // Desktop compat: TryParse is a little more forgiving than Fusion. - for (int j = 0; j < parts[i].Length; j++) - { - if (!char.IsDigit(parts[i][j])) - throw new FileLoadException(SR.InvalidAssemblyName); - } - if (!(ushort.TryParse(parts[i], out versionNumbers[i]))) - { - throw new FileLoadException(SR.InvalidAssemblyName); - } - } - } - - if (versionNumbers[0] == ushort.MaxValue || versionNumbers[1] == ushort.MaxValue) - throw new FileLoadException(SR.InvalidAssemblyName); - if (versionNumbers[2] == ushort.MaxValue) - return new Version(versionNumbers[0], versionNumbers[1]); - if (versionNumbers[3] == ushort.MaxValue) - return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]); - return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); - } - - private static string ParseCulture(string attributeValue) - { - if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) - { - return ""; - } - else - { - CultureInfo culture = CultureInfo.GetCultureInfo(attributeValue); // Force a CultureNotFoundException if not a valid culture. - return culture.Name; - } - } - - private static byte[] ParsePKT(string attributeValue) - { - if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) - return Array.Empty(); - - if (attributeValue.Length != 8 * 2) - throw new FileLoadException(SR.InvalidAssemblyName); - - byte[] pkt = new byte[8]; - int srcIndex = 0; - for (int i = 0; i < 8; i++) - { - char hi = attributeValue[srcIndex++]; - char lo = attributeValue[srcIndex++]; - pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo)); - } - return pkt; - } - - private static ProcessorArchitecture ParseProcessorArchitecture(string attributeValue) - { - if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.MSIL; - if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.X86; - if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.IA64; - if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Amd64; - if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Arm; - throw new FileLoadException(SR.InvalidAssemblyName); - } - - private static byte ParseHexNybble(char c) - { - if (c >= '0' && c <= '9') - return (byte)(c - '0'); - if (c >= 'a' && c <= 'f') - return (byte)(c - 'a' + 10); - if (c >= 'A' && c <= 'F') - return (byte)(c - 'A' + 10); - throw new FileLoadException(SR.InvalidAssemblyName); - } - - private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' }; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs new file mode 100644 index 0000000000000..fc4ed2816e580 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs @@ -0,0 +1,52 @@ +// 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.Globalization; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace System.Reflection +{ + [System.Runtime.CompilerServices.ReflectionBlocked] + public static class AssemblyRuntimeNameHelpers + { + // + // Converts an AssemblyName to a RuntimeAssemblyName that is free from any future mutations on the AssemblyName. + // + public static RuntimeAssemblyName ToRuntimeAssemblyName(this AssemblyName assemblyName) + { + if (assemblyName.Name == null) + throw new ArgumentException(SR.InvalidAssemblyName); + + AssemblyNameFlags flags = assemblyName.Flags; + AssemblyContentType contentType = assemblyName.ContentType; +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + ProcessorArchitecture processorArchitecture = assemblyName.ProcessorArchitecture; +#pragma warning restore SYSLIB0037 + AssemblyNameFlags combinedFlags = CombineAssemblyNameFlags(flags, contentType, processorArchitecture); + byte[]? pkOriginal; + if (0 != (flags & AssemblyNameFlags.PublicKey)) + pkOriginal = assemblyName.GetPublicKey(); + else + pkOriginal = assemblyName.GetPublicKeyToken(); + + // AssemblyName's PKT property getters do NOT copy the array before giving it out. Make our own copy + // as the original is wide open to tampering by anyone. + byte[]? pkCopy = null; + if (pkOriginal != null) + { + pkCopy = new byte[pkOriginal.Length]; + Array.Copy(pkOriginal, pkCopy, pkOriginal.Length); + } + + return new RuntimeAssemblyName(assemblyName.Name, assemblyName.Version, assemblyName.CultureName, combinedFlags, pkCopy); + } + + internal static AssemblyNameFlags CombineAssemblyNameFlags(AssemblyNameFlags flags, AssemblyContentType contentType, ProcessorArchitecture processorArchitecture) + { + return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4)); + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs index 90c0fe5ff824a..f4dbc0d667140 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs @@ -16,7 +16,7 @@ namespace System.Reflection // public sealed class RuntimeAssemblyName : IEquatable { - public RuntimeAssemblyName(string name, Version version, string cultureName, AssemblyNameFlags flags, byte[] publicKeyOrToken) + public RuntimeAssemblyName(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) { Debug.Assert(name != null); this.Name = name; @@ -34,20 +34,26 @@ public RuntimeAssemblyName(string name, Version version, string cultureName, Ass this.PublicKeyOrToken = publicKeyOrToken; } + public static RuntimeAssemblyName Parse(string name) + { + AssemblyNameParser.AssemblyNameParts parts = AssemblyNameParser.Parse(name); + return new RuntimeAssemblyName(parts._name, parts._version, parts._cultureName, parts._flags, parts._publicKeyOrToken); + } + // Simple name. public string Name { get; } // Optional version. - public Version Version { get; } + public Version? Version { get; } // Optional culture name. - public string CultureName { get; } + public string? CultureName { get; } // Optional flags (this is actually an OR of the classic flags and the ContentType.) public AssemblyNameFlags Flags { get; } // Optional public key (if Flags.PublicKey == true) or public key token. - public byte[] PublicKeyOrToken { get; } + public byte[]? PublicKeyOrToken { get; } // Equality - this compares every bit of data in the RuntimeAssemblyName which is acceptable for use as keys in a cache // where semantic duplication is permissible. This method is *not* meant to define ref->def binding rules or @@ -73,8 +79,8 @@ public bool Equals(RuntimeAssemblyName? other) if (this.Flags != other.Flags) return false; - byte[] thisPK = this.PublicKeyOrToken; - byte[] otherPK = other.PublicKeyOrToken; + byte[]? thisPK = this.PublicKeyOrToken; + byte[]? otherPK = other.PublicKeyOrToken; if (thisPK == null) { if (otherPK != null) @@ -139,7 +145,7 @@ public void CopyToAssemblyName(AssemblyName blank) blank.Flags = this.Flags.ExtractAssemblyNameFlags(); blank.ContentType = this.Flags.ExtractAssemblyContentType(); #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - blank.ProcessorArchitecture = this.Flags.ExtractProcessorArchitecture(); + blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags); #pragma warning restore SYSLIB0037 if (this.PublicKeyOrToken != null) @@ -162,9 +168,14 @@ public string FullName { get { - byte[] pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; + byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags.ExtractAssemblyNameFlags(), Flags.ExtractAssemblyContentType()); } } + + internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) + { + return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); + } } } 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 304f7073e7ec3..a7edbf10d819a 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 @@ -679,18 +679,6 @@ internal struct ConservativelyReportedRegionDesc [RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")] internal static extern void MemoryBarrier(); - [Intrinsic] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "fabs")] - internal static extern double fabs(double x); - - [Intrinsic] - internal static float fabsf(float x) - { - // fabsf is not a real export for some architectures - return (float)fabs(x); - } - [Intrinsic] [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "acos")] diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs index 53edc6a6ec5e4..2227d4a59682b 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs @@ -89,7 +89,7 @@ private static CoreTypeResolver CreateCoreTypeResolver(Func + namespace System.Reflection.Runtime.General { internal static partial class TypeUnifier diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs index 209a91e0cb102..fdbcf0b53685d 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs @@ -10,6 +10,8 @@ using Internal.Reflection.Tracing; +#pragma warning disable CA1067 // override Equals because it implements IEquatable + namespace System.Reflection.Runtime.TypeInfos { // diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs index dfebfcacea21d..2dc289a7c2fa4 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs @@ -139,7 +139,7 @@ public RuntimeAssemblyName GetNextAssemblyName() } _index = src; string fullName = new string(buffer, 0, dst); - return AssemblyNameParser.Parse(fullName); + return RuntimeAssemblyName.Parse(fullName); } // @@ -173,7 +173,7 @@ public RuntimeAssemblyName GetNextEmbeddedAssemblyName() } _index = src; string fullName = new string(buffer, 0, dst); - return AssemblyNameParser.Parse(fullName); + return RuntimeAssemblyName.Parse(fullName); } // diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 237b75275cec9..db22c68fde053 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -345,6 +345,7 @@ typedef __int64 time_t; #define PAL_INITIALIZE_DEBUGGER_EXCEPTIONS 0x10 #define PAL_INITIALIZE_ENSURE_STACK_SIZE 0x20 #define PAL_INITIALIZE_REGISTER_SIGNALS 0x40 +#define PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL 0x80 // PAL_Initialize() flags #define PAL_INITIALIZE (PAL_INITIALIZE_SYNC_THREAD | \ @@ -359,7 +360,8 @@ typedef __int64 time_t; PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER | \ PAL_INITIALIZE_DEBUGGER_EXCEPTIONS | \ PAL_INITIALIZE_ENSURE_STACK_SIZE | \ - PAL_INITIALIZE_REGISTER_SIGNALS) + PAL_INITIALIZE_REGISTER_SIGNALS | \ + PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL) typedef DWORD (PALAPI_NOEXPORT *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; @@ -2842,24 +2844,6 @@ VirtualQuery( #define FillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) #define ZeroMemory(Destination,Length) memset((Destination),0,(Length)) -#define LMEM_FIXED 0x0000 -#define LMEM_MOVEABLE 0x0002 -#define LMEM_ZEROINIT 0x0040 -#define LPTR (LMEM_FIXED | LMEM_ZEROINIT) - -PALIMPORT -HLOCAL -PALAPI -LocalAlloc( - IN UINT uFlags, - IN SIZE_T uBytes); - -PALIMPORT -HLOCAL -PALAPI -LocalFree( - IN HLOCAL hMem); - PALIMPORT BOOL PALAPI @@ -3261,8 +3245,8 @@ FORCEINLINE void PAL_ArmInterlockedOperationBarrier() Function: InterlockedAdd -The InterlockedAdd function adds the value of the specified variable -with another specified value. The function prevents more than one thread +The InterlockedAdd function adds the value of the specified variable +with another specified value. The function prevents more than one thread from using the same variable simultaneously. Parameters @@ -3934,8 +3918,6 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); #define wcspbrk PAL_wcspbrk #define wcscmp PAL_wcscmp #define wcsncpy PAL_wcsncpy -#define wcstok PAL_wcstok -#define wcscspn PAL_wcscspn #define realloc PAL_realloc #define fopen PAL_fopen #define strtok PAL_strtok @@ -4125,8 +4107,6 @@ PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcschr(const WCHAR *, WCHAR); PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcsrchr(const WCHAR *, WCHAR); PALIMPORT WCHAR _WConst_return * __cdecl PAL_wcspbrk(const WCHAR *, const WCHAR *); PALIMPORT DLLEXPORT WCHAR _WConst_return * __cdecl PAL_wcsstr(const WCHAR *, const WCHAR *); -PALIMPORT WCHAR * __cdecl PAL_wcstok(WCHAR *, const WCHAR *); -PALIMPORT DLLEXPORT size_t __cdecl PAL_wcscspn(const WCHAR *, const WCHAR *); PALIMPORT int __cdecl PAL_swprintf(WCHAR *, const WCHAR *, ...); PALIMPORT int __cdecl PAL_vswprintf(WCHAR *, const WCHAR *, va_list); PALIMPORT int __cdecl PAL_swscanf(const WCHAR *, const WCHAR *, ...); diff --git a/src/coreclr/pal/inc/palprivate.h b/src/coreclr/pal/inc/palprivate.h index 097229eb64ef4..f90352b32355e 100644 --- a/src/coreclr/pal/inc/palprivate.h +++ b/src/coreclr/pal/inc/palprivate.h @@ -203,8 +203,6 @@ CompareFileTime( IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2); -PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t); - /* These are from the file in windows. They are needed for _open_osfhandle.*/ #define _O_RDONLY 0x0000 diff --git a/src/coreclr/pal/inc/rt/sal.h b/src/coreclr/pal/inc/rt/sal.h index 198b46d4a4e06..ef976be402fdc 100644 --- a/src/coreclr/pal/inc/rt/sal.h +++ b/src/coreclr/pal/inc/rt/sal.h @@ -2862,6 +2862,10 @@ of each annotation, see the advanced annotations section. #define __useHeader _Use_decl_anno_impl_ #define __on_failure(annotes) _On_failure_impl_(annotes _SAL_nop_impl_) +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) (0) +#endif + #ifndef __fallthrough // [ #if __has_cpp_attribute(fallthrough) #define __fallthrough [[fallthrough]] diff --git a/src/coreclr/pal/inc/unixasmmacros.inc b/src/coreclr/pal/inc/unixasmmacros.inc index 1fe285eef162d..a1bad6300f3cf 100644 --- a/src/coreclr/pal/inc/unixasmmacros.inc +++ b/src/coreclr/pal/inc/unixasmmacros.inc @@ -39,6 +39,8 @@ #include "unixasmmacrosamd64.inc" #elif defined(HOST_ARM) #include "unixasmmacrosarm.inc" +#elif defined(HOST_ARMV6) +#include "unixasmmacrosarm.inc" #elif defined(HOST_ARM64) #include "unixasmmacrosarm64.inc" #elif defined(HOST_S390X) diff --git a/src/coreclr/pal/inc/unixasmmacrosarm.inc b/src/coreclr/pal/inc/unixasmmacrosarm.inc index e0c0016cc26ab..d323ccc49fbd2 100644 --- a/src/coreclr/pal/inc/unixasmmacrosarm.inc +++ b/src/coreclr/pal/inc/unixasmmacrosarm.inc @@ -197,7 +197,11 @@ C_FUNC(\Name\()_End): .endm .macro EMIT_BREAKPOINT +#ifdef __armv6__ + .inst 0xe7f001f0 +#else .inst.w 0xde01 +#endif .endm .macro PROLOG_PUSH RegList diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 4f071b21046b0..29765f81ea77a 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -45,6 +45,9 @@ if(CLR_CMAKE_HOST_ARCH_AMD64) set(PAL_ARCH_SOURCES_DIR amd64) elseif(CLR_CMAKE_HOST_ARCH_ARM) set(PAL_ARCH_SOURCES_DIR arm) +elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + set(PAL_ARCH_SOURCES_DIR arm) + add_definitions(-D__armv6__) elseif(CLR_CMAKE_HOST_ARCH_ARM64) set(PAL_ARCH_SOURCES_DIR arm64) elseif(CLR_CMAKE_HOST_ARCH_I386) @@ -123,7 +126,6 @@ set(SOURCES cruntime/malloc.cpp cruntime/math.cpp cruntime/misc.cpp - cruntime/path.cpp cruntime/printf.cpp cruntime/printfcpp.cpp cruntime/silent_printf.cpp @@ -131,7 +133,6 @@ set(SOURCES cruntime/stringtls.cpp cruntime/thread.cpp cruntime/wchar.cpp - cruntime/wchartls.cpp debug/debug.cpp exception/seh.cpp exception/signal.cpp @@ -145,14 +146,12 @@ set(SOURCES init/pal.cpp init/sxs.cpp loader/module.cpp - loader/modulename.cpp locale/unicode.cpp locale/unicodedata.cpp locale/utf8.cpp map/common.cpp map/map.cpp map/virtual.cpp - memory/local.cpp misc/cgroup.cpp misc/dbgmsg.cpp misc/environ.cpp diff --git a/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S index 4179f61e16276..a7c92e93188e4 100644 --- a/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S +++ b/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S @@ -5,7 +5,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif .macro CALL_SIGNAL_HANDLER_WRAPPER Alignment diff --git a/src/coreclr/pal/src/arch/arm/context2.S b/src/coreclr/pal/src/arch/arm/context2.S index 1cd7684a953e8..edb5d35bf1e40 100644 --- a/src/coreclr/pal/src/arch/arm/context2.S +++ b/src/coreclr/pal/src/arch/arm/context2.S @@ -10,7 +10,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif #define CONTEXT_ARM 0x00200000 diff --git a/src/coreclr/pal/src/arch/arm/debugbreak.S b/src/coreclr/pal/src/arch/arm/debugbreak.S index dd8a9348352dc..88301b98548c3 100644 --- a/src/coreclr/pal/src/arch/arm/debugbreak.S +++ b/src/coreclr/pal/src/arch/arm/debugbreak.S @@ -4,7 +4,9 @@ #include "unixasmmacros.inc" .syntax unified +#ifndef __armv6__ .thumb +#endif LEAF_ENTRY DBG_DebugBreak, _TEXT EMIT_BREAKPOINT diff --git a/src/coreclr/pal/src/arch/arm/exceptionhelper.S b/src/coreclr/pal/src/arch/arm/exceptionhelper.S index f733aad613379..a43ed14be7d98 100644 --- a/src/coreclr/pal/src/arch/arm/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/arm/exceptionhelper.S @@ -5,7 +5,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/cruntime/path.cpp b/src/coreclr/pal/src/cruntime/path.cpp deleted file mode 100644 index c25636771bc61..0000000000000 --- a/src/coreclr/pal/src/cruntime/path.cpp +++ /dev/null @@ -1,113 +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: - - path.c - -Abstract: - - Implementation of path functions part of Windows runtime library. - -Revision History: - - - ---*/ - -#include "pal/palinternal.h" -#include "pal/dbgmsg.h" -#include "pal/file.h" -#include "pal/printfcpp.hpp" - -#include -#include -#include -#include -#include - -SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/*++ -Function: - _fullpath - -See MSDN doc. - ---*/ -char * -__cdecl -_fullpath( - char *absPath, - const char *relPath, - size_t maxLength) -{ - char realpath_buf[PATH_MAX+1]; - char path_copy[PATH_MAX+1]; - char *retval = NULL; - DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]); - size_t min_length; - BOOL fBufAllocated = FALSE; - - PERF_ENTRY(_fullpath); - ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n", - absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); - - if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS) - { - TRACE("_fullpath: strncpy_s failed!\n"); - goto fullpathExit; - } - - FILEDosToUnixPathA(path_copy); - - if(NULL == realpath(path_copy, realpath_buf)) - { - ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n", - realpath_buf, errno, strerror(errno)); - goto fullpathExit; - } - - TRACE("real path is %s\n", realpath_buf); - min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator - - if(NULL == absPath) - { - absPath = static_cast( - PAL_malloc(_MAX_PATH * sizeof(char))); - if (!absPath) - { - ERROR("PAL_malloc failed with error %d\n", errno); - goto fullpathExit; - } - maxLength = _MAX_PATH; - fBufAllocated = TRUE; - } - - if(min_length > maxLength) - { - ERROR("maxLength is %lu, we need at least %lu\n", - maxLength, min_length); - if (fBufAllocated) - { - PAL_free(absPath); - fBufAllocated = FALSE; - } - goto fullpathExit; - } - - strcpy_s(absPath, maxLength, realpath_buf); - retval = absPath; - -fullpathExit: - LOGEXIT("_fullpath returns char * %p\n", retval); - PERF_EXIT(_fullpath); - return retval; -} - - - diff --git a/src/coreclr/pal/src/cruntime/printfcpp.cpp b/src/coreclr/pal/src/cruntime/printfcpp.cpp index d7e992c090a00..fee79c91df12b 100644 --- a/src/coreclr/pal/src/cruntime/printfcpp.cpp +++ b/src/coreclr/pal/src/cruntime/printfcpp.cpp @@ -86,7 +86,7 @@ static int Internal_Convertfwrite(CPalThread *pthrCurrent, const void *buffer, s free(newBuff); return -1; } - ret = InternalFwrite(newBuff, 1, count, stream, &iError); + ret = InternalFwrite(newBuff, 1, nsize, stream, &iError); if (iError != 0) { ERROR("InternalFwrite did not write the whole buffer. Error is %d\n", iError); diff --git a/src/coreclr/pal/src/cruntime/wchar.cpp b/src/coreclr/pal/src/cruntime/wchar.cpp index 5c21d7bd01533..3d887aecdb883 100644 --- a/src/coreclr/pal/src/cruntime/wchar.cpp +++ b/src/coreclr/pal/src/cruntime/wchar.cpp @@ -3,8 +3,6 @@ /*++ - - Module Name: wchar.c @@ -13,11 +11,8 @@ Module Name: Implementation of wide char string functions. - - --*/ - #include "pal/palinternal.h" #include "pal/cruntime.h" #include "pal/dbgmsg.h" @@ -25,7 +20,6 @@ Module Name: #include "pal/thread.hpp" #include "pal/threadsusp.hpp" - #if HAVE_CONFIG_H #include "config.h" #endif @@ -950,46 +944,3 @@ PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) PERF_EXIT(wcstod); return RetVal; } - -/*++ -Function: - PAL_wcscspn - -Finds the number of consecutive characters from the start of the string -that are not in the set. - -Return value: - -The number of characters from the start of the string that are not in -the set. - -Parameters: -string String -strCharSet Set of delimiter characters - ---*/ -size_t -__cdecl -PAL_wcscspn(const wchar_16 *string, const wchar_16 *strCharSet) -{ - const wchar_16 *temp; - size_t count = 0; - - PERF_ENTRY(wcscspn); - - while(*string != 0) - { - for(temp = strCharSet; *temp != 0; temp++) - { - if (*string == *temp) - { - PERF_EXIT(wcscspn); - return count; - } - } - count++; - string++; - } - PERF_EXIT(wcscspn); - return count; -} diff --git a/src/coreclr/pal/src/cruntime/wchartls.cpp b/src/coreclr/pal/src/cruntime/wchartls.cpp deleted file mode 100644 index 35b73359889a5..0000000000000 --- a/src/coreclr/pal/src/cruntime/wchartls.cpp +++ /dev/null @@ -1,125 +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: - - wchartls.c - -Abstract: - - Implementation of wide char string functions that depend on per-thread data - - - ---*/ - -#include "pal/palinternal.h" -#include "pal/thread.hpp" -#include "pal/dbgmsg.h" - -using namespace CorUnix; - - -SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/*++ -Function: - PAL_wcstok - -Finds the next token in a wide character string. - -Return value: - -A pointer to the next token found in strToken. Returns NULL when no more -tokens are found. Each call modifies strToken by substituting a NULL -character for each delimiter that is encountered. - -Parameters: -strToken String containing token(s) -strDelimit Set of delimiter characters - ---*/ -WCHAR * -__cdecl -PAL_wcstok(WCHAR *strToken, const WCHAR *strDelimit) -{ - CPalThread *pThread = NULL; - WCHAR *retval = NULL; - WCHAR *delim_ptr; - WCHAR *next_context; /* string to save in TLS for future calls */ - - PERF_ENTRY(wcstok); - ENTRY("PAL_wcstok (strToken=%p (%S), strDelimit=%p (%S))\n", - strToken?strToken:W16_NULLSTRING, - strToken?strToken:W16_NULLSTRING, - strDelimit?strDelimit:W16_NULLSTRING, - strDelimit?strDelimit:W16_NULLSTRING); - - /* Get the per-thread buffer from the thread structure. */ - pThread = InternalGetCurrentThread(); - - if(NULL == strDelimit) - { - ERROR("delimiter string is NULL\n"); - goto done; - } - - /* get token string from TLS if none is provided */ - if(NULL == strToken) - { - TRACE("wcstok() called with NULL string, using previous string\n"); - strToken = pThread->crtInfo.wcstokContext; - if(NULL == strToken) - { - ERROR("wcstok called with NULL string without a previous call\n"); - goto done; - } - } - - /* first, skip all leading delimiters */ - while ((*strToken != '\0') && (PAL_wcschr(strDelimit,*strToken))) - { - strToken++; - } - - /* if there were only delimiters, there's no string */ - if('\0' == strToken[0]) - { - TRACE("end of string already reached, returning NULL\n"); - goto done; - } - - /* we're now at the beginning of the token; look for the first delimiter */ - delim_ptr = PAL_wcspbrk(strToken,strDelimit); - if(NULL == delim_ptr) - { - TRACE("no delimiters found, this is the last token\n"); - /* place the next context at the end of the string, so that subsequent - calls will return NULL */ - next_context = strToken+PAL_wcslen(strToken); - retval = strToken; - } - else - { - /* null-terminate current token */ - *delim_ptr=0; - - /* place the next context right after the delimiter */ - next_context = delim_ptr+1; - retval = strToken; - - TRACE("found delimiter; next token will be %p\n",next_context); - } - - pThread->crtInfo.wcstokContext = next_context; - -done: - LOGEXIT("PAL_wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); - PERF_EXIT(wcstok); - return(retval); -} - diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index e5aebdf652c6a..eca89e0a204c6 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -369,19 +369,13 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE { CPalThread *pThread = InternalGetCurrentThread(); - CONTEXT *contextRecord; - EXCEPTION_RECORD *exceptionRecord; - AllocateExceptionRecords(&exceptionRecord, &contextRecord); + CONTEXT *contextRecord = pContext; + g_hardware_exception_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0)); - *contextRecord = *pContext; - *exceptionRecord = *pExRecord; - - contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + pContext->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; bool continueExecution; - { - // The exception object takes ownership of the exceptionRecord and contextRecord - PAL_SEHException exception(exceptionRecord, contextRecord); + PAL_SEHException exception(pExRecord, pContext, true); TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress); @@ -389,8 +383,8 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE if (continueExecution) { // Make a copy of the exception records so that we can free them before restoring the context - *pContext = *contextRecord; - *pExRecord = *exceptionRecord; + *pContext = *exception.ExceptionPointers.ContextRecord; + *pExRecord = *exception.ExceptionPointers.ExceptionRecord; } // The exception records are destroyed by the PAL_SEHException destructor now. diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 4b149f941b5dc..3091650ec5faa 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -496,7 +496,9 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL #ifndef HOST_WINDOWS -extern int g_common_signal_handler_context_locvar_offset; +// Frame pointer relative offset of a local containing a pointer to the windows style context of a location +// where a hardware exception occured. +int g_hardware_exception_context_locvar_offset = 0; BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers) { @@ -506,19 +508,17 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP DWORD64 curPc = CONTEXTGetPC(context); -#ifndef __APPLE__ - // Check if the PC is the return address from the SEHProcessException in the common_signal_handler. - // If that's the case, extract its local variable containing the windows style context of the hardware + // Check if the PC is the return address from the SEHProcessException. + // If that's the case, extract its local variable containing a pointer to the windows style context of the hardware // exception and return that. This skips the hardware signal handler trampoline that the libunwind - // cannot cross on some systems. + // cannot cross on some systems. On macOS, it skips a similar trampoline we create in HijackFaultingThread. if ((void*)curPc == g_SEHProcessExceptionReturnAddress) { - CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); - memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT)); + CONTEXT* exceptionContext = *(CONTEXT**)(CONTEXTGetFP(context) + g_hardware_exception_context_locvar_offset); + memcpy_s(context, sizeof(CONTEXT), exceptionContext, sizeof(CONTEXT)); return TRUE; } -#endif if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0) { @@ -699,7 +699,7 @@ PAL_FreeExceptionRecords(IN EXCEPTION_RECORD *exceptionRecord, IN CONTEXT *conte Note: The name of this function and the name of the ExceptionRecord parameter is used in the sos lldb plugin code to read the exception - record. See coreclr\ToolBox\SOS\lldbplugin\services.cpp. + record. See coreclr\tools\SOS\lldbplugin\services.cpp. This function must not be inlined or optimized so the below PAL_VirtualUnwind calls end up with RaiseException caller's context and so the above debugger diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 521150530fa33..63b7ef115f26d 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -116,10 +116,6 @@ struct sigaction g_previous_sigabrt; #if !HAVE_MACH_EXCEPTIONS -// Offset of the local variable containing pointer to windows style context in the common_signal_handler function. -// This offset is relative to the frame pointer. -int g_common_signal_handler_context_locvar_offset = 0; - // TOP of special stack for handling stack overflow volatile void* g_stackOverflowHandlerStack = NULL; @@ -240,8 +236,11 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags) } #ifdef INJECT_ACTIVATION_SIGNAL - handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation); - g_registered_activation_handler = true; + if (flags & PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL) + { + handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation); + g_registered_activation_handler = true; + } #endif return TRUE; @@ -939,11 +938,12 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext #if !HAVE_MACH_EXCEPTIONS sigset_t signal_set; CONTEXT signalContextRecord; + CONTEXT* signalContextRecordPtr = &signalContextRecord; EXCEPTION_RECORD exceptionRecord; native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; - g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); + g_hardware_exception_context_locvar_offset = (int)((char*)&signalContextRecordPtr - (char*)__builtin_frame_address(0)); if (code == (SIGSEGV | StackOverflowFlag)) { diff --git a/src/coreclr/pal/src/include/pal/modulename.h b/src/coreclr/pal/src/include/pal/modulename.h deleted file mode 100644 index 87d54b77a5b95..0000000000000 --- a/src/coreclr/pal/src/include/pal/modulename.h +++ /dev/null @@ -1,35 +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: - - include/pal/modulename.h - -Abstract: - Header file for functions to get the name of a module - -Revision History: - - - ---*/ - -#ifndef _PAL_MODULENAME_H_ -#define _PAL_MODULENAME_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - -const char *PAL_dladdr(LPVOID ProcAddress); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /*_PAL_MODULENAME_H_*/ diff --git a/src/coreclr/pal/src/include/pal/palinternal.h b/src/coreclr/pal/src/include/pal/palinternal.h index 3a12d78910364..ff3703c6ae4f7 100644 --- a/src/coreclr/pal/src/include/pal/palinternal.h +++ b/src/coreclr/pal/src/include/pal/palinternal.h @@ -526,8 +526,6 @@ function_name() to call the system's implementation #undef wcsstr #undef wcscmp #undef wcsncpy -#undef wcstok -#undef wcscspn #undef iswupper #undef iswspace #undef towlower diff --git a/src/coreclr/pal/src/include/pal/seh.hpp b/src/coreclr/pal/src/include/pal/seh.hpp index 6ad89df0fdd65..327fe0d7fb03e 100644 --- a/src/coreclr/pal/src/include/pal/seh.hpp +++ b/src/coreclr/pal/src/include/pal/seh.hpp @@ -145,5 +145,10 @@ CorUnix::PAL_ERROR SEHDisable(CorUnix::CPalThread *pthrCurrent); } +// Offset of the local variable containing pointer to windows style context in the common_signal_handler / PAL_DispatchException function. +// This offset is relative to the frame pointer. +extern int g_hardware_exception_context_locvar_offset; + + #endif /* _PAL_SEH_HPP_ */ diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 5469b4bebd483..951680114d886 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -1242,7 +1242,7 @@ static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv) return NULL; } - if(!MultiByteToWideChar(CP_ACP, 0,command_line, i, retval, i)) + if(!MultiByteToWideChar(CP_ACP, 0,command_line, -1, retval, i)) { ASSERT("MultiByteToWideChar failure\n"); free(retval); diff --git a/src/coreclr/pal/src/libunwind/CMakeLists.txt b/src/coreclr/pal/src/libunwind/CMakeLists.txt index 17659432fd0e4..dfcd140a89a5b 100644 --- a/src/coreclr/pal/src/libunwind/CMakeLists.txt +++ b/src/coreclr/pal/src/libunwind/CMakeLists.txt @@ -19,6 +19,7 @@ add_definitions(-D_GNU_SOURCE) add_definitions(-DPACKAGE_STRING="") add_definitions(-DPACKAGE_BUGREPORT="") + if(CLR_CMAKE_HOST_UNIX) if (CLR_CMAKE_HOST_ARCH_AMD64) set(arch x86_64) @@ -26,6 +27,8 @@ if(CLR_CMAKE_HOST_UNIX) set(arch aarch64) elseif(CLR_CMAKE_HOST_ARCH_ARM) set(arch arm) + elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + set(arch arm) elseif(CLR_CMAKE_HOST_ARCH_I386) set(arch x86) elseif(CLR_CMAKE_HOST_ARCH_S390X) @@ -45,7 +48,7 @@ if(CLR_CMAKE_HOST_UNIX) add_compile_options(-Wno-incompatible-pointer-types) endif() - if(CLR_CMAKE_HOST_ARCH_ARM) + if(CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARMV6) # Ensure that the remote and local unwind code can reside in the same binary without name clashing add_definitions("-Darm_search_unwind_table=UNW_OBJ(arm_search_unwind_table)") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -109,6 +112,10 @@ if(CLR_CMAKE_HOST_WIN32) set(TARGET_ARM 1) set(arch arm) add_definitions(-D__arm__) + elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + set(TARGET_ARM 1) + set(arch arm) + add_definitions(-D__arm__) elseif(CLR_CMAKE_TARGET_ARCH_S390X) set(TARGET_S390X 1) set(arch s390x) @@ -155,7 +162,7 @@ if(CLR_CMAKE_HOST_WIN32) add_compile_options(-wd4477) # fprintf argument type endif (CLR_CMAKE_HOST_WIN32) -if(CLR_CMAKE_TARGET_ARCH_ARM) +if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARMV6) # The arm sources include ex_tables.h from include/tdep-arm without going through a redirection # in include/tdep like it works for similar files on other architectures. So we need to add # the include/tdep-arm to include directories diff --git a/src/coreclr/pal/src/libunwind/src/CMakeLists.txt b/src/coreclr/pal/src/libunwind/src/CMakeLists.txt index b6dee4f413a80..17a30e027e03e 100644 --- a/src/coreclr/pal/src/libunwind/src/CMakeLists.txt +++ b/src/coreclr/pal/src/libunwind/src/CMakeLists.txt @@ -316,6 +316,11 @@ if(CLR_CMAKE_HOST_UNIX) SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) + elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm}) + SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) elseif(CLR_CMAKE_HOST_ARCH_I386) SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os}) SET(libunwind_remote_la_SOURCES ${libunwind_x86_la_SOURCES_x86}) @@ -363,6 +368,11 @@ else(CLR_CMAKE_HOST_UNIX) SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) + elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm}) + SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) elseif(CLR_CMAKE_TARGET_ARCH_I386) SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os}) SET(libunwind_remote_la_SOURCES ${libunwind_x86_la_SOURCES_x86}) diff --git a/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c b/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c index 74d42ffe2abb2..07bd4a73b276c 100644 --- a/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c +++ b/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c @@ -28,6 +28,8 @@ _OOP_find_proc_info ( int ret = 0; unw_dyn_info_t di; + memset(&di, 0, sizeof(di)); + di.start_ip = start_ip; di.end_ip = end_ip; di.gp = pi->gp; diff --git a/src/coreclr/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp index e792f75a2b22e..2a559b56e2bef 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -30,7 +30,6 @@ SET_DEFAULT_DEBUG_CHANNEL(LOADER); // some headers have code with asserts, so do #include "pal/file.h" #include "pal/utils.h" #include "pal/init.h" -#include "pal/modulename.h" #include "pal/environ.h" #include "pal/virtual.h" #include "pal/map.hpp" @@ -342,9 +341,10 @@ GetProcAddress( /* if we don't know the module's full name yet, this is our chance to obtain it */ if (!module->lib_name && module->dl_handle) { - const char* libName = PAL_dladdr((LPVOID)ProcAddress); - if (libName) + Dl_info dl_info; + if (dladdr((LPVOID)ProcAddress, &dl_info) != 0) { + const char* libName = dl_info.dli_fname; module->lib_name = UTIL_MBToWC_Alloc(libName, -1); if (nullptr == module->lib_name) { @@ -356,6 +356,10 @@ GetProcAddress( module, libName); } } + else + { + TRACE("GetProcAddress: dladdr() call failed!\n"); + } } } else @@ -925,7 +929,7 @@ struct CopyModuleDataParam int result; }; -void handle_image_range(uint8_t* source_start, size_t size, struct CopyModuleDataParam* param) +void handle_image_range(uint8_t* source_start, size_t size, struct CopyModuleDataParam* param) { uint8_t* source_end = source_start + size; if (param->destination_buffer_start != NULL) diff --git a/src/coreclr/pal/src/loader/modulename.cpp b/src/coreclr/pal/src/loader/modulename.cpp deleted file mode 100644 index 40c1c6de5c3d6..0000000000000 --- a/src/coreclr/pal/src/loader/modulename.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. - -/*++ - - - -Module Name: - - modulename.cpp - -Abstract: - - Implementation of internal functions to get module names - - - ---*/ - -#include "pal/thread.hpp" -#include "pal/malloc.hpp" -#include "pal/palinternal.h" -#include "pal/dbgmsg.h" -#include "pal/modulename.h" - -#include - -using namespace CorUnix; - -SET_DEFAULT_DEBUG_CHANNEL(LOADER); - -/*++ - PAL_dladdr - - Internal wrapper for dladder used only to get module name - -Parameters: - LPVOID ProcAddress: a pointer to a function in a shared library - -Return value: - Pointer to string with the fullpath to the shared library containing - ProcAddress. - - NULL if error occurred. - -Notes: - The string returned by this function is owned by the OS. - If you need to keep it, strdup() it, because it is unknown how long - this ptr will point at the string you want (over the lifetime of - the system running) It is only safe to use it immediately after calling - this function. ---*/ -const char *PAL_dladdr(LPVOID ProcAddress) -{ - Dl_info dl_info; - if (!dladdr(ProcAddress, &dl_info)) - { - WARN("dladdr() call failed!\n"); - /* If we get an error, return NULL */ - return (NULL); - } - else - { - /* Return the module name */ - return dl_info.dli_fname; - } -} - diff --git a/src/coreclr/pal/src/memory/local.cpp b/src/coreclr/pal/src/memory/local.cpp deleted file mode 100644 index fc62ef428b1e2..0000000000000 --- a/src/coreclr/pal/src/memory/local.cpp +++ /dev/null @@ -1,93 +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: - - local.c - -Abstract: - - Implementation of local memory management functions. - -Revision History: - - - ---*/ - -#include "pal/palinternal.h" -#include "pal/dbgmsg.h" - - -SET_DEFAULT_DEBUG_CHANNEL(MEM); - - -/*++ -Function: - LocalAlloc - -See MSDN doc. ---*/ -HLOCAL -PALAPI -LocalAlloc( - IN UINT uFlags, - IN SIZE_T uBytes) -{ - LPVOID lpRetVal = NULL; - PERF_ENTRY(LocalAlloc); - ENTRY("LocalAlloc (uFlags=%#x, uBytes=%u)\n", uFlags, uBytes); - - if ((uFlags & ~LMEM_ZEROINIT) != 0) - { - ASSERT("Invalid parameter AllocFlags=0x%x\n", uFlags); - SetLastError(ERROR_INVALID_PARAMETER); - goto done; - } - - lpRetVal = PAL_malloc(uBytes); - - if (lpRetVal == NULL) - { - ERROR("Not enough memory\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - - if ((uFlags & LMEM_ZEROINIT) != 0) - { - memset(lpRetVal, 0, uBytes); - } - -done: - LOGEXIT( "LocalAlloc returning %p.\n", lpRetVal ); - PERF_EXIT(LocalAlloc); - return (HLOCAL) lpRetVal; -} - -/*++ -Function: - LocalFree - -See MSDN doc. ---*/ -HLOCAL -PALAPI -LocalFree( - IN HLOCAL hMem) -{ - BOOL bRetVal = FALSE; - PERF_ENTRY(LocalFree); - ENTRY("LocalFree (hmem=%p)\n", hMem); - - free(hMem); - bRetVal = TRUE; - - LOGEXIT( "LocalFree returning %p.\n", bRetVal == TRUE ? (HLOCAL)NULL : hMem ); - PERF_EXIT(LocalFree); - return bRetVal == TRUE ? (HLOCAL)NULL : hMem; -} diff --git a/src/coreclr/pal/src/misc/fmtmessage.cpp b/src/coreclr/pal/src/misc/fmtmessage.cpp index 81502bfc7722e..e9d87d19c4a08 100644 --- a/src/coreclr/pal/src/misc/fmtmessage.cpp +++ b/src/coreclr/pal/src/misc/fmtmessage.cpp @@ -63,7 +63,7 @@ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) allocChars = MAX_ERROR_STRING_LENGTH + 1; } - LPWSTR lpRetVal = (LPWSTR)LocalAlloc(LMEM_FIXED, allocChars * sizeof(WCHAR)); + LPWSTR lpRetVal = (LPWSTR)PAL_malloc(allocChars * sizeof(WCHAR)); if (lpRetVal) { @@ -135,7 +135,7 @@ static INT FMTMSG__watoi( LPWSTR str ) UINT NumOfBytes = 0; \ nSize *= 2; \ NumOfBytes = nSize * sizeof( WCHAR ); \ - lpTemp = static_cast( LocalAlloc( LMEM_FIXED, NumOfBytes ) ); \ + lpTemp = static_cast( PAL_malloc( NumOfBytes ) ); \ TRACE( "Growing the buffer.\n" );\ \ if ( !lpTemp ) \ @@ -149,7 +149,7 @@ static INT FMTMSG__watoi( LPWSTR str ) \ *lpWorkingString = '\0';\ PAL_wcscpy( lpTemp, lpReturnString );\ - LocalFree( lpReturnString ); \ + free( lpReturnString ); \ lpWorkingString = lpReturnString = lpTemp; \ lpWorkingString += nCount; \ } \ @@ -341,7 +341,7 @@ FormatMessageW( /* Parameter processing. */ if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) { - TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to " + TRACE( "Allocated %d TCHARs. Don't forget to call free to " "free the memory when done.\n", nSize ); bIsLocalAlloced = TRUE; } @@ -418,7 +418,7 @@ FormatMessageW( } lpWorkingString = static_cast( - LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) ); + PAL_malloc( nSize * sizeof( WCHAR ) ) ); if ( !lpWorkingString ) { ERROR( "Unable to allocate memory for the working string.\n" ); @@ -675,14 +675,14 @@ FormatMessageW( { TRACE( "Copying the string into the buffer.\n" ); PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); - LocalFree( lpReturnString ); + free( lpReturnString ); } } else /* Error, something occurred. */ { if ( lpReturnString ) { - LocalFree( lpReturnString ); + free( lpReturnString ); } } LOGEXIT( "FormatMessageW returns %d.\n", nCount ); diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index f58757a1f6d5f..f14b2442afa78 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -415,7 +415,6 @@ add_executable_clr(paltests c_runtime/wcsstr/test1/test1.cpp c_runtime/wcstod/test1/test1.cpp c_runtime/wcstod/test2/test2.cpp - c_runtime/wcstok/test1/test1.cpp c_runtime/wcstoul/test1/test1.cpp c_runtime/wcstoul/test2/test2.cpp c_runtime/wcstoul/test3/test3.cpp @@ -581,9 +580,6 @@ add_executable_clr(paltests # filemapping_memmgt/GetProcAddress/test1/testlib.cpp filemapping_memmgt/GetProcAddress/test2/test2.cpp # filemapping_memmgt/GetProcAddress/test2/testlib.cpp - filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp - filemapping_memmgt/LocalFree/test1/LocalFree.cpp - filemapping_memmgt/LocalFree/test2/LocalFree.cpp filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp deleted file mode 100644 index 564466c2a4e7f..0000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Search for a number of tokens within strings. Check that the return values -** are what is expected, and also that the strings match up with our expected -** results. -** -** -**==========================================================================*/ - -#include - -PALTEST(c_runtime_wcstok_test1_paltest_wcstok_test1, "c_runtime/wcstok/test1/paltest_wcstok_test1") -{ - /* foo bar baz */ - WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z','\0'}; - - /* foo \0ar baz */ - WCHAR result1[] = {'f','o','o',' ','\0','a','r',' ','b','a','z','\0'}; - - /* foo \0a\0 baz */ - WCHAR result2[] = {'f','o','o',' ','\0','a','\0',' ','b','a','z','\0'}; - - WCHAR* tempString; - int len = 0; - WCHAR *ptr; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - len = (wcslen(str)*sizeof(WCHAR)) + 2; - - /* Tokenize 'str'. It will hit the 'b' delimiter first. Check to see - that the ptr is pointing to the start of the string and do a compare - to ensure the tokenized string is what we expected. - */ - - tempString = convert("bz"); - ptr = wcstok(str, tempString); - free(tempString); - - if (ptr != str) - { - Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str, ptr); - } - - if (memcmp(str, result1, len) != 0) - { - Fail("ERROR: wcstok altered the string in an unexpected fashion."); - } - - /* If NULL is passed as the first parameter, wcstok will continue - tokenizing the same string. Test that this works properly. - */ - tempString = convert("r "); - ptr = wcstok(NULL, tempString); - free(tempString); - - if (ptr != str + 5) - { - Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str+5, ptr); - } - - if (memcmp(str, result2, len) != 0) - { - Fail("ERROR: wcstok altered the string in an unexpected fashion."); - } - - /* Continue onward, and search for 'X' now, which won't be found. The - pointer should point just after the last NULL in the string. And - the string itself shouldn't have changed. - */ - tempString = convert("X"); - ptr = wcstok(NULL, tempString); - free(tempString); - - if (ptr != str + 7) - { - Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str + 7, ptr); - } - - if (memcmp(str, result2, len) != 0) - { - Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n"); - } - - /* Call wcstok again. Now the ptr should point to the end of the - string at NULL. And the string itself shouldn't have changed. - */ - tempString = convert("X"); - ptr = wcstok(NULL, tempString); - free(tempString); - - if (ptr != NULL) - { - Fail("ERROR: Expected wcstok() to return %p, got %p!\n", NULL, ptr); - } - - if (memcmp(str, result2, len) != 0) - { - Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n"); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt index c674de294db45..a7e27f9228976 100644 --- a/src/coreclr/pal/tests/palsuite/compilableTests.txt +++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt @@ -348,7 +348,6 @@ c_runtime/wcsrchr/test1/paltest_wcsrchr_test1 c_runtime/wcsstr/test1/paltest_wcsstr_test1 c_runtime/wcstod/test1/paltest_wcstod_test1 c_runtime/wcstod/test2/paltest_wcstod_test2 -c_runtime/wcstok/test1/paltest_wcstok_test1 c_runtime/wcstoul/test1/paltest_wcstoul_test1 c_runtime/wcstoul/test2/paltest_wcstoul_test2 c_runtime/wcstoul/test3/paltest_wcstoul_test3 @@ -487,9 +486,6 @@ filemapping_memmgt/GetModuleFileNameW/test1/paltest_getmodulefilenamew_test1 filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2 filemapping_memmgt/GetProcAddress/test1/paltest_getprocaddress_test1 filemapping_memmgt/GetProcAddress/test2/paltest_getprocaddress_test2 -filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1 -filemapping_memmgt/LocalFree/test1/paltest_localfree_test1 -filemapping_memmgt/LocalFree/test2/paltest_localfree_test2 filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1 filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2 filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3 diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp deleted file mode 100644 index 5879ed598071a..0000000000000 --- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: LocalAlloc.c -** -** Purpose: Positive test the LocalAlloc API. -** Call LocalAlloc with zero as the allocation attribute -** -** -**============================================================*/ -#include - -PALTEST(filemapping_memmgt_LocalAlloc_test1_paltest_localalloc_test1, "filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1") -{ - HLOCAL LocalHeap; - HLOCAL FreeHeap; - int err; - const SIZE_T heapSize = 64; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*Allocate the specified number of bytes from the heap*/ - /*with allocation attribute: zero which is required by PAL Doc*/ - LocalHeap = LocalAlloc(0, heapSize); - if(!LocalHeap) - { - Fail("\nFailed to call LocalAlloc API, " - "error code=%u\n", GetLastError()); - } - - /*Free the allocated local heap memory*/ - FreeHeap = LocalFree(LocalHeap); - if(FreeHeap) - { - Fail("Failed to call LocalFree API, " - "error code=%u\n", GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp deleted file mode 100644 index 0fcb32d6fc96f..0000000000000 --- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: LocalFree.c -** -** Purpose: Positive test the LocalFree API. -** Call LocalFree to free a specified local memory object -** -** -**============================================================*/ -#include - -PALTEST(filemapping_memmgt_LocalFree_test1_paltest_localfree_test1, "filemapping_memmgt/LocalFree/test1/paltest_localfree_test1") -{ - HLOCAL LocalHeap; - HLOCAL FreeHeap; - int err; - const SIZE_T heapSize = 64; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*Allocate the specified number of bytes from the heap*/ - /*with zero ad the allocation attribute*/ - LocalHeap = LocalAlloc(0, heapSize); - if(!LocalHeap) - { - Fail("\nFailed to call LocalAlloc API, " - "error code=%u\n", GetLastError()); - } - - /*Free the allocated local heap memory*/ - FreeHeap = LocalFree(LocalHeap); - if(FreeHeap) - { - Fail("Failed to call LocalFree API, " - "error code=%u\n", GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp deleted file mode 100644 index 5d66077a2cfd7..0000000000000 --- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: LocalFree.c -** -** Purpose: Positive test the LocalFree API. -** call LocalFree by passing NULL as local memory -** object handle -** -** -**============================================================*/ -#include - -PALTEST(filemapping_memmgt_LocalFree_test2_paltest_localfree_test2, "filemapping_memmgt/LocalFree/test2/paltest_localfree_test2") -{ - HLOCAL FreeHeap; - int err; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*call LocalFree by passing NULL as local memory object handle*/ - FreeHeap = LocalFree(NULL); - if(FreeHeap) - { - Fail("Failed to call LocalFree API, " - "error code=%u\n", GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp index d71e0ea85c333..93363488bc61d 100644 --- a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp +++ b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp @@ -7,9 +7,9 @@ ** ** Purpose: Positive test the LoadLibrary API. Test will verify ** that it is unable to load the library twice. Once by -** using the full path name and secondly by using the +** using the full path name and secondly by using the ** short name. -** +** ** **============================================================*/ @@ -25,14 +25,13 @@ typedef int (*dllfunct)(); #define GETATTACHCOUNTNAME "_GetAttachCount@0" #endif - /* Helper function to test the loaded library. */ BOOL PALAPI TestDll(HMODULE hLib) { int RetVal; char FunctName[] = GETATTACHCOUNTNAME; - FARPROC DllFunc; + FARPROC DllFunc; /* Access a function from the loaded library. */ @@ -45,7 +44,7 @@ BOOL PALAPI TestDll(HMODULE hLib) return (FALSE); } - /* Verify that the DLL_PROCESS_ATTACH is only + /* Verify that the DLL_PROCESS_ATTACH is only * accessed once.*/ RetVal = DllFunc(); if (RetVal != 1) @@ -70,7 +69,7 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar char fname[_MAX_FNAME]; char ext[_MAX_EXT]; - + /* Initialize the PAL. */ if ((PAL_Initialize(argc, argv)) != 0) @@ -84,15 +83,15 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar /* Get the full path to the library (DLL). */ - - if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) { - + + if (NULL != realpath(argv[0],fullpath)) { + _splitpath(fullPath,drive,dir,fname,ext); _makepath(fullPath,drive,dir,LibraryName,""); - - + + } else { - Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); + Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. realpath returned NULL\n",argv[0]); } /* Call Load library with the short name of @@ -101,11 +100,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar hShortLib = LoadLibrary(LibraryName); if(hShortLib == NULL) { - Fail("ERROR:%u:Unable to load library %s\n", - GetLastError(), + Fail("ERROR:%u:Unable to load library %s\n", + GetLastError(), LibraryName); } - + /* Test the loaded library. */ if (!TestDll(hShortLib)) @@ -120,8 +119,8 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar hFullLib = LoadLibrary(fullPath); if(hFullLib == NULL) { - Trace("ERROR:%u:Unable to load library %s\n", - GetLastError(), + Trace("ERROR:%u:Unable to load library %s\n", + GetLastError(), fullPath); iRetVal = FAIL; goto cleanUpTwo; @@ -141,11 +140,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar cleanUpTwo: - /* Call the FreeLibrary API. - */ + /* Call the FreeLibrary API. + */ if (!FreeLibrary(hFullLib)) { - Trace("ERROR:%u: Unable to free library \"%s\"\n", + Trace("ERROR:%u: Unable to free library \"%s\"\n", GetLastError(), fullPath); iRetVal = FAIL; @@ -153,11 +152,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar cleanUpOne: - /* Call the FreeLibrary API. - */ + /* Call the FreeLibrary API. + */ if (!FreeLibrary(hShortLib)) { - Trace("ERROR:%u: Unable to free library \"%s\"\n", + Trace("ERROR:%u: Unable to free library \"%s\"\n", GetLastError(), LibraryName); iRetVal = FAIL; @@ -167,5 +166,4 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar */ PAL_TerminateEx(iRetVal); return iRetVal; - } diff --git a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp index b489ef27f965e..1bbf9a6d08ad1 100644 --- a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp +++ b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp @@ -7,9 +7,9 @@ ** ** Purpose: Positive test the LoadLibrary API. Test will verify ** that it is unable to load the library twice. Once by -** using the full path name and secondly by using the +** using the full path name and secondly by using the ** short name. -** +** ** **============================================================*/ @@ -25,14 +25,13 @@ typedef int (*dllfunct)(); #define GETATTACHCOUNTNAME "_GetAttachCount@0" #endif - /* Helper function to test the loaded library. */ BOOL PALAPI TestDll(HMODULE hLib) { int RetVal; char FunctName[] = GETATTACHCOUNTNAME; - FARPROC DllFunc; + FARPROC DllFunc; /* Access a function from the loaded library. */ @@ -45,7 +44,7 @@ BOOL PALAPI TestDll(HMODULE hLib) return (FALSE); } - /* Verify that the DLL_PROCESS_ATTACH is only + /* Verify that the DLL_PROCESS_ATTACH is only * accessed once.*/ RetVal = DllFunc(); if (RetVal != 1) @@ -72,7 +71,7 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar char relTestDir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; - + BOOL bRc = FALSE; char relLibPath[_MAX_DIR]; @@ -89,15 +88,15 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar /* Get the full path to the library (DLL). */ - - if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) { - + + if (NULL != realpath(argv[0],fullpath)) { + _splitpath(fullPath,drive,dir,fname,ext); _makepath(fullPath,drive,dir,LibraryName,""); - - + + } else { - Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); + Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. realpath returned NULL\n",argv[0]); } /* Get relative path to the library @@ -112,11 +111,11 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar hShortLib = LoadLibrary(LibraryName); if(hShortLib == NULL) { - Fail("ERROR:%u:Short:Unable to load library %s\n", - GetLastError(), + Fail("ERROR:%u:Short:Unable to load library %s\n", + GetLastError(), LibraryName); } - + /* Test the loaded library. */ if (!TestDll(hShortLib)) @@ -131,8 +130,8 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar hFullLib = LoadLibrary(fullPath); if(hFullLib == NULL) { - Trace("ERROR:%u:Full:Unable to load library %s\n", - GetLastError(), + Trace("ERROR:%u:Full:Unable to load library %s\n", + GetLastError(), fullPath); iRetVal = FAIL; goto cleanUpTwo; @@ -148,14 +147,14 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar /* ** Call the load library with the relative path - ** wrt to the directory ./testloadlibrary/.. + ** wrt to the directory ./testloadlibrary/.. ** since we don't want to make any assumptions ** regarding the type of build */ hRelLib = LoadLibrary(relLibPath); if(hRelLib == NULL) { - Trace("ERROR:%u:Rel:Unable to load library at %s\n", + Trace("ERROR:%u:Rel:Unable to load library at %s\n", GetLastError(), relLibPath); iRetVal = FAIL; goto cleanUpTwo; @@ -190,12 +189,12 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar cleanUpThree: - /* Call the FreeLibrary API. - */ + /* Call the FreeLibrary API. + */ if (!FreeLibrary(hRelLib)) { - Trace("ERROR:%u: Unable to free library \"%s\"\n", + Trace("ERROR:%u: Unable to free library \"%s\"\n", GetLastError(), relLibPath); iRetVal = FAIL; @@ -203,11 +202,11 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar cleanUpTwo: - /* Call the FreeLibrary API. - */ + /* Call the FreeLibrary API. + */ if (!FreeLibrary(hFullLib)) { - Trace("ERROR:%u: Unable to free library \"%s\"\n", + Trace("ERROR:%u: Unable to free library \"%s\"\n", GetLastError(), fullPath); iRetVal = FAIL; @@ -215,20 +214,18 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar cleanUpOne: - /* Call the FreeLibrary API. - */ + /* Call the FreeLibrary API. + */ if (!FreeLibrary(hShortLib)) { - Trace("ERROR:%u: Unable to free library \"%s\"\n", + Trace("ERROR:%u: Unable to free library \"%s\"\n", GetLastError(), LibraryName); iRetVal = FAIL; } - /* Terminate the PAL. */ PAL_TerminateEx(iRetVal); return iRetVal; - } diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp index b16b0ea27754e..15d94411bb030 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp @@ -36,9 +36,9 @@ PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscel the error message it extracts is correct, only that it does place some information into the buffer when it is called. */ - + /* - + ERROR_SUCCESS (0L) is normally returned by GetLastError, But, the ERROR_SUCCESS is removed from messages for Unix based Systems To ensure that we have some information into the buffer we are using the message @@ -54,25 +54,25 @@ PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscel 0, /* maximum size of message buffer */ NULL /* array of message inserts */ ); - - if(ReturnResult == 0) + + if(ReturnResult == 0) { Fail("ERROR: The return value was 0, which indicates failure. The " "function failed when trying to Format a FROM_SYSTEM message."); } - - if(wcslen(OutBuffer) <= 0) + + if(wcslen(OutBuffer) <= 0) { Fail("ERROR: There are no characters in the buffer, and when the " "FORMAT_MESSAGE_FROM_SYSTEM flag is used with ERROR_FILE_NOT_FOUND error, " "something should be put into the buffer."); } - - LocalFree(OutBuffer); - + + free(OutBuffer); + PAL_Terminate(); return PASS; - + } diff --git a/src/coreclr/pal/tests/palsuite/paltestlist.txt b/src/coreclr/pal/tests/palsuite/paltestlist.txt index 2b9ac7ccd4eb1..2afdf101d5b68 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist.txt @@ -333,7 +333,6 @@ c_runtime/wcsrchr/test1/paltest_wcsrchr_test1 c_runtime/wcsstr/test1/paltest_wcsstr_test1 c_runtime/wcstod/test1/paltest_wcstod_test1 c_runtime/wcstod/test2/paltest_wcstod_test2 -c_runtime/wcstok/test1/paltest_wcstok_test1 c_runtime/wcstoul/test1/paltest_wcstoul_test1 c_runtime/wcstoul/test2/paltest_wcstoul_test2 c_runtime/wcstoul/test3/paltest_wcstoul_test3 @@ -449,9 +448,6 @@ filemapping_memmgt/CreateFileMappingW/test9/paltest_createfilemappingw_test9 filemapping_memmgt/FreeLibrary/test2/paltest_freelibrary_test2 filemapping_memmgt/GetModuleFileNameA/test2/paltest_getmodulefilenamea_test2 filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2 -filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1 -filemapping_memmgt/LocalFree/test1/paltest_localfree_test1 -filemapping_memmgt/LocalFree/test2/paltest_localfree_test2 filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1 filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2 filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3 diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj index 1127c3df8bdf3..36ed2ce497be1 100644 --- a/src/coreclr/runtime-prereqs.proj +++ b/src/coreclr/runtime-prereqs.proj @@ -7,7 +7,7 @@ - + diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 5f062c9af2f40..26801ea8c198c 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -48,6 +48,7 @@ <_CoreClrBuildArg Condition="'$(ClrAllJitsSubset)' == 'true'" Include="-component alljits" /> <_CoreClrBuildArg Condition="'$(ClrILToolsSubset)' == 'true'" Include="-component iltools" /> <_CoreClrBuildArg Condition="'$(ClrNativeAotSubset)' == 'true'" Include="-component nativeaot" /> + <_CoreClrBuildArg Condition="'$(ClrSpmiSubset)' == 'true'" Include="-component spmi" /> diff --git a/src/coreclr/scripts/jitrollingbuild.py b/src/coreclr/scripts/jitrollingbuild.py index 100aff85c3522..71e7d148a61d1 100644 --- a/src/coreclr/scripts/jitrollingbuild.py +++ b/src/coreclr/scripts/jitrollingbuild.py @@ -74,6 +74,13 @@ git_hash_help = "git hash" +use_latest_jit_change_help = """\ +Starting with the given git hash, look backwards in the git log for the first change that includes any JIT +change. We want to ensure that any git hash uploaded to the JIT rolling build store is a JIT change. This +addresses a problem where Azure DevOps sometimes builds changes that come soon after a JIT change, instead of +the JIT change itself. +""" + target_dir_help = "Directory to put the downloaded JIT." skip_cleanup_help = "Skip intermediate file removal." @@ -97,6 +104,7 @@ upload_parser = subparsers.add_parser("upload", description=upload_description, parents=[common_parser]) upload_parser.add_argument("-git_hash", required=True, help=git_hash_help) +upload_parser.add_argument("--use_latest_jit_change", action="store_true", help=use_latest_jit_change_help) upload_parser.add_argument("-az_storage_key", help="Key for the clrjit Azure Storage location. Default: use the value of the CLRJIT_AZ_KEY environment variable.") upload_parser.add_argument("--skip_cleanup", action="store_true", help=skip_cleanup_help) @@ -458,6 +466,32 @@ def upload_blob(file, blob_name): # pdb_paths = [os.path.join(pdb_dir, item) for item in os.listdir(pdb_dir) if re.match(r'.*clrjit.*', item)] # files += pdb_paths + # Figure out which git hash to use for the upload. By default, it is the required coreclr_args.git_hash argument. + # However, if "--use_latest_jit_change" is passed, we look backwards in the git log for the nearest git commit + # with a JIT change (it could, and often will be, the same as the argument git_hash). + jit_git_hash = coreclr_args.git_hash + + if coreclr_args.use_latest_jit_change: + # Do all the remaining commands, including a number of 'git' commands including relative paths, + # from the root of the runtime repo. + + with ChangeDir(coreclr_args.runtime_repo_location): + # Enumerate the last change, starting with the jit_git_hash, that included JIT changes. + command = [ "git", "log", "--pretty=format:%H", jit_git_hash, "-1", "--", "src/coreclr/jit/*" ] + print("Invoking: {}".format(" ".join(command))) + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + stdout_change_list, _ = proc.communicate() + return_code = proc.returncode + change_list_hashes = [] + if return_code == 0: + change_list_hashes = stdout_change_list.decode('utf-8').strip().splitlines() + + if len(change_list_hashes) == 0: + print("Couldn't find any JIT changes! Just using the argument git_hash") + else: + jit_git_hash = change_list_hashes[0] + print("Using git_hash {}".format(jit_git_hash)) + print("Uploading:") for item in files: print(" {}".format(item)) @@ -472,7 +506,7 @@ def upload_blob(file, blob_name): raise RuntimeError("Missing azure storage package.") blob_service_client = BlobServiceClient(account_url=az_blob_storage_account_uri, credential=coreclr_args.az_storage_key) - blob_folder_name = "{}/{}/{}/{}/{}".format(az_builds_root_folder, coreclr_args.git_hash, coreclr_args.host_os, coreclr_args.arch, coreclr_args.build_type) + blob_folder_name = "{}/{}/{}/{}/{}".format(az_builds_root_folder, jit_git_hash, coreclr_args.host_os, coreclr_args.arch, coreclr_args.build_type) total_bytes_uploaded = 0 @@ -684,6 +718,11 @@ def setup_spmi_location_arg(spmi_location): lambda unused: True, "Unable to set git_hash") + coreclr_args.verify(args, + "use_latest_jit_change", + lambda unused: True, + "Unable to set use_latest_jit_change") + coreclr_args.verify(args, "az_storage_key", lambda item: item is not None, diff --git a/src/coreclr/scripts/jitutil.py b/src/coreclr/scripts/jitutil.py index c7906124b45d4..5df464da5fc0c 100644 --- a/src/coreclr/scripts/jitutil.py +++ b/src/coreclr/scripts/jitutil.py @@ -85,12 +85,31 @@ def set_pipeline_variable(name, value): print(define_variable_format.format(name, value)) # set variable + ################################################################################ ## ## Helper functions ## ################################################################################ +def decode_string(str_to_decode): + """Decode a UTF-8 encoded bytes to string. + + Args: + str_to_decode (byte stream): Byte stream to decode + + Returns: + String output. If there any encoding/decoding errors, it will replace it with + UnicodeEncodeError. + """ + try: + output = str_to_decode.decode("utf-8", errors='replace') + except UnicodeEncodeError: + output = "UnicodeEncodeError" + except UnicodeDecodeError: + output = "UnicodeDecodeError" + return output + def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None): """ Runs the command. @@ -119,15 +138,15 @@ def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=Non if proc.poll() is not None: break if output: - output_str = output.strip().decode("utf-8") + output_str = decode_string(output.strip()) print(output_str) of.write(output_str + "\n") else: command_stdout, command_stderr = proc.communicate() if len(command_stdout) > 0: - print(command_stdout.decode("utf-8")) + print(decode_string(command_stdout)) if len(command_stderr) > 0: - print(command_stderr.decode("utf-8")) + print(decode_string(command_stderr)) return_code = proc.returncode if _exit_on_fail and return_code != 0: diff --git a/src/coreclr/scripts/superpmi-asmdiffs.proj b/src/coreclr/scripts/superpmi-asmdiffs.proj index aef782d769cb9..661a60aca831a 100644 --- a/src/coreclr/scripts/superpmi-asmdiffs.proj +++ b/src/coreclr/scripts/superpmi-asmdiffs.proj @@ -55,7 +55,8 @@ - + + diff --git a/src/coreclr/scripts/superpmi-collect.proj b/src/coreclr/scripts/superpmi-collect.proj index 963e117688f57..8d59a8218ae88 100644 --- a/src/coreclr/scripts/superpmi-collect.proj +++ b/src/coreclr/scripts/superpmi-collect.proj @@ -42,6 +42,14 @@ PmiAssembliesPayload - Path that will be sent to helix machine to run collection on PmiAssembliesDirectory - Path on helix machine itself where superpmi.py will discover the sent assemblies. --> + + + + + + + + %HELIX_PYTHONPATH% $(WorkItemDirectory)\pmiAssembliesDirectory @@ -54,7 +62,7 @@ %HELIX_WORKITEM_UPLOAD_ROOT% $(BUILD_SOURCESDIRECTORY)\artifacts\helixresults - $(SuperPMIDirectory)\superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)\pmi.dll + $(SuperPMIDirectory)\superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)\pmi.dll -pmi_path @(PmiPathDirectories->'$(SuperPMIDirectory)\%(Identity)', ' ') $HELIX_PYTHONPATH @@ -68,7 +76,7 @@ $HELIX_WORKITEM_UPLOAD_ROOT $(BUILD_SOURCESDIRECTORY)/artifacts/helixresults - $(SuperPMIDirectory)/superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)/pmi.dll + $(SuperPMIDirectory)/superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)/pmi.dll -pmi_path @(PmiPathDirectories->'$(SuperPMIDirectory)/%(Identity)', ' ') diff --git a/src/coreclr/scripts/superpmi-replay.proj b/src/coreclr/scripts/superpmi-replay.proj index e76a4a3d810e5..cac87c580fdde 100644 --- a/src/coreclr/scripts/superpmi-replay.proj +++ b/src/coreclr/scripts/superpmi-replay.proj @@ -55,7 +55,8 @@ - + + diff --git a/src/coreclr/scripts/superpmi.md b/src/coreclr/scripts/superpmi.md index d9404dc32d740..36e24711637ae 100644 --- a/src/coreclr/scripts/superpmi.md +++ b/src/coreclr/scripts/superpmi.md @@ -1,7 +1,7 @@ # Documentation for the superpmi.py tool SuperPMI is a tool for developing and testing the JIT compiler. -General information on SuperPMI can be found [here](../ToolBox/superpmi/readme.md). +General information on SuperPMI can be found [here](../tools/superpmi/readme.md). ## Overview diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 8433294a146d8..3c9d417f81cc0 100755 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -276,6 +276,7 @@ collect_parser.add_argument("-assemblies", dest="assemblies", nargs="+", default=[], help="A list of managed dlls or directories to recursively use while collecting with PMI or crossgen2. Required if --pmi or --crossgen2 is specified.") collect_parser.add_argument("-exclude", dest="exclude", nargs="+", default=[], help="A list of files or directories to exclude from the files and directories specified by `-assemblies`.") collect_parser.add_argument("-pmi_location", help="Path to pmi.dll to use during PMI run. Optional; pmi.dll will be downloaded from Azure Storage if necessary.") +collect_parser.add_argument("-pmi_path", metavar="PMIPATH_DIR", nargs='*', help="Specify a \"load path\" where assemblies can be found during pmi.dll run. Optional; the argument values are translated to PMIPATH environment variable.") collect_parser.add_argument("-output_mch_path", help="Location to place the final MCH file.") collect_parser.add_argument("--merge_mch_files", action="store_true", help="Merge multiple MCH files. Use the -mch_files flag to pass a list of MCH files to merge.") collect_parser.add_argument("-mch_files", metavar="MCH_FILE", nargs='+', help="Pass a sequence of MCH files which will be merged. Required by --merge_mch_files.") @@ -831,7 +832,14 @@ async def run_pmi(print_prefix, assembly, self): pmi_command_env = env_copy.copy() pmi_complus_env = complus_env.copy() pmi_complus_env["JitName"] = self.collection_shim_name - set_and_report_env(pmi_command_env, root_env, pmi_complus_env) + + if self.coreclr_args.pmi_path is not None: + pmi_root_env = root_env.copy() + pmi_root_env["PMIPATH"] = ";".join(self.coreclr_args.pmi_path) + else: + pmi_root_env = root_env + + set_and_report_env(pmi_command_env, pmi_root_env, pmi_complus_env) old_env = os.environ.copy() os.environ.update(pmi_command_env) @@ -3105,6 +3113,11 @@ def verify_replay_common_args(): lambda unused: True, "Unable to set tiered_compilation") + coreclr_args.verify(args, + "pmi_path", + lambda unused: True, + "Unable to set pmi_path") + if (args.collection_command is None) and (args.pmi is False) and (args.crossgen2 is False): print("Either a collection command or `--pmi` or `--crossgen2` must be specified") sys.exit(1) @@ -3121,6 +3134,12 @@ def verify_replay_common_args(): print("Specify `-assemblies` if `--pmi` or `--crossgen2` is given") sys.exit(1) + if not args.pmi: + if args.pmi_path is not None: + logging.warning("Warning: -pmi_path is set but --pmi is not.") + if args.pmi_location is not None: + logging.warning("Warning: -pmi_location is set but --pmi is not.") + if args.collection_command is None and args.merge_mch_files is not True: assert args.collection_args is None assert (args.pmi is True) or (args.crossgen2 is True) diff --git a/src/coreclr/tools/CMakeLists.txt b/src/coreclr/tools/CMakeLists.txt index a50b1e6a1afbd..db59797e26f78 100644 --- a/src/coreclr/tools/CMakeLists.txt +++ b/src/coreclr/tools/CMakeLists.txt @@ -1,3 +1,6 @@ +add_subdirectory(SOS) +add_subdirectory(superpmi) + if (CLR_CMAKE_TARGET_WIN32 AND NOT CLR_CMAKE_CROSS_ARCH) add_subdirectory(GenClrDebugResource) add_subdirectory(InjectResource) diff --git a/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs b/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs index b246a9847f227..5357e2f68234b 100644 --- a/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs +++ b/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs @@ -24,6 +24,7 @@ public abstract partial class CompilationBuilder protected IEnumerable _compilationRoots = Array.Empty(); protected OptimizationMode _optimizationMode = OptimizationMode.None; protected int _parallelism = -1; + protected bool _resilient; public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler) { @@ -72,6 +73,12 @@ public CompilationBuilder UseOptimizationMode(OptimizationMode mode) return this; } + public CompilationBuilder UseResilience(bool resilient) + { + _resilient = resilient; + return this; + } + public abstract CompilationBuilder UseBackendOptions(IEnumerable options); public abstract CompilationBuilder UseILProvider(ILProvider ilProvider); diff --git a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs index fa0828fc034e8..029949cda3846 100644 --- a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs +++ b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs @@ -157,7 +157,7 @@ public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAc try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); @@ -174,12 +174,9 @@ public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAc } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/tools/Common/Compiler/Logger.cs b/src/coreclr/tools/Common/Compiler/Logger.cs index eb77c7cd681e1..5ecd5e846c4be 100644 --- a/src/coreclr/tools/Common/Compiler/Logger.cs +++ b/src/coreclr/tools/Common/Compiler/Logger.cs @@ -10,6 +10,7 @@ using Internal.TypeSystem.Ecma; using ILCompiler.Logging; +using ILLink.Shared; using ILSequencePoint = Internal.IL.ILSequencePoint; using MethodIL = Internal.IL.MethodIL; @@ -47,6 +48,13 @@ public Logger(TextWriter writer, bool isVerbose) { } + public void LogMessage(string message) + { + MessageContainer? messageContainer = MessageContainer.CreateInfoMessage(message); + if(messageContainer.HasValue) + Writer.WriteLine(messageContainer.Value.ToMSBuildString()); + } + public void LogWarning(string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { MessageContainer? warning = MessageContainer.CreateWarningMessage(this, text, code, origin, subcategory); @@ -54,14 +62,19 @@ public void LogWarning(string text, int code, MessageOrigin origin, string subca Writer.WriteLine(warning.Value.ToMSBuildString()); } - public void LogWarning(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) + public void LogWarning(MessageOrigin origin, DiagnosticId id, params string[] args) { - MessageOrigin messageOrigin = new MessageOrigin(origin); - MessageContainer? warning = MessageContainer.CreateWarningMessage(this, text, code, messageOrigin, subcategory); + MessageContainer? warning = MessageContainer.CreateWarningMessage(this, origin, id, args); if (warning.HasValue) Writer.WriteLine(warning.Value.ToMSBuildString()); } + public void LogWarning(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) => + LogWarning(text, code, new MessageOrigin(origin), subcategory); + + public void LogWarning(TypeSystemEntity origin, DiagnosticId id, params string[] args) => + LogWarning(new MessageOrigin(origin), id, args); + public void LogWarning(string text, int code, MethodIL origin, int ilOffset, string subcategory = MessageSubCategory.None) { string document = null; @@ -86,12 +99,62 @@ public void LogWarning(string text, int code, MethodIL origin, int ilOffset, str LogWarning(text, code, messageOrigin, subcategory); } + public void LogWarning(MethodIL origin, int ilOffset, DiagnosticId id, params string[] args) + { + string document = null; + int? lineNumber = null; + + IEnumerable sequencePoints = origin.GetDebugInfo()?.GetSequencePoints(); + if (sequencePoints != null) + { + foreach (var sequencePoint in sequencePoints) + { + if (sequencePoint.Offset <= ilOffset) + { + document = sequencePoint.Document; + lineNumber = sequencePoint.LineNumber; + } + } + } + + MethodDesc warnedMethod = CompilerGeneratedState.GetUserDefinedMethodForCompilerGeneratedMember(origin.OwningMethod) ?? origin.OwningMethod; + + MessageOrigin messageOrigin = new MessageOrigin(warnedMethod, document, lineNumber, null); + LogWarning(messageOrigin, id, args); + } + public void LogWarning(string text, int code, string origin, string subcategory = MessageSubCategory.None) { MessageOrigin _origin = new MessageOrigin(origin); LogWarning(text, code, _origin, subcategory); } + public void LogWarning(string origin, DiagnosticId id, params string[] args) + { + MessageOrigin _origin = new MessageOrigin(origin); + LogWarning(_origin, id, args); + } + + public void LogError(string text, int code, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null) + { + MessageContainer? error = MessageContainer.CreateErrorMessage(text, code, subcategory, origin); + if (error.HasValue) + Writer.WriteLine(error.Value.ToMSBuildString()); + } + + public void LogError(MessageOrigin? origin, DiagnosticId id, params string[] args) + { + MessageContainer? error = MessageContainer.CreateErrorMessage(origin, id, args); + if (error.HasValue) + Writer.WriteLine(error.Value.ToMSBuildString()); + } + + public void LogError(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) => + LogError(text, code, subcategory, new MessageOrigin(origin)); + + public void LogError(TypeSystemEntity origin, DiagnosticId id, params string[] args) => + LogError(new MessageOrigin(origin), id, args); + internal bool IsWarningSuppressed(int code, MessageOrigin origin) { // This is causing too much noise @@ -167,7 +230,7 @@ internal bool IsSingleWarn(ModuleDesc owningModule, string messageSubcategory) { if (_trimWarnedAssemblies.Add(assemblyName)) { - LogWarning($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, GetModuleFileName(owningModule)); + LogWarning(GetModuleFileName(owningModule), DiagnosticId.AssemblyProducedTrimWarnings, assemblyName); } } } @@ -177,12 +240,12 @@ internal bool IsSingleWarn(ModuleDesc owningModule, string messageSubcategory) { if (_aotWarnedAssemblies.Add(assemblyName)) { - LogWarning($"Assembly '{assemblyName}' produced AOT analysis warnings.", 3053, GetModuleFileName(owningModule)); + LogWarning(GetModuleFileName(owningModule), DiagnosticId.AssemblyProducedAOTWarnings, assemblyName); } } } } - + return result; } @@ -198,11 +261,4 @@ private static string GetModuleFileName(ModuleDesc module) return assemblyName; } } - - public static class MessageSubCategory - { - public const string None = ""; - public const string TrimAnalysis = "Trim analysis"; - public const string AotAnalysis = "AOT analysis"; - } } diff --git a/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs b/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs index 95ed5bf04fa0c..060315e345555 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs @@ -6,6 +6,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler.Logging @@ -65,6 +67,22 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin return new MessageContainer(MessageCategory.Error, text, code, subcategory, origin); } + /// + /// Create an error message. + /// + /// Filename, line, and column where the error was found + /// Unique error ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of errors and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Error' category + internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, DiagnosticId id, params string[] args) + { + if (!((int)id >= 1000 && (int)id <= 2000)) + throw new ArgumentOutOfRangeException(nameof(id), $"The provided code '{(int)id}' does not fall into the error category, which is in the range of 1000 to 2000 (inclusive)."); + + return new MessageContainer(MessageCategory.Error, id, origin: origin, args: args); + } + /// /// Create a warning message. /// @@ -79,12 +97,29 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin /// New MessageContainer of 'Warning' category internal static MessageContainer? CreateWarningMessage(Logger context, string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { - //if (!(code > 2000 && code <= 6000)) - // throw new ArgumentOutOfRangeException(nameof(code), $"The provided code '{code}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + if (!(code > 2000 && code <= 6000)) + throw new ArgumentOutOfRangeException(nameof(code), $"The provided code '{code}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); return CreateWarningMessageContainer(context, text, code, origin, subcategory); } + /// + /// Create a warning message. + /// + /// Context with the relevant warning suppression info. + /// Filename or member where the warning is coming from + /// Unique warning ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of warnings and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Warning' category + internal static MessageContainer? CreateWarningMessage(Logger context, MessageOrigin origin, DiagnosticId id, params string[] args) + { + if (!((int)id > 2000 && (int)id <= 6000)) + throw new ArgumentOutOfRangeException(nameof(id), $"The provided code '{(int)id}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + + return CreateWarningMessageContainer(context, origin, id, id.GetDiagnosticSubcategory(), args); + } + private static MessageContainer? CreateWarningMessageContainer(Logger context, string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { if (context.IsWarningSuppressed(code, origin)) @@ -99,6 +134,20 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin return new MessageContainer(MessageCategory.Warning, text, code, subcategory, origin); } + private static MessageContainer? CreateWarningMessageContainer(Logger context, MessageOrigin origin, DiagnosticId id, string subcategory, params string[] args) + { + if (context.IsWarningSuppressed((int)id, origin)) + return null; + + if (TryLogSingleWarning(context, (int)id, origin, subcategory)) + return null; + + if (context.IsWarningAsError((int)id)) + return new MessageContainer(MessageCategory.WarningAsError, id, subcategory, origin, args); + + return new MessageContainer(MessageCategory.Warning, id, subcategory, origin, args); + } + private static bool TryLogSingleWarning(Logger context, int code, MessageOrigin origin, string subcategory) { if (subcategory != MessageSubCategory.AotAnalysis && subcategory != MessageSubCategory.TrimAnalysis) @@ -135,7 +184,7 @@ private static bool TryLogSingleWarning(Logger context, int code, MessageOrigin private static bool IsTrimmableAssembly(ModuleDesc assembly) { if (assembly is EcmaAssembly ecmaAssembly) - { + { foreach (var attribute in ecmaAssembly.GetDecodedCustomAttributes("System.Reflection", "AssemblyMetadataAttribute")) { if (attribute.FixedArguments.Length != 2) @@ -193,6 +242,15 @@ private MessageContainer(MessageCategory category, string text, int? code, strin Text = text; } + private MessageContainer(MessageCategory category, DiagnosticId id, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null, params string[] args) + { + Code = (int)id; + Category = category; + Origin = origin; + SubCategory = subcategory; + Text = new DiagnosticString(id).GetMessage(args); + } + public override string ToString() => ToMSBuildString(); public string ToMSBuildString() @@ -238,7 +296,7 @@ public string ToMSBuildString() { if (Origin?.MemberDefinition is MethodDesc method) sb.Append(method.GetDisplayName()); - else + else sb.Append(Origin?.MemberDefinition.ToString()); sb.Append(": "); diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs index 34821288b76d9..3c22da1f5478b 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using ILLink.Shared; using Mono.Cecil; namespace Mono.Linker @@ -41,15 +42,11 @@ void PopulateCacheForType (TypeDefinition type) case "AsyncIteratorStateMachineAttribute": case "AsyncStateMachineAttribute": case "IteratorStateMachineAttribute": - TypeDefinition stateMachineType = GetFirstConstructorArgumentAsType (attribute); + TypeDefinition? stateMachineType = GetFirstConstructorArgumentAsType (attribute); if (stateMachineType != null) { if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd (stateMachineType, method)) { var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType]; - _context.LogWarning ( - $"Methods '{method.GetDisplayName ()}' and '{alreadyAssociatedMethod.GetDisplayName ()}' are both associated with state machine type '{stateMachineType.GetDisplayName ()}'. This is currently unsupported and may lead to incorrectly reported warnings.", - 2107, - new MessageOrigin (method), - MessageSubCategory.TrimAnalysis); + _context.LogWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), stateMachineType.GetDisplayName ()); } } @@ -59,7 +56,7 @@ void PopulateCacheForType (TypeDefinition type) } } - static TypeDefinition GetFirstConstructorArgumentAsType (CustomAttribute attribute) + static TypeDefinition? GetFirstConstructorArgumentAsType (CustomAttribute attribute) { if (!attribute.HasConstructorArguments) return null; @@ -67,13 +64,13 @@ static TypeDefinition GetFirstConstructorArgumentAsType (CustomAttribute attribu return attribute.ConstructorArguments[0].Value as TypeDefinition; } - public MethodDefinition GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) + public MethodDefinition? GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) { if (sourceMember == null) return null; TypeDefinition compilerGeneratedType = (sourceMember as TypeDefinition) ?? sourceMember.DeclaringType; - if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition userDefinedMethod)) + if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition? userDefinedMethod)) return userDefinedMethod; // Only handle async or iterator state machine diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs index ed4763b75cda8..65211abd93c07 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs @@ -1,6 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; @@ -147,7 +146,10 @@ public void VisitTypeReference (TypeReference typeReference, StringBuilder build } if (typeReference.IsNested) { - VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver), builder, resolver); + Debug.Assert (typeReference is not SentinelType && typeReference is not PinnedType); + // GetInflatedDeclaringType may return null for generic parameters, byrefs, and pointers, but these + // are separately handled above. + VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver)!, builder, resolver); builder.Append ('.'); } diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs index 923197f58b6bf..8a6594e47f205 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable enable using System; using System.Collections.Generic; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs index f0a4afd09b187..69fb968c4ef9c 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text; +using ILLink.Shared; using Mono.Cecil; namespace Mono.Linker @@ -54,6 +55,22 @@ internal static MessageContainer CreateErrorMessage (string text, int code, stri return new MessageContainer (MessageCategory.Error, text, code, subcategory, origin); } + /// + /// Create an error message. + /// + /// Filename, line, and column where the error was found + /// Unique error ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of errors and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Error' category + internal static MessageContainer CreateErrorMessage (MessageOrigin? origin, DiagnosticId id, params string[] args) + { + if (!((int) id >= 1000 && (int) id <= 2000)) + throw new ArgumentOutOfRangeException (nameof (id), $"The provided code '{(int) id}' does not fall into the error category, which is in the range of 1000 to 2000 (inclusive)."); + + return new MessageContainer (MessageCategory.Error, id, origin: origin, args: args); + } + /// /// Create a custom error message. /// @@ -96,6 +113,25 @@ internal static MessageContainer CreateWarningMessage (LinkContext context, stri return CreateWarningMessageContainer (context, text, code, origin, version, subcategory); } + /// + /// Create a warning message. + /// + /// Context with the relevant warning suppression info. + /// Filename or member where the warning is coming from + /// Unique warning ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of warnings and possibly add a new one + /// Optional warning version number. Versioned warnings can be controlled with the + /// warning wave option --warn VERSION. Unversioned warnings are unaffected by this option. + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Warning' category + internal static MessageContainer CreateWarningMessage (LinkContext context, MessageOrigin origin, DiagnosticId id, WarnVersion version, params string[] args) + { + if (!((int) id > 2000 && (int) id <= 6000)) + throw new ArgumentOutOfRangeException (nameof (id), $"The provided code '{(int) id}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + + return CreateWarningMessageContainer (context, origin, id, version, id.GetDiagnosticSubcategory (), args); + } + /// /// Create a custom warning message. /// @@ -141,6 +177,26 @@ private static MessageContainer CreateWarningMessageContainer (LinkContext conte return new MessageContainer (MessageCategory.Warning, text, code, subcategory, origin); } + private static MessageContainer CreateWarningMessageContainer (LinkContext context, MessageOrigin origin, DiagnosticId id, WarnVersion version, string subcategory, params string[] args) + { + if (!(version >= WarnVersion.ILLink0 && version <= WarnVersion.Latest)) + throw new ArgumentException ($"The provided warning version '{version}' is invalid."); + + if (context.IsWarningSuppressed ((int) id, origin)) + return Empty; + + if (version > context.WarnVersion) + return Empty; + + if (TryLogSingleWarning (context, (int) id, origin, subcategory)) + return Empty; + + if (context.IsWarningAsError ((int) id)) + return new MessageContainer (MessageCategory.WarningAsError, id, subcategory, origin, args); + + return new MessageContainer (MessageCategory.Warning, id, subcategory, origin, args); + } + public bool IsWarningMessage ([NotNullWhen (true)] out int? code) { code = null; @@ -159,15 +215,16 @@ static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin or if (subcategory != MessageSubCategory.TrimAnalysis) return false; - Debug.Assert (origin.Provider != null); + // There are valid cases where we can't map the message to an assembly + // For example if it's caused by something in an xml file passed on the command line + // In that case, give up on single-warn collapse and just print out the warning on its own. var assembly = origin.Provider switch { AssemblyDefinition asm => asm, TypeDefinition type => type.Module.Assembly, IMemberDefinition member => member.DeclaringType.Module.Assembly, - _ => throw new NotSupportedException () + _ => null }; - Debug.Assert (assembly != null); if (assembly == null) return false; @@ -181,7 +238,7 @@ static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin or return false; if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName)) - context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly)); + context.LogWarning (context.GetAssemblyLocation (assembly), DiagnosticId.AssemblyProducedTrimWarnings, assemblyName); return true; } @@ -215,6 +272,15 @@ private MessageContainer (MessageCategory category, string text, int? code, stri Text = text; } + private MessageContainer (MessageCategory category, DiagnosticId id, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null, params string[] args) + { + Code = (int) id; + Category = category; + Origin = origin; + SubCategory = subcategory; + Text = new DiagnosticString (id).GetMessage (args); + } + public override string ToString () => ToMSBuildString (); public string ToMSBuildString () @@ -256,6 +322,8 @@ public string ToMSBuildString () if (Origin?.Provider != null) { if (Origin?.Provider is MethodDefinition method) sb.Append (method.GetDisplayName ()); + else if (Origin?.Provider is MemberReference memberRef) + sb.Append (memberRef.GetDisplayName ()); else if (Origin?.Provider is IMemberDefinition member) sb.Append (member.FullName); else if (Origin?.Provider is AssemblyDefinition assembly) @@ -274,7 +342,7 @@ public string ToMSBuildString () public bool Equals (MessageContainer other) => (Category, Text, Code, SubCategory, Origin) == (other.Category, other.Text, other.Code, other.SubCategory, other.Origin); - public override bool Equals (object obj) => obj is MessageContainer messageContainer && Equals (messageContainer); + public override bool Equals (object? obj) => obj is MessageContainer messageContainer && Equals (messageContainer); public override int GetHashCode () => (Category, Text, Code, SubCategory, Origin).GetHashCode (); public int CompareTo (MessageContainer other) diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs index 84357b26ae221..62de5fb3268fb 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs @@ -12,49 +12,55 @@ namespace Mono.Linker { public readonly struct MessageOrigin : IComparable, IEquatable { -#nullable enable public string? FileName { get; } public ICustomAttributeProvider? Provider { get; } - readonly ICustomAttributeProvider _suppressionContextMember; + readonly ICustomAttributeProvider? _suppressionContextMember; public ICustomAttributeProvider? SuppressionContextMember { get { Debug.Assert (_suppressionContextMember == null || _suppressionContextMember is IMemberDefinition || _suppressionContextMember is AssemblyDefinition); return _suppressionContextMember ?? Provider; } } -#nullable disable + public int SourceLine { get; } public int SourceColumn { get; } public int? ILOffset { get; } const int HiddenLineNumber = 0xfeefee; - public MessageOrigin (IMemberDefinition memberDefinition, int? ilOffset = null) + public MessageOrigin (IMemberDefinition? memberDefinition, int? ilOffset = null) : this (memberDefinition as ICustomAttributeProvider, ilOffset) { } - public MessageOrigin (ICustomAttributeProvider provider) + public MessageOrigin (ICustomAttributeProvider? provider) : this (provider, null) { } public MessageOrigin (string fileName, int sourceLine = 0, int sourceColumn = 0) + : this (fileName, sourceLine, sourceColumn, null) + { + } + + // The assembly attribute should be specified if available as it allows assigning the diagnostic + // to a an assembly (we group based on assembly). + public MessageOrigin (string fileName, int sourceLine, int sourceColumn, AssemblyDefinition? assembly) { FileName = fileName; SourceLine = sourceLine; SourceColumn = sourceColumn; - Provider = null; + Provider = assembly; _suppressionContextMember = null; ILOffset = null; } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset) : this (provider, ilOffset, null) { } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset, ICustomAttributeProvider suppressionContextMember) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset, ICustomAttributeProvider? suppressionContextMember) { Debug.Assert (provider == null || provider is IMemberDefinition || provider is AssemblyDefinition); Debug.Assert (suppressionContextMember == null || suppressionContextMember is IMemberDefinition || provider is AssemblyDefinition); @@ -66,7 +72,7 @@ public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset, ICustomA ILOffset = ilOffset; } - public MessageOrigin (MessageOrigin other, IMemberDefinition suppressionContextMember) + public MessageOrigin (MessageOrigin other, IMemberDefinition? suppressionContextMember) { FileName = other.FileName; Provider = other.Provider; @@ -76,21 +82,21 @@ public MessageOrigin (MessageOrigin other, IMemberDefinition suppressionContextM ILOffset = other.ILOffset; } - public override string ToString () + public override string? ToString () { int sourceLine = SourceLine, sourceColumn = SourceColumn; - string fileName = FileName; + string? fileName = FileName; if (Provider is MethodDefinition method && method.DebugInformation.HasSequencePoints) { var offset = ILOffset ?? 0; - SequencePoint correspondingSequencePoint = method.DebugInformation.SequencePoints + SequencePoint? correspondingSequencePoint = method.DebugInformation.SequencePoints .Where (s => s.Offset <= offset)?.Last (); // If the warning comes from hidden line (compiler generated code typically) // search for any sequence point with non-hidden line number and report that as a best effort. - if (correspondingSequencePoint.StartLine == HiddenLineNumber) { + if (correspondingSequencePoint?.StartLine == HiddenLineNumber) { correspondingSequencePoint = method.DebugInformation.SequencePoints - .Where (s => s.StartLine != HiddenLineNumber)?.FirstOrDefault (); + .Where (s => s.StartLine != HiddenLineNumber).FirstOrDefault (); } if (correspondingSequencePoint != null) { @@ -118,7 +124,7 @@ public override string ToString () public bool Equals (MessageOrigin other) => (FileName, Provider, SourceLine, SourceColumn, ILOffset) == (other.FileName, other.Provider, other.SourceLine, other.SourceColumn, other.ILOffset); - public override bool Equals (object obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); + public override bool Equals (object? obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); public override int GetHashCode () => (FileName, Provider, SourceLine, SourceColumn).GetHashCode (); public static bool operator == (MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals (rhs); public static bool operator != (MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals (rhs); @@ -128,12 +134,12 @@ public int CompareTo (MessageOrigin other) if (Provider != null && other.Provider != null) { var thisMember = Provider as IMemberDefinition; var otherMember = other.Provider as IMemberDefinition; - TypeDefinition thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; - TypeDefinition otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; var thisAssembly = thisTypeDef?.Module.Assembly ?? Provider as AssemblyDefinition; var otherAssembly = otherTypeDef?.Module.Assembly ?? other.Provider as AssemblyDefinition; - int result = (thisAssembly.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo - ((otherAssembly.Name.Name, otherTypeDef?.Name, otherMember?.Name)); + int result = (thisAssembly?.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo + ((otherAssembly?.Name.Name, otherTypeDef?.Name, otherMember?.Name)); if (result != 0) return result; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md index 883332600e88d..4fdfbf1c1fdac 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md @@ -1 +1 @@ -Sources from the dotnet/linker repo at commit c0567db0b9088e2ad4144cd0fe2a985611ec28f0. +Sources from the dotnet/linker repo at commit 2999a6a9dd884d554be18d3c86a4a9db4b61e156. diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs index 55b09b37b3431..aa1a796bfaa0f 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs @@ -20,6 +20,7 @@ public void EmitSource() WriteLine("#pragma warning disable 649"); WriteLine("#pragma warning disable 169"); WriteLine("#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct"); + WriteLine("#pragma warning disable CA1066 // IEquatable implementations aren't used"); WriteLine("#pragma warning disable IDE0059"); WriteLine(); diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs index 1d92be5677148..bbc23ec878484 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs @@ -6,6 +6,7 @@ #pragma warning disable 649 #pragma warning disable 169 #pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used #pragma warning disable IDE0059 using System; diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs index 8eba905400e42..5b7921f972f97 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - #pragma warning disable 169 - -// There is no defined ordering between fields in multiple declarations of partial class or struct -#pragma warning disable 282 - +#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used using System; using System.IO; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 30189ccc4cb52..cd464db795534 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -658,7 +658,7 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_METHODTABLE; } methodInfo->regionKind = CorInfoRegionKind.CORINFO_REGION_NONE; - Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args); + Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args, methodIL); Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals); return true; @@ -683,9 +683,9 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN return (CORINFO_CLASS_STRUCT_**)GetPin(jitVisibleInstantiation); } - private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, bool suppressHiddenArgument = false) + private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, MethodILScope scope, bool suppressHiddenArgument = false) { - Get_CORINFO_SIG_INFO(method.Signature, sig); + Get_CORINFO_SIG_INFO(method.Signature, sig, scope); // Does the method have a hidden parameter? bool hasHiddenParameter = !suppressHiddenArgument && method.RequiresInstArg(); @@ -845,7 +845,7 @@ private static CorInfoCallConvExtension GetMemberFunctionCallingConventionVarian var c => c }; - private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig) + private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig, MethodILScope scope) { sig->callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask); @@ -875,7 +875,7 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s sig->pSig = null; sig->cbSig = 0; // Not used by the JIT sig->methodSignature = ObjectToHandle(signature); - sig->scope = null; + sig->scope = scope is not null ? ObjectToHandle(scope) : null; // scope can be null for internal calls and COM methods. sig->token = 0; // Not used by the JIT } @@ -1149,7 +1149,7 @@ private void getMethodSig(CORINFO_METHOD_STRUCT_* ftn, CORINFO_SIG_INFO* sig, CO } } - Get_CORINFO_SIG_INFO(method, sig: sig); + Get_CORINFO_SIG_INFO(method, sig: sig, scope: null); } private bool getMethodInfo(CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_INFO* info) @@ -1795,7 +1795,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX var methodIL = HandleToObject(module); var methodSig = (MethodSignature)methodIL.GetObject((int)sigTOK); - Get_CORINFO_SIG_INFO(methodSig, sig); + Get_CORINFO_SIG_INFO(methodSig, sig, methodIL); #if !READYTORUN // Check whether we need to report this as a fat pointer call @@ -1811,7 +1811,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX private void findCallSiteSig(CORINFO_MODULE_STRUCT_* module, uint methTOK, CORINFO_CONTEXT_STRUCT* context, CORINFO_SIG_INFO* sig) { var methodIL = HandleToObject(module); - Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig); + Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig, methodIL); } private CORINFO_CLASS_STRUCT_* getTokenTypeAsHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken) @@ -3745,7 +3745,7 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes) #if READYTORUN // TODO: enable this check in full AOT - if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty())) // Only blittable arguments + if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty(), ((MetadataType)this.MethodBeingCompiled.OwningType).Module)) // Only blittable arguments { ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramNonBlittableTypes, this.MethodBeingCompiled); } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat index c775755558de9..69e3367c4e094 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat @@ -1,4 +1,4 @@ pushd %~dp0 -call ..\..\..\..\..\..\dotnet.cmd run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\aot\jitinterface\jitinterface.h ..\..\..\..\jit\ICorJitInfo_API_names.h ..\..\..\..\jit\ICorJitInfo_API_wrapper.hpp ..\..\..\..\inc\icorjitinfoimpl_generated.h ..\..\..\..\ToolBox\superpmi\superpmi-shim-counter\icorjitinfo.cpp ..\..\..\..\ToolBox\superpmi\superpmi-shim-simple\icorjitinfo.cpp +call ..\..\..\..\..\..\dotnet.cmd run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\aot\jitinterface\jitinterface.h ..\..\..\..\jit\ICorJitInfo_API_names.h ..\..\..\..\jit\ICorJitInfo_API_wrapper.hpp ..\..\..\..\inc\icorjitinfoimpl_generated.h ..\..\..\..\tools\superpmi\superpmi-shim-counter\icorjitinfo.cpp ..\..\..\..\tools\superpmi\superpmi-shim-simple\icorjitinfo.cpp call ..\..\..\..\..\..\dotnet.cmd run -- InstructionSetGenerator InstructionSetDesc.txt ..\..\Internal\Runtime\ReadyToRunInstructionSet.cs ..\..\Internal\Runtime\ReadyToRunInstructionSetHelper.cs ..\CorInfoInstructionSet.cs ..\..\..\..\inc\corinfoinstructionset.h ..\..\..\..\inc\readytoruninstructionset.h popd diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh index 7dc71bd378d85..ca9cdcb52ef11 100755 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash cd "$(dirname ${BASH_SOURCE[0]})" -../../../../../../dotnet.sh run -- ThunkInput.txt ../CorInfoBase.cs ../../../aot/jitinterface/jitinterface.h ../../../../jit/ICorJitInfo_API_names.h ../../../../jit/ICorJitInfo_API_wrapper.hpp ../../../../inc/icorjitinfoimpl_generated.h ../../../../ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp ../../../../ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +../../../../../../dotnet.sh run -- ThunkInput.txt ../CorInfoBase.cs ../../../aot/jitinterface/jitinterface.h ../../../../jit/ICorJitInfo_API_names.h ../../../../jit/ICorJitInfo_API_wrapper.hpp ../../../../inc/icorjitinfoimpl_generated.h ../../../../tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp ../../../../tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp ../../../../../../dotnet.sh run -- InstructionSetGenerator InstructionSetDesc.txt ../../Internal/Runtime/ReadyToRunInstructionSet.cs ../../Internal/Runtime/ReadyToRunInstructionSetHelper.cs ../CorInfoInstructionSet.cs ../../../../inc/corinfoinstructionset.h ../../../../inc/readytoruninstructionset.h diff --git a/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs b/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs index 1b067af21b476..03a59a840e1de 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs @@ -263,7 +263,7 @@ private static bool CanCastParamTo(this ParameterizedType thisType, TypeDesc par else if (curTypesParm.IsGenericParameter) { var genericVariableFromParam = (GenericParameterDesc)curTypesParm; - if (genericVariableFromParam.HasReferenceTypeConstraint) + if (genericVariableFromParam.HasReferenceTypeConstraint || IsConstrainedAsGCPointer(genericVariableFromParam)) { return genericVariableFromParam.CanCastToInternal(paramType, protect); } @@ -281,6 +281,30 @@ private static bool CanCastParamTo(this ParameterizedType thisType, TypeDesc par return false; } + private static bool IsConstrainedAsGCPointer(GenericParameterDesc type) + { + foreach (var typeConstraint in type.TypeConstraints) + { + if (typeConstraint.IsGenericParameter) + { + if (IsConstrainedAsGCPointer((GenericParameterDesc)typeConstraint)) + return true; + } + + if (!typeConstraint.IsInterface && typeConstraint.IsGCPointer) + { + // Object, ValueType, and Enum are GCPointers but they do not constrain the type to GCPointer! + if (!typeConstraint.IsWellKnownType(WellKnownType.Object) && + !typeConstraint.IsWellKnownType(WellKnownType.ValueType) && + !typeConstraint.IsWellKnownType(WellKnownType.Enum)) + { + return true; + } + } + } + return false; + } + private static TypeFlags GetNormalizedIntegralArrayElementType(TypeDesc type) { Debug.Assert(!type.IsEnum); @@ -502,7 +526,7 @@ private static bool IsBoxedAndCanCastTo(this TypeDesc thisType, TypeDesc otherTy else if (thisType.IsGenericParameter) { var genericVariableFromParam = (GenericParameterDesc)thisType; - if (genericVariableFromParam.HasReferenceTypeConstraint) + if (genericVariableFromParam.HasReferenceTypeConstraint || IsConstrainedAsGCPointer(genericVariableFromParam)) { return genericVariableFromParam.CanCastToInternal(otherType, protect); } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 71c7423b8fbb0..2190f9ac1a278 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -63,6 +63,11 @@ private static class FieldLayoutFlags /// True if type transitively has UnsafeValueTypeAttribute /// public const int IsUnsafeValueType = 0x200; + + /// + /// True if the type transitively has any types with LayoutKind.Auto in its layout. + /// + public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400; } private class StaticBlockInfo @@ -115,6 +120,21 @@ public bool IsUnsafeValueType } } + /// + /// Does a type have auto-layout or transitively have any fields of a type with auto-layout. + /// + public virtual bool IsAutoLayoutOrHasAutoLayoutFields + { + get + { + if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout)) + { + ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); + } + return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields); + } + } + /// /// The number of bytes required to hold a field of this type @@ -406,6 +426,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind) { _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceLayoutAbiUnstable); } + if (computedLayout.IsAutoLayoutOrHasAutoLayoutFields) + { + _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields); + } if (computedLayout.Offsets != null) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index 863e857a21def..a19ec4b3603bf 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -82,6 +82,7 @@ public struct ComputedInstanceFieldLayout public LayoutInt ByteCountUnaligned; public LayoutInt ByteCountAlignment; public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions + public bool IsAutoLayoutOrHasAutoLayoutFields; /// /// If Offsets is non-null, then all field based layout is complete. diff --git a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs index 2ec3883af9f08..c794377bf1971 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs @@ -12,7 +12,9 @@ namespace Internal.TypeSystem /// type system do not have a known size. This type is used to make such sizes viral through the type layout /// computations) /// +#pragma warning disable CA1066 // IEquatable implementation wouldn't be used public struct LayoutInt +#pragma warning restore CA1066 { private int _value; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 249faef7cd040..637f1f7538ff8 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -37,12 +37,8 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp TypeDesc fieldType = field.FieldType; - // ByRef instance fields are not allowed. - if (fieldType.IsByRef) - ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); - - // ByRef-like instance fields on non-byref-like types are not allowed. - if (fieldType.IsByRefLike && !type.IsByRefLike) + // ByRef and byref-like instance fields on non-byref-like types are not allowed. + if ((fieldType.IsByRef || fieldType.IsByRefLike) && !type.IsByRefLike) ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); numInstanceFields++; @@ -112,7 +108,8 @@ out instanceByteSizeAndAlignment ByteCountAlignment = instanceByteSizeAndAlignment.Alignment, FieldAlignment = sizeAndAlignment.Alignment, FieldSize = sizeAndAlignment.Size, - LayoutAbiStable = true + LayoutAbiStable = true, + IsAutoLayoutOrHasAutoLayoutFields = false, }; if (numInstanceFields > 0) @@ -214,7 +211,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy } ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field); - SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _); + SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _); block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target); result.Offsets[index] = new FieldAndOffset(field, block.Size); @@ -305,13 +302,16 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty var offsets = new FieldAndOffset[numInstanceFields]; int fieldOrdinal = 0; bool layoutAbiStable = true; + bool hasAutoLayoutField = false; foreach (var fieldAndOffset in layoutMetadata.Offsets) { TypeDesc fieldType = fieldAndOffset.Field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); if (!fieldLayoutAbiStable) layoutAbiStable = false; + if (fieldHasAutoLayout) + hasAutoLayoutField = true; largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); @@ -354,7 +354,10 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty layoutMetadata.Size, out instanceByteSizeAndAlignment); - ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); + ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout + { + IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; @@ -388,15 +391,18 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType int fieldOrdinal = 0; int packingSize = ComputePackingSize(type, layoutMetadata); bool layoutAbiStable = true; + bool hasAutoLayoutField = false; foreach (var field in type.GetFields()) { if (field.IsStatic) continue; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); if (!fieldLayoutAbiStable) layoutAbiStable = false; + if (fieldHasAutoLayout) + hasAutoLayoutField = true; largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement); @@ -415,7 +421,10 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType layoutMetadata.Size, out instanceByteSizeAndAlignment); - ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); + ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout + { + IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; @@ -468,9 +477,9 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, } else { - Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum); + Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _); instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++; } } @@ -507,7 +516,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, TypeDesc fieldType = field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -646,7 +655,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, for (int i = 0; i < instanceValueClassFieldsArr.Length; i++) { // Align the cumulative field offset to the indeterminate value - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -694,7 +703,10 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, classLayoutSize: 0, byteCount: out instanceByteSizeAndAlignment); - ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); + ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout + { + IsAutoLayoutOrHasAutoLayoutFields = true, + }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; @@ -707,7 +719,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias) { - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _); instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target); offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias); @@ -767,10 +779,11 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8 return cumulativeInstanceFieldPos; } - private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable) + private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout) { SizeAndAlignment result; layoutAbiStable = true; + fieldTypeHasAutoLayout = true; if (fieldType.IsDefType) { @@ -780,6 +793,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, result.Size = defType.InstanceFieldSize; result.Alignment = defType.InstanceFieldAlignment; layoutAbiStable = defType.LayoutAbiStable; + fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields; } else { @@ -797,7 +811,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, } else { - Debug.Assert(fieldType.IsPointer || fieldType.IsFunctionPointer); + Debug.Assert(fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsByRef); result.Size = fieldType.Context.Target.LayoutPointerSize; result.Alignment = fieldType.Context.Target.LayoutPointerSize; } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs index 0e155fda998f3..5a281d21ba11a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs @@ -67,7 +67,7 @@ public override string ToString() public bool HasAssemblyCustomAttribute(string attributeNamespace, string attributeName) { - return _metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(), + return !_metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(), attributeNamespace, attributeName).IsNil; } } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs index 48ca23cf1ea26..537b494b0d6f9 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs @@ -256,7 +256,8 @@ private TypeDesc ParseTypeImpl(SignatureTypeCode typeCode) else return null; default: - throw new BadImageFormatException(); + ThrowHelper.ThrowBadImageFormatException(); + return null; } } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs index 5d8d4fd0f4c2b..b270b73ab8d90 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs @@ -26,7 +26,7 @@ private static unsafe MetadataReader TryOpenMetadataFile(string filePath, Metada try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); @@ -56,12 +56,9 @@ private static unsafe MetadataReader TryOpenMetadataFile(string filePath, Metada } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs index c68f9a10fe2fa..dd91b65fa9079 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs @@ -20,7 +20,7 @@ string IPrefixMangledSignature.Prefix { get { - return "Calli"; + return RuntimeMarshallingEnabled ? "CalliWithRuntimeMarshalling" : "Calli"; } } } diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs index 89be9fa3a7d88..cd6e620aa8607 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs @@ -13,6 +13,11 @@ partial class CalliMarshallingMethodThunk protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) { var otherMethod = (CalliMarshallingMethodThunk)other; + int result = RuntimeMarshallingEnabled.CompareTo(otherMethod.RuntimeMarshallingEnabled); + if (result != 0) + { + return result; + } return comparer.Compare(_targetSignature, otherMethod._targetSignature); } } diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs index bdbd7b67998f4..d0d397bafdf38 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs @@ -21,11 +21,13 @@ public partial class CalliMarshallingMethodThunk : ILStubMethod private MethodSignature _signature; public CalliMarshallingMethodThunk(MethodSignature targetSignature, TypeDesc owningType, - InteropStateManager interopStateManager) + InteropStateManager interopStateManager, + bool runtimeMarshallingEnabled) { _targetSignature = targetSignature; _owningType = owningType; _interopStateManager = interopStateManager; + RuntimeMarshallingEnabled = runtimeMarshallingEnabled; } public MethodSignature TargetSignature @@ -87,6 +89,8 @@ public override string DiagnosticName } } + public bool RuntimeMarshallingEnabled { get; } + public override PInvokeMetadata GetPInvokeMethodMetadata() { // Return PInvokeAttributes.PreserveSig to circumvent marshalling required checks diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs index 276f7dc4a42fc..5b09863069020 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs @@ -27,6 +27,14 @@ public partial class DelegateMarshallingMethodThunk : ILStubMethod private readonly MethodDesc _invokeMethod; private MethodSignature _signature; // signature of the native callable marshalling stub + public MethodDesc InvokeMethod + { + get + { + return _invokeMethod; + } + } + public DelegateMarshallingMethodThunkKind Kind { get; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs index d77bb5994ec0e..81245ffe82515 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs @@ -12,11 +12,6 @@ namespace Internal.IL.Stubs { /// /// Provides method bodies for PInvoke methods - /// - /// This by no means intends to provide full PInvoke support. The intended use of this is to - /// a) prevent calls getting generated to targets that require a full marshaller - /// (this compiler doesn't provide that), and b) offer a hand in some very simple marshalling - /// situations (but support for this part might go away as the product matures). /// public struct PInvokeILEmitter { @@ -55,23 +50,27 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter { MarshalDirection direction = MarshalDirection.Forward; MethodSignature methodSig; + bool runtimeMarshallingEnabled; switch (targetMethod) { case DelegateMarshallingMethodThunk delegateMethod: methodSig = delegateMethod.DelegateSignature; direction = delegateMethod.Direction; + runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(delegateMethod.DelegateType.Module); break; case CalliMarshallingMethodThunk calliMethod: methodSig = calliMethod.TargetSignature; + runtimeMarshallingEnabled = calliMethod.RuntimeMarshallingEnabled; break; default: methodSig = targetMethod.Signature; + runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)targetMethod.OwningType).Module); break; } int indexOffset = 0; if (!methodSig.IsStatic && direction == MarshalDirection.Forward) { - // For instance methods(eg. Forward delegate marshalling thunk), first argument is + // For instance methods(eg. Forward delegate marshalling thunk), first argument is // the instance indexOffset = 1; } @@ -88,7 +87,7 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter // if we don't have metadata for the parameter, create a dummy one parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null); } - else + else { Debug.Assert(i == parameterMetadataArray[parameterIndex].Index); parameterMetadata = parameterMetadataArray[parameterIndex++]; @@ -104,7 +103,7 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter { // PreserveSig = false can only show up an regular forward PInvokes Debug.Assert(direction == MarshalDirection.Forward); - + parameterType = methodSig.Context.GetByRefType(parameterType); isHRSwappedRetVal = true; } @@ -114,20 +113,35 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter parameterType = methodSig[i - 1]; } - marshallers[i] = Marshaller.CreateMarshaller(parameterType, - parameterIndex, - methodSig.GetEmbeddedSignatureData(), - MarshallerType.Argument, - parameterMetadata.MarshalAsDescriptor, - direction, - marshallers, - interopStateManager, - indexOffset + parameterMetadata.Index, - flags, - parameterMetadata.In, - isHRSwappedRetVal ? true : parameterMetadata.Out, - isHRSwappedRetVal ? false : parameterMetadata.Return - ); + if (runtimeMarshallingEnabled) + { + marshallers[i] = Marshaller.CreateMarshaller(parameterType, + parameterIndex, + methodSig.GetEmbeddedSignatureData(), + MarshallerType.Argument, + parameterMetadata.MarshalAsDescriptor, + direction, + marshallers, + interopStateManager, + indexOffset + parameterMetadata.Index, + flags, + parameterMetadata.In, + isHRSwappedRetVal ? true : parameterMetadata.Out, + isHRSwappedRetVal ? false : parameterMetadata.Return + ); + } + else + { + marshallers[i] = Marshaller.CreateDisabledMarshaller( + parameterType, + parameterIndex, + MarshallerType.Argument, + direction, + marshallers, + indexOffset + parameterMetadata.Index, + flags, + parameterMetadata.Return); + } } return marshallers; @@ -146,10 +160,10 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind.ReverseOpenStatic) { // - // For Open static delegates call + // For Open static delegates call // InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer() // which returns a function pointer. Just call the function pointer and we are done. - // + // TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { @@ -193,7 +207,7 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn else if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind .ForwardNativeFunctionWrapper) { - // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, clear the error code before doing P/Invoke + // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, clear the error code before doing P/Invoke if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( @@ -225,7 +239,7 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn MethodSignatureFlags unmanagedCallingConvention = _flags.UnmanagedCallingConvention; if (unmanagedCallingConvention == MethodSignatureFlags.None) unmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConvention; - + MethodSignature nativeSig = new MethodSignature( MethodSignatureFlags.Static | unmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes); @@ -257,9 +271,16 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) TypeDesc nativeReturnType = _flags.PreserveSig ? _marshallers[0].NativeParameterType : context.GetWellKnownType(WellKnownType.Int32); TypeDesc[] nativeParameterTypes = new TypeDesc[isHRSwappedRetVal ? _marshallers.Length : _marshallers.Length - 1]; - // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke + bool runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module); + + // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_flags.SetLastError) { + if (!runtimeMarshallingEnabled) + { + // When runtime marshalling is disabled, we don't support SetLastError + throw new NotSupportedException(); + } callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastError", null))); } @@ -271,6 +292,11 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) if (isHRSwappedRetVal) { + if (!runtimeMarshallingEnabled) + { + // When runtime marshalling is disabled, we don't support HResult-return-swapping + throw new NotSupportedException(); + } nativeParameterTypes[_marshallers.Length - 1] = _marshallers[0].NativeParameterType; } @@ -364,6 +390,9 @@ private void EmitCalli(PInvokeILCodeStreams ilCodeStreams, CalliMarshallingMetho private MethodIL EmitIL() { + if (_targetMethod.HasCustomAttribute("System.Runtime.InteropServices", "LCIDConversionAttribute")) + throw new NotSupportedException(); + PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream marshallingCodestream = pInvokeILCodeStreams.MarshallingCodeStream; @@ -417,8 +446,8 @@ private MethodIL EmitIL() return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired()); } - public static MethodIL EmitIL(MethodDesc method, - PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, + public static MethodIL EmitIL(MethodDesc method, + PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager) { try diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs index 8925f9964b093..b047f29e9ec64 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs @@ -126,7 +126,7 @@ public static MethodIL EmitExceptionBody(string message, MethodDesc method) TypeSystemContext context = method.Context; MethodSignature ctorSignature = new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void), new TypeDesc[] { context.GetWellKnownType(WellKnownType.String) }); - MethodDesc exceptionCtor = method.Context.GetWellKnownType(WellKnownType.Exception).GetKnownMethod(".ctor", ctorSignature); + MethodDesc exceptionCtor = InteropTypes.GetMarshalDirectiveException(context).GetKnownMethod(".ctor", ctorSignature); ILCodeStream codeStream = emitter.NewCodeStream(); codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(message)); diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index f23a4479634a9..d37f44971968b 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -5,6 +5,7 @@ using Internal.IL; using Debug = System.Diagnostics.Debug; using Internal.IL.Stubs; +using Internal.TypeSystem.Ecma; namespace Internal.TypeSystem.Interop { @@ -75,6 +76,7 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type, #if !READYTORUN case MarshallerKind.Struct: case MarshallerKind.LayoutClass: + Debug.Assert(interopStateManager is not null, "An InteropStateManager is required to look up the native representation of a non-blittable struct or class with layout."); return interopStateManager.GetStructMarshallingNativeType((MetadataType)type); #endif @@ -93,6 +95,9 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type, case MarshallerKind.OleDateTime: return context.GetWellKnownType(WellKnownType.Double); + case MarshallerKind.FailedTypeLoad: + return context.GetWellKnownType(WellKnownType.IntPtr); + case MarshallerKind.SafeHandle: case MarshallerKind.CriticalHandle: return context.GetWellKnownType(WellKnownType.IntPtr); @@ -454,7 +459,7 @@ internal static MarshallerKind GetMarshallerKind( case NativeTypeKind.Array: { if (isField) - return MarshallerKind.Invalid; + return MarshallerKind.FailedTypeLoad; var arrayType = (ArrayType)type; @@ -581,6 +586,8 @@ internal static MarshallerKind GetMarshallerKind( } else if (type.IsObject) { + if (nativeType == NativeTypeKind.AsAny && isField) + return MarshallerKind.FailedTypeLoad; if (nativeType == NativeTypeKind.AsAny) return isAnsi ? MarshallerKind.AsAnyA : MarshallerKind.AsAnyW; else @@ -844,6 +851,37 @@ private static MarshallerKind GetArrayElementMarshallerKind( } } + internal static MarshallerKind GetDisabledMarshallerKind( + TypeDesc type) + { + if (type.Category == TypeFlags.Void) + { + return MarshallerKind.VoidReturn; + } + else if (type.IsByRef) + { + // Managed refs are not supported when runtime marshalling is disabled. + return MarshallerKind.Invalid; + } + else if (type.IsPrimitive) + { + return MarshallerKind.BlittableValue; + } + else if (type.IsPointer || type.IsFunctionPointer) + { + return MarshallerKind.BlittableValue; + } + else if (type.IsValueType) + { + var defType = (DefType)type; + if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields) + { + return MarshallerKind.BlittableValue; + } + } + return MarshallerKind.Invalid; + } + internal static bool ShouldCheckForPendingException(TargetDetails target, PInvokeMetadata metadata) { if (!target.IsOSX) @@ -861,5 +899,10 @@ internal static bool ShouldCheckForPendingException(TargetDetails target, PInvok return metadata.Module.Equals(ObjectiveCLibrary) && metadata.Name.StartsWith(ObjectiveCMsgSend); } + + public static bool IsRuntimeMarshallingEnabled(ModuleDesc module) + { + return module.Assembly is not EcmaAssembly assembly || !assembly.HasAssemblyCustomAttribute("System.Runtime.CompilerServices", "DisableRuntimeMarshallingAttribute"); + } } } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs index 4244a04ab1810..01b2702615238 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs @@ -86,6 +86,8 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind) return new OleDateTimeMarshaller(); case MarshallerKind.OleCurrency: return new OleCurrencyMarshaller(); + case MarshallerKind.FailedTypeLoad: + return new FailedTypeLoadMarshaller(); case MarshallerKind.Variant: return new VariantMarshaller(); default: @@ -1073,6 +1075,19 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream) } } + class FailedTypeLoadMarshaller : Marshaller + { + protected override void TransformManagedToNative(ILCodeStream codeStream) + { + ThrowHelper.ThrowTypeLoadException(ManagedType); + } + + protected override void TransformNativeToManaged(ILCodeStream codeStream) + { + ThrowHelper.ThrowTypeLoadException(ManagedType); + } + } + class VariantMarshaller : Marshaller { protected override void AllocManagedToNative(ILCodeStream codeStream) diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs index ea0494643a14a..7b7e3a24d9813 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs @@ -329,6 +329,44 @@ public static Marshaller CreateMarshaller(TypeDesc parameterType, return marshaller; } + + /// + /// Create a marshaller + /// + /// type of the parameter to marshal + /// The created Marshaller + public static Marshaller CreateDisabledMarshaller(TypeDesc parameterType, + int? parameterIndex, + MarshallerType marshallerType, + MarshalDirection direction, + Marshaller[] marshallers, + int index, + PInvokeFlags flags, + bool isReturn) + { + MarshallerKind marshallerKind = MarshalHelpers.GetDisabledMarshallerKind(parameterType); + + TypeSystemContext context = parameterType.Context; + // Create the marshaller based on MarshallerKind + Marshaller marshaller = CreateMarshaller(marshallerKind); + marshaller.Context = context; + marshaller.MarshallerKind = marshallerKind; + marshaller.MarshallerType = marshallerType; + marshaller.ElementMarshallerKind = MarshallerKind.Unknown; + marshaller.ManagedParameterType = parameterType; + marshaller.ManagedType = parameterType; + marshaller.Return = isReturn; + marshaller.IsManagedByRef = false; + marshaller.IsNativeByRef = false; + marshaller.MarshalDirection = direction; + marshaller.MarshalAsDescriptor = null; + marshaller.Marshallers = marshallers; + marshaller.Index = index; + marshaller.PInvokeFlags = flags; + marshaller.In = true; + marshaller.Out = false; + return marshaller; + } #endregion @@ -1560,7 +1598,7 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream) class AnsiStringMarshaller : Marshaller { #if READYTORUN - const int MAX_LOCAL_BUFFER_LENGTH = 260 + 1; // MAX_PATH + 1 + const int MAX_LOCAL_BUFFER_LENGTH = 260 + 1; // MAX_PATH + 1 private ILLocalVariable? _localBuffer = null; #endif @@ -1597,7 +1635,7 @@ protected override void TransformManagedToNative(ILCodeStream codeStream) .GetKnownMethod("ConvertToNative", null); bool bPassByValueInOnly = In && !Out && !IsManagedByRef; - + if (bPassByValueInOnly) { var bufSize = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); @@ -1632,7 +1670,7 @@ protected override void TransformManagedToNative(ILCodeStream codeStream) codeStream.EmitStLoc(bufSize); // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize - codeStream.EmitLdc(MAX_LOCAL_BUFFER_LENGTH + 1); + codeStream.EmitLdc(MAX_LOCAL_BUFFER_LENGTH + 1); codeStream.EmitLdLoc(bufSize); codeStream.Emit(ILOpcode.clt); codeStream.Emit(ILOpcode.brtrue, noOptimize); diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs index 37d09857b694a..888a174ff38fc 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs @@ -45,6 +45,7 @@ enum MarshallerKind LayoutClassPtr, AsAnyA, AsAnyW, + FailedTypeLoad, ComInterface, BlittableValueClassWithCopyCtor, Invalid diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs index 202fcce90bece..0d594010328e6 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs @@ -38,7 +38,7 @@ public InteropStateManager(ModuleDesc generatedAssembly) // // Delegate Marshalling Stubs // - + /// /// Generates marshalling stubs for open static delegates /// @@ -105,9 +105,9 @@ public PInvokeDelegateWrapper GetPInvokeDelegateWrapper(TypeDesc delegateType) } // - // Struct Marshalling + // Struct Marshalling // To support struct marshalling compiler needs to generate a native type which - // imitates the original struct being passed to managed side with corresponding + // imitates the original struct being passed to managed side with corresponding // fields of marshalled types. Additionally it needs to generate three thunks // 1. Managed to Native Thunk: For forward marshalling // 2. Native to Managed Thunk: For reverse marshalling @@ -186,9 +186,9 @@ public FieldDesc GetPInvokeLazyFixupField(MethodDesc method) return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); } - public MethodDesc GetPInvokeCalliStub(MethodSignature signature) + public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext) { - return _pInvokeCalliHashtable.GetOrCreateValue(signature); + return _pInvokeCalliHashtable.GetOrCreateValue(new CalliMarshallingMethodThunkKey(signature, MarshalHelpers.IsRuntimeMarshallingEnabled(moduleContext))); } private class NativeStructTypeHashtable : LockFreeReaderHashtable @@ -355,7 +355,7 @@ protected override bool CompareValueToValue(DelegateMarshallingMethodThunk value protected override DelegateMarshallingMethodThunk CreateValueFromKey(DelegateMarshallingStubHashtableKey key) { - return new DelegateMarshallingMethodThunk(key.DelegateType, _owningType, + return new DelegateMarshallingMethodThunk(key.DelegateType, _owningType, _interopStateManager, key.Kind); } @@ -478,34 +478,36 @@ public PInvokeLazyFixupFieldHashtable(DefType owningType) } } - private class PInvokeCalliHashtable : LockFreeReaderHashtable + private readonly record struct CalliMarshallingMethodThunkKey(MethodSignature Signature, bool RuntimeMarshallingEnabled); + + private class PInvokeCalliHashtable : LockFreeReaderHashtable { private readonly InteropStateManager _interopStateManager; private readonly TypeDesc _owningType; - protected override int GetKeyHashCode(MethodSignature key) + protected override int GetKeyHashCode(CalliMarshallingMethodThunkKey key) { return key.GetHashCode(); } protected override int GetValueHashCode(CalliMarshallingMethodThunk value) { - return value.TargetSignature.GetHashCode(); + return new CalliMarshallingMethodThunkKey(value.TargetSignature, value.RuntimeMarshallingEnabled).GetHashCode(); } - protected override bool CompareKeyToValue(MethodSignature key, CalliMarshallingMethodThunk value) + protected override bool CompareKeyToValue(CalliMarshallingMethodThunkKey key, CalliMarshallingMethodThunk value) { - return key.Equals(value.TargetSignature); + return key.Signature.Equals(value.TargetSignature) && key.RuntimeMarshallingEnabled == value.RuntimeMarshallingEnabled; } protected override bool CompareValueToValue(CalliMarshallingMethodThunk value1, CalliMarshallingMethodThunk value2) { - return value1.TargetSignature.Equals(value2.TargetSignature); + return value1.TargetSignature.Equals(value2.TargetSignature) && value1.RuntimeMarshallingEnabled == value2.RuntimeMarshallingEnabled; } - protected override CalliMarshallingMethodThunk CreateValueFromKey(MethodSignature key) + protected override CalliMarshallingMethodThunk CreateValueFromKey(CalliMarshallingMethodThunkKey key) { - return new CalliMarshallingMethodThunk(key, _owningType, _interopStateManager); + return new CalliMarshallingMethodThunk(key.Signature, _owningType, _interopStateManager, key.RuntimeMarshallingEnabled); } public PInvokeCalliHashtable(InteropStateManager interopStateManager, TypeDesc owningType) diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs index 96ffe8868422d..ac32fbbe54647 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs @@ -54,6 +54,11 @@ public static MetadataType GetNativeFunctionPointerWrapper(TypeSystemContext con return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "NativeFunctionPointerWrapper"); } + public static MetadataType GetMarshalDirectiveException(TypeSystemContext context) + { + return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "MarshalDirectiveException"); + } + public static MetadataType GetVariant(TypeSystemContext context) { return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "Variant"); diff --git a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs index d1b3d10ed5a3f..258a005ffdd09 100644 --- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs +++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs @@ -2060,7 +2060,7 @@ void ImportLoadField(int token, bool isStatic) actualThis = StackValue.CreateByRef(actualThis.Type); var declaredThis = owningType.IsValueType ? - StackValue.CreateByRef(owningType) : StackValue.CreateObjRef(owningType); + StackValue.CreateByRef(owningType, readOnly : true) : StackValue.CreateObjRef(owningType); CheckIsAssignable(actualThis, declaredThis); diff --git a/src/coreclr/ToolBox/SOS/CMakeLists.txt b/src/coreclr/tools/SOS/CMakeLists.txt similarity index 100% rename from src/coreclr/ToolBox/SOS/CMakeLists.txt rename to src/coreclr/tools/SOS/CMakeLists.txt diff --git a/src/coreclr/ToolBox/SOS/DIALib/DIALib.il b/src/coreclr/tools/SOS/DIALib/DIALib.il similarity index 100% rename from src/coreclr/ToolBox/SOS/DIALib/DIALib.il rename to src/coreclr/tools/SOS/DIALib/DIALib.il diff --git a/src/coreclr/ToolBox/SOS/DIALib/DIALib.ilproj b/src/coreclr/tools/SOS/DIALib/DIALib.ilproj similarity index 100% rename from src/coreclr/ToolBox/SOS/DIALib/DIALib.ilproj rename to src/coreclr/tools/SOS/DIALib/DIALib.ilproj diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/DacTableGen.csproj b/src/coreclr/tools/SOS/DacTableGen/DacTableGen.csproj similarity index 100% rename from src/coreclr/ToolBox/SOS/DacTableGen/DacTableGen.csproj rename to src/coreclr/tools/SOS/DacTableGen/DacTableGen.csproj diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/MapSymbolProvider.cs b/src/coreclr/tools/SOS/DacTableGen/MapSymbolProvider.cs similarity index 100% rename from src/coreclr/ToolBox/SOS/DacTableGen/MapSymbolProvider.cs rename to src/coreclr/tools/SOS/DacTableGen/MapSymbolProvider.cs diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/cvconst.cs b/src/coreclr/tools/SOS/DacTableGen/cvconst.cs similarity index 100% rename from src/coreclr/ToolBox/SOS/DacTableGen/cvconst.cs rename to src/coreclr/tools/SOS/DacTableGen/cvconst.cs diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/diautil.cs b/src/coreclr/tools/SOS/DacTableGen/diautil.cs similarity index 100% rename from src/coreclr/ToolBox/SOS/DacTableGen/diautil.cs rename to src/coreclr/tools/SOS/DacTableGen/diautil.cs diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/main.cs b/src/coreclr/tools/SOS/DacTableGen/main.cs similarity index 100% rename from src/coreclr/ToolBox/SOS/DacTableGen/main.cs rename to src/coreclr/tools/SOS/DacTableGen/main.cs diff --git a/src/coreclr/ToolBox/SOS/Directory.Build.props b/src/coreclr/tools/SOS/Directory.Build.props similarity index 100% rename from src/coreclr/ToolBox/SOS/Directory.Build.props rename to src/coreclr/tools/SOS/Directory.Build.props diff --git a/src/coreclr/ToolBox/SOS/SOS_README.md b/src/coreclr/tools/SOS/SOS_README.md similarity index 100% rename from src/coreclr/ToolBox/SOS/SOS_README.md rename to src/coreclr/tools/SOS/SOS_README.md diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index f3f780e87e060..d19b60b104c24 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -143,8 +143,9 @@ public virtual ISymbolNode GetFieldRvaData(FieldDesc field) { // Use the typical field definition in case this is an instantiated generic type field = field.GetTypicalFieldDefinition(); + int fieldTypePack = (field.FieldType as MetadataType)?.GetClassLayout().PackingSize ?? 1; return NodeFactory.ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), - ((EcmaField)field).GetFieldRvaData(), NodeFactory.Target.PointerSize); + ((EcmaField)field).GetFieldRvaData(), Math.Max(NodeFactory.Target.PointerSize, fieldTypePack)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs index fb4ad5ce51b7f..232df5cd22d4e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs @@ -24,6 +24,7 @@ partial class CompilationBuilder protected bool _methodBodyFolding; protected InstructionSetSupport _instructionSetSupport; protected SecurityMitigationOptions _mitigationOptions; + protected bool _useDwarf5; partial void InitializePartial() { @@ -103,6 +104,12 @@ public CompilationBuilder UseMethodImportationErrorProvider(MethodImportationErr return this; } + public CompilationBuilder UseDwarf5(bool value) + { + _useDwarf5 = value; + return this; + } + protected PreinitializationManager GetPreinitializationManager() { if (_preinitializationManager == null) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs index f3585e0e098f0..6e659a95eb7e7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs @@ -10,6 +10,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler.Dataflow @@ -287,9 +289,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(field.FieldType)) { // Already know that there's a non-empty annotation on a field which is not System.Type/String and we're about to ignore it - _logger.LogWarning( - $"Field '{field.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'.", - 2097, field, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(field, DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings, field.GetDisplayName()); continue; } @@ -341,9 +341,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) } else { - _logger.LogWarning( - $"The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters though.", - 2041, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods); } } @@ -362,9 +360,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) returnAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes()); if (returnAnnotation != DynamicallyAccessedMemberTypes.None && !IsTypeInterestingForDataflow(signature.ReturnType)) { - _logger.LogWarning( - $"Return type of method '{method.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'.", - 2106, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings, method.GetDisplayName()); } } else @@ -375,9 +371,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(signature[parameter.SequenceNumber - 1])) { - _logger.LogWarning( - $"Parameter #{parameter.SequenceNumber} of method '{method.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'.", - 2098, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings, $"#{parameter.SequenceNumber}", method.GetDisplayName()); continue; } @@ -433,9 +427,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(property.Signature.ReturnType)) { - _logger.LogWarning( - $"Property '{property.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'.", - 2099, property, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings, property.GetDisplayName()); continue; } @@ -460,9 +452,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (annotatedMethods.Any(a => a.Method == setMethod)) { - _logger.LogWarning( - $"'DynamicallyAccessedMembersAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its accessor '{setMethod.GetDisplayName()}'.", - 2043, setMethod, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(setMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), setMethod.GetDisplayName()); } else { @@ -496,9 +486,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (annotatedMethods.Any(a => a.Method == getMethod)) { - _logger.LogWarning( - $"'DynamicallyAccessedMembersAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its accessor '{getMethod.GetDisplayName()}'.", - 2043, getMethod, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(getMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), getMethod.GetDisplayName()); } else { @@ -510,9 +498,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (backingFieldFromGetter != null && backingFieldFromSetter != null && backingFieldFromGetter != backingFieldFromSetter) { - _logger.LogWarning( - $"Could not find a unique backing field for property '{property.GetDisplayName()}' to propagate 'DynamicallyAccessedMembersAttribute'.", - 2042, property, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName()); backingField = null; } else @@ -524,9 +510,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) { if (annotatedFields.Any(a => a.Field == backingField)) { - _logger.LogWarning( - $"'DynamicallyAccessedMemberAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its backing field '{backingField.GetDisplayName()}'.", - 2056, backingField, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName()); } else { @@ -729,33 +713,23 @@ void LogValidationWarning(object provider, object baseProvider, MethodDesc origi switch (provider) { case int parameterNumber: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter #{parameterNumber} of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(origin)}' " + - $"don't match overridden parameter #{parameterNumber} of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2092, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides, + $"#{parameterNumber}", DiagnosticUtilities.GetMethodSignatureDisplayName(origin), + $"#{parameterNumber}", DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; case GenericParameterDesc genericParameterOverride: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the generic parameter '{genericParameterOverride.Name}' of '{DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin(genericParameterOverride))}' " + - $"don't match overridden generic parameter '{((GenericParameterDesc)baseProvider).Name}' of '{DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin((GenericParameterDesc)baseProvider))}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2095, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides, + genericParameterOverride.Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin(genericParameterOverride)), + ((GenericParameterDesc)baseProvider).Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin((GenericParameterDesc)baseProvider))); break; case TypeDesc methodReturnType: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(origin)}' " + - $"don't match overridden return value of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2093, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides, + DiagnosticUtilities.GetMethodSignatureDisplayName(origin), DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; // No fields - it's not possible to have a virtual field and override it case MethodDesc methodDefinition: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the implicit 'this' parameter of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(methodDefinition)}' " + - $"don't match overridden implicit 'this' parameter of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2094, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnImplicitThisBetweenOverrides, + DiagnosticUtilities.GetMethodSignatureDisplayName(methodDefinition), DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; default: throw new NotImplementedException($"Unsupported provider type {provider.GetType()}"); 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 06d371cd17aea..420dc07dcfa75 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -1029,8 +1029,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } RequireDynamicallyAccessedMembers( @@ -1048,8 +1048,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } RequireDynamicallyAccessedMembers( @@ -2162,8 +2162,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage( + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage( DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } } @@ -2226,9 +2226,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet { string arg1 = MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(calledMethod, "RequiresUnreferencedCodeAttribute")); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg(DiagnosticUtilities.GetRequiresAttributeUrl(calledMethod, "RequiresUnreferencedCodeAttribute")); - string message = new DiagnosticString(DiagnosticId.RequiresUnreferencedCode).GetMessage(calledMethod.GetDisplayName(), arg1, arg2); - _logger.LogWarning(message, (int)DiagnosticId.RequiresUnreferencedCode, callingMethodBody, offset, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(callingMethodBody, offset, DiagnosticId.RequiresUnreferencedCode, calledMethod.GetDisplayName(), arg1, arg2); } if (shouldEnableAotWarnings && @@ -2241,9 +2240,8 @@ static void LogDynamicCodeWarning(Logger logger, MethodIL callingMethodBody, int { string arg1 = MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(calledMethod, "RequiresDynamicCodeAttribute")); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg(DiagnosticUtilities.GetRequiresAttributeUrl(calledMethod, "RequiresDynamicCodeAttribute")); - string message = new DiagnosticString(DiagnosticId.RequiresDynamicCode).GetMessage(calledMethod.GetDisplayName(), arg1, arg2); - logger.LogWarning(message, (int)DiagnosticId.RequiresDynamicCode, callingMethodBody, offset, MessageSubCategory.AotAnalysis); + logger.LogWarning(callingMethodBody, offset, DiagnosticId.RequiresDynamicCode, calledMethod.GetDisplayName(), arg1, arg2); } // To get good reporting of errors we need to track the origin of the value for all method calls @@ -2933,32 +2931,20 @@ void WarnOnReflectionAccess(ref ReflectionPatternContext context, TypeSystemEnti // are not suppressed in RUC scopes. Here the scope represents the DynamicallyAccessedMembers // annotation on a type, not a callsite which uses the annotation. We always want to warn about // possible reflection access indicated by these annotations. - - var message = string.Format( - "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements.", - ((TypeOrigin)context.MemberWithRequirements).GetDisplayName(), - entity.GetDisplayName()); - _logger.LogWarning(message, 2115, context.Source, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers, + ((TypeOrigin)context.MemberWithRequirements).GetDisplayName(), entity.GetDisplayName()); } else { if (entity is FieldDesc && context.ReportingEnabled) { - _logger.LogWarning( - $"Field '{entity.GetDisplayName()}' with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field.", - 2110, - context.Source, - MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersFieldAccessedViaReflection, entity.GetDisplayName()); } else { Debug.Assert(entity is MethodDesc); - _logger.LogWarning( - $"Method '{entity.GetDisplayName()}' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.", - 2111, - context.Source, - MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName()); } } } @@ -2969,11 +2955,8 @@ void MarkMethod(ref ReflectionPatternContext reflectionContext, MethodDesc metho { if (_purpose == ScanningPurpose.GetTypeDataflow) { - var message = string.Format( - "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.", - ((TypeOrigin)reflectionContext.MemberWithRequirements).GetDisplayName(), - method.GetDisplayName()); - _logger.LogWarning(message, 2113, reflectionContext.Source, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(reflectionContext.Source, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode, + ((TypeOrigin)reflectionContext.MemberWithRequirements).GetDisplayName(), method.GetDisplayName()); } } @@ -3066,8 +3049,8 @@ void ValidateGenericMethodInstantiation( if (!AnalyzeGenericInstantiationTypeArray(genericParametersArray, ref reflectionContext, reflectionMethod, genericMethod.GetMethodDefinition().Instantiation)) { reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(reflectionMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(reflectionMethod))); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs index 99d97784e7811..61a48fe965a0c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs @@ -7,6 +7,8 @@ using Internal.IL; using Internal.TypeSystem; +using ILLink.Shared; + namespace ILCompiler.Dataflow { /// diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs index a4388b4eeb4a9..9857c633784db 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs @@ -36,6 +36,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) if (_details.Variance != null) { + sb.Append("__Variance__"); for (int i = 0; i < _details.Variance.Length; i++) { sb.Append('_'); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs index e690b5d420078..5462b8fedc11b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs @@ -85,6 +85,9 @@ public class ObjectWriter : IDisposable, ITypesDebugInfoWriter [DllImport(NativeObjectWriterFileName)] private static extern void FinishObjWriter(IntPtr objWriter); + [DllImport(NativeObjectWriterFileName)] + private static extern void SetDwarfVersion(IntPtr objWriter, ushort v); + [DllImport(NativeObjectWriterFileName)] private static extern void SwitchSection(IntPtr objWriter, string sectionName, CustomSectionAttributes attributes = 0, string comdatName = null); @@ -884,6 +887,11 @@ public ObjectWriter(string objectFilePath, NodeFactory factory, ObjectWritingOpt _isSingleFileCompilation = _nodeFactory.CompilationModuleGroup.IsSingleFileCompilation; _userDefinedTypeDescriptor = new UserDefinedTypeDescriptor(this, factory); _options = options; + + if ((_options & ObjectWritingOptions.UseDwarf5) != 0) + { + SetDwarfVersion(_nativeObjectWriter, 5); + } } public void Dispose() @@ -1319,5 +1327,6 @@ public enum ObjectWritingOptions { GenerateDebugInfo = 0x01, ControlFlowGuard = 0x02, + UseDwarf5 = 0x4, } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs new file mode 100644 index 0000000000000..773c061081e45 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs @@ -0,0 +1,52 @@ +// 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.Xml.XPath; +using ILLink.Shared; +using Internal.TypeSystem; + +namespace ILCompiler +{ + public static class FeatureSettings + { + public static bool ShouldProcessElement(XPathNavigator nav, IReadOnlyDictionary featureSwitchValues) + { + var feature = GetAttribute(nav, "feature"); + if (string.IsNullOrEmpty(feature)) + return true; + + var value = GetAttribute(nav, "featurevalue"); + if (string.IsNullOrEmpty(value)) + { + //context.LogError(null, DiagnosticId.XmlFeatureDoesNotSpecifyFeatureValue, documentLocation, feature); + return false; + } + + if (!bool.TryParse(value, out bool bValue)) + { + //context.LogError(null, DiagnosticId.XmlUnsupportedNonBooleanValueForFeature, documentLocation, feature); + return false; + } + + var isDefault = GetAttribute(nav, "featuredefault"); + bool bIsDefault = false; + if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault)) + { + //context.LogError(null, DiagnosticId.XmlDocumentLocationHasInvalidFeatureDefault, documentLocation); + return false; + } + + if (!featureSwitchValues.TryGetValue(feature, out bool featureSetting)) + return bIsDefault; + + return bValue == featureSetting; + } + + public static string GetAttribute(XPathNavigator nav, string attribute) + { + return nav.GetAttribute(attribute, String.Empty); + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs index 5f06913b97d37..20050db2c8cda 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs @@ -792,7 +792,7 @@ public MethodIL EmitIL(MethodDesc method) } } - private class SubstitutionsReader : ProcessLinkerXmlBase + private class SubstitutionsReader : ProcessXmlBase { private readonly Dictionary _methodSubstitutions; private readonly Dictionary _fieldSubstitutions; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs index 378af488af020..cfbfe6d7a5e47 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs @@ -8,6 +8,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler @@ -232,14 +234,9 @@ public void LogWarnings(Logger logger) if (!reportedProblems.Add(new EntityPair(ownerDefinition, referentDefinition))) continue; - string message = $"Generic expansion to '{actualProblem.Key.Referent.GetDisplayName()}' was aborted " + - "due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. " + - "Generic recursion also negatively affects compilation speed and the size of the compilation output. " + - "It is advisable to remove the source of the generic recursion by restructuring the program around " + - "the source of recursion. The source of generic recursion might include: "; - ModuleCycleInfo cycleInfo = actualProblem.Value; bool first = true; + string message = ""; foreach (TypeSystemEntity cycleEntity in cycleInfo.EntitiesInCycles) { if (!first) @@ -250,7 +247,7 @@ public void LogWarnings(Logger logger) message += $"'{cycleEntity.GetDisplayName()}'"; } - logger.LogWarning(message, 3054, actualProblem.Key.Owner, MessageSubCategory.AotAnalysis); + logger.LogWarning(actualProblem.Key.Owner, DiagnosticId.GenericRecursionCycle, actualProblem.Key.Referent.GetDisplayName(), message); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs index f9df59bfa816f..3b2b3a2e25384 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs @@ -100,7 +100,7 @@ public AssemblyFeatureInfo(EcmaModule module, IReadOnlyDictionary } } - private class SubstitutionsReader : ProcessLinkerXmlBase + private class SubstitutionsReader : ProcessXmlBase { private readonly HashSet _substitutions = new HashSet(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs index c5101bde818fa..e157381162aa5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs @@ -1,316 +1,511 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Linq; using System.Reflection; +using System.Reflection.Metadata; using System.Text; +using System.Text.RegularExpressions; using System.Xml; - +using System.Xml.Linq; +using System.Xml.XPath; +using ILLink.Shared; using Internal.TypeSystem; +#nullable enable + namespace ILCompiler { - /// - /// Base class for readers of IL Linker XML file format. - /// - internal abstract class ProcessLinkerXmlBase + [Flags] + public enum AllowedAssemblies { - private readonly XmlReader _reader; - private readonly ModuleDesc _owningModule; + ContainingAssembly = 0x1, + AnyAssembly = 0x2 | ContainingAssembly, + AllAssemblies = 0x4 | AnyAssembly + } + + public abstract class ProcessLinkerXmlBase + { + const string FullNameAttributeName = "fullname"; + const string LinkerElementName = "linker"; + const string TypeElementName = "type"; + const string SignatureAttributeName = "signature"; + const string NameAttributeName = "name"; + const string FieldElementName = "field"; + const string MethodElementName = "method"; + const string EventElementName = "event"; + const string PropertyElementName = "property"; + const string AllAssembliesFullName = "*"; + protected const string XmlNamespace = ""; + + protected readonly string _xmlDocumentLocation; + readonly XPathNavigator _document; + protected readonly ModuleDesc? _owningModule; private readonly IReadOnlyDictionary _featureSwitchValues; protected readonly TypeSystemContext _context; - public ProcessLinkerXmlBase(TypeSystemContext context, XmlReader reader, ModuleDesc owningModule, IReadOnlyDictionary featureSwitchValues) + protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) { - _reader = reader; - _owningModule = owningModule; - _featureSwitchValues = featureSwitchValues; _context = context; + using (documentStream) + { + _document = XDocument.Load(documentStream, LoadOptions.SetLineInfo).CreateNavigator(); + } + _xmlDocumentLocation = xmlDocumentLocation; + _featureSwitchValues = featureSwitchValues; } - public void ProcessXml() + protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) + : this(context, documentStream, xmlDocumentLocation, featureSwitchValues) { - if (_reader.IsStartElement() && _reader.Name == "linker") + _owningModule = resourceAssembly ?? throw new ArgumentNullException(nameof(resourceAssembly)); + } + + protected virtual bool ShouldProcessElement(XPathNavigator nav) => FeatureSettings.ShouldProcessElement(nav, _featureSwitchValues); + + protected virtual void ProcessXml(bool ignoreResource) + { + if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly) && _owningModule == null) + throw new InvalidOperationException("The containing assembly must be specified for XML which is restricted to modifying that assembly only."); + + try { - if (!ShouldProcessElement()) + XPathNavigator nav = _document.CreateNavigator(); + + // Initial structure check - ignore XML document which don't look like linker XML format + if (!nav.MoveToChild(LinkerElementName, XmlNamespace)) + return; + + if (_owningModule != null) + { + if (ignoreResource) + return; + } + + if (!ShouldProcessElement(nav)) return; - _reader.Read(); + ProcessAssemblies(nav); - ProcessAssemblies(); + // For embedded XML, allow not specifying the assembly explicitly in XML. + if (_owningModule != null) + ProcessAssembly(_owningModule, nav, warnOnUnresolvedTypes: true); + + } + catch (Exception ex) + { + // throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.ErrorProcessingXmlLocation, _xmlDocumentLocation), ex); + throw ex; } } - protected string GetAttribute(string attribute) - { - return _reader.GetAttribute(attribute); - } + protected virtual AllowedAssemblies AllowedAssemblySelector { get => _owningModule != null ? AllowedAssemblies.ContainingAssembly : AllowedAssemblies.AnyAssembly; } - protected bool IsEmpty() + bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyName? assemblyName) { - return _reader.IsEmptyElement; + assemblyName = null; + if (GetFullName(nav) == AllAssembliesFullName) + return true; + + assemblyName = GetAssemblyName(nav); + return false; } - private void ProcessAssemblies() + protected virtual void ProcessAssemblies(XPathNavigator nav) { - while (_reader.IsStartElement()) + foreach (XPathNavigator assemblyNav in nav.SelectChildren("assembly", "")) { - if (_reader.Name == "assembly") + // Errors for invalid assembly names should show up even if this element will be + // skipped due to feature conditions. + bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyName? name); + if (processAllAssemblies && AllowedAssemblySelector != AllowedAssemblies.AllAssemblies) { - string assemblyName = _reader.GetAttribute("fullname"); + //LogWarning(assemblyNav, DiagnosticId.XmlUnsuportedWildcard); + continue; + } - if (assemblyName == "*") + ModuleDesc? assemblyToProcess = null; + if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly)) + { + Debug.Assert(!processAllAssemblies); + Debug.Assert(_owningModule != null); + if (_owningModule.Assembly.GetName().Name != name!.Name) { - // https://github.com/dotnet/runtimelab/issues/1381 - _reader.Skip(); + //LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _resource.Value.Assembly.Name.Name, name.ToString()); continue; } + assemblyToProcess = _owningModule; + } - // Errors for invalid assembly names should show up even if this element will be - // skipped due to feature conditions. - var name = new AssemblyName(assemblyName); + if (!ShouldProcessElement(assemblyNav)) + continue; - if (!ShouldProcessElement()) - { - _reader.Skip(); - continue; - } - - ModuleDesc assembly = GetAssembly(name); + if (processAllAssemblies) + { + throw new NotImplementedException(); + // We could avoid loading all references in this case: https://github.com/dotnet/linker/issues/1708 + //foreach (ModuleDesc assembly in GetReferencedAssemblies()) + // ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: false); + } + else + { + Debug.Assert(!processAllAssemblies); + ModuleDesc? assembly = assemblyToProcess ?? _context.ResolveAssembly(name!); if (assembly == null) { - //Context.LogWarning($"Could not resolve assembly '{name.Name}'", 2007, _xmlDocumentLocation); - _reader.Skip(); + //LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name); continue; } - _reader.Read(); - - ProcessAssembly(assembly); - } - else if (_reader.Name == "type") - { - ProcessType(_owningModule); - } - else if (_reader.Name == "resource") - { - ProcessResource(_owningModule); - } - else - { - _reader.Skip(); + ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: true); } } } - protected ModuleDesc GetAssembly(AssemblyName name) - { - return _context.ResolveAssembly(name); - } - private void ProcessAssembly(ModuleDesc assembly) + protected abstract void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes); + + protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) { - while (_reader.IsStartElement()) + foreach (XPathNavigator typeNav in nav.SelectChildren(TypeElementName, XmlNamespace)) { - if (_reader.Name == "type") + + if (!ShouldProcessElement(typeNav)) + continue; + + string fullname = GetFullName(typeNav); + + if (fullname.IndexOf("*") != -1) { - ProcessType(assembly); + if (ProcessTypePattern(fullname, assembly, typeNav)) + continue; } - else if (_reader.Name == "resource") + + // TODO: Process exported types + + // TODO: Semantics differ and xml format is cecil specific, therefore they are discrepancies on things like nested types + TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, fullname, throwIfNotFound: false); + + if (type == null) { - ProcessResource(assembly); + //if (warnOnUnresolvedTypes) + // LogWarning(typeNav, DiagnosticId.XmlCouldNotResolveType, fullname); + continue; } - _reader.Skip(); + ProcessType(type, typeNav); } + } + + void MatchType(TypeDesc type, Regex regex, XPathNavigator nav) + { + StringBuilder sb = new StringBuilder(); + CecilTypeNameFormatter.Instance.AppendName(sb, type); + if (regex.Match(sb.ToString()).Success) + ProcessType(type, nav); + } - _reader.ReadEndElement(); + protected virtual bool ProcessTypePattern(string fullname, ModuleDesc assembly, XPathNavigator nav) + { + Regex regex = new Regex(fullname.Replace(".", @"\.").Replace("*", "(.*)")); + + foreach (TypeDesc type in assembly.GetAllTypes()) + MatchType(type, regex, nav); + + return true; } - private void ProcessType(ModuleDesc assembly) + protected abstract void ProcessType(TypeDesc type, XPathNavigator nav); + + protected void ProcessTypeChildren(TypeDesc type, XPathNavigator nav, object? customData = null) { - if (ShouldProcessElement()) + if (nav.HasChildren) { - string typeName = _reader.GetAttribute("fullname"); + ProcessSelectedFields(nav, type); + ProcessSelectedMethods(nav, type, customData); + // TODO: In order to be compatible with the format we need to be able to recognize properties, events and maybe attributes + } + } - if (typeName.Contains('*')) - throw new NotSupportedException(); + void ProcessSelectedFields(XPathNavigator nav, TypeDesc type) + { + foreach (XPathNavigator fieldNav in nav.SelectChildren(FieldElementName, XmlNamespace)) + { + if (!ShouldProcessElement(fieldNav)) + continue; + ProcessField(type, fieldNav); + } + } - TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, typeName, throwIfNotFound: false); - if (type == null) + protected virtual void ProcessField(TypeDesc type, XPathNavigator nav) + { + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) + { + FieldDesc? field = GetField(type, signature); + if (field == null) { - //Context.LogWarning ($"Could not resolve type '{fullname}'", 2008, _xmlDocumentLocation); - _reader.Skip(); + //LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, signature, type.GetDisplayName()); return; } - _reader.Read(); + ProcessField(type, field, nav); + } - while (_reader.IsStartElement()) + string name = GetName(nav); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + foreach (FieldDesc field in type.GetFields()) { - if (_reader.Name == "method") - { - ProcessMethod(type); - } - else if (_reader.Name == "field") + if (field.Name == name) { - ProcessField(type); - } - else if (_reader.Name == "attribute") - { - ProcessAttribute(type); + foundMatch = true; + ProcessField(type, field, nav); } + } + - _reader.Skip(); + if (!foundMatch) + { + // LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName()); } } + } + + protected static FieldDesc? GetField(TypeDesc type, string signature) + { + StringBuilder sb = new StringBuilder(); + foreach (FieldDesc field in type.GetFields()) + { + sb.Clear(); + CecilTypeNameFormatter.Instance.AppendName(sb, field.FieldType); + if (signature == sb.ToString() + " " + field.Name) + return field; + } + + return null; + } + + protected virtual void ProcessField(TypeDesc type, FieldDesc field, XPathNavigator nav) { } - _reader.Skip(); + void ProcessSelectedMethods(XPathNavigator nav, TypeDesc type, object? customData) + { + foreach (XPathNavigator methodNav in nav.SelectChildren(MethodElementName, XmlNamespace)) + { + if (!ShouldProcessElement(methodNav)) + continue; + ProcessMethod(type, methodNav, customData); + } } - private void ProcessMethod(TypeDesc type) + protected virtual void ProcessMethod(TypeDesc type, XPathNavigator nav, object? customData) { - if (ShouldProcessElement()) + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) { - string signature = _reader.GetAttribute("signature"); - if (!String.IsNullOrEmpty(signature)) + MethodDesc? method = GetMethod(type, signature); + if (method == null) { - MethodDesc method = GetMethod(type, signature); - if (method == null) - { - //Context.LogWarning($"Could not find method '{signature}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation); - return; - } - - ProcessMethod(method); + //LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName()); + return; } - string methodName = _reader.GetAttribute("name"); - if (!String.IsNullOrEmpty(methodName)) - { - bool foundMatch = false; - foreach (MethodDesc method in type.GetMethods()) - { - if (method.Name == methodName) - { - foundMatch = true; - ProcessMethod(method); - } - } + ProcessMethod(type, method, nav, customData); + } - if (!foundMatch) + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + foreach (MethodDesc method in type.GetAllMethods()) + { + if (name == method.Name) { - //Context.LogWarning($"Could not find method '{name}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation); + foundMatch = true; + ProcessMethod(type, method, nav, customData); } } + if (!foundMatch) + { + // LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, name, type.GetDisplayName()); + } } } - protected virtual void ProcessMethod(MethodDesc method) + protected virtual MethodDesc? GetMethod(TypeDesc type, string signature) => null; + + protected virtual void ProcessMethod(TypeDesc type, MethodDesc method, XPathNavigator nav, object? customData) { } + +#if false + void ProcessSelectedEvents(XPathNavigator nav, TypeDefinition type, object? customData) { + foreach (XPathNavigator eventNav in nav.SelectChildren(EventElementName, XmlNamespace)) + { + if (!ShouldProcessElement(eventNav)) + continue; + ProcessEvent(type, eventNav, customData); + } } - private void ProcessField(TypeDesc type) + protected virtual void ProcessEvent(TypeDefinition type, XPathNavigator nav, object? customData) { - if (ShouldProcessElement()) + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) { - string fieldName = _reader.GetAttribute("name"); - if (!String.IsNullOrEmpty(fieldName)) + EventDefinition? @event = GetEvent(type, signature); + if (@event == null) { - FieldDesc field = type.GetField(fieldName); + LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, signature, type.GetDisplayName()); + return; + } - if (field == null) - { - //Context.LogWarning($"Could not find field '{name}' on type '{type.GetDisplayName()}'", 2012, _xmlDocumentLocation); - } - else + ProcessEvent(type, @event, nav, customData); + } + + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + foreach (EventDefinition @event in type.Events) + { + if (@event.Name == name) { - ProcessField(field); + foundMatch = true; + ProcessEvent(type, @event, nav, customData); } } + + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, name, type.GetDisplayName()); + } } } - protected virtual void ProcessField(FieldDesc field) + protected static EventDefinition? GetEvent(TypeDefinition type, string signature) { - } + if (!type.HasEvents) + return null; - protected virtual void ProcessAttribute(TypeDesc type) - { - } + foreach (EventDefinition @event in type.Events) + if (signature == @event.EventType.FullName + " " + @event.Name) + return @event; - protected virtual void ProcessResource(ModuleDesc module) - { + return null; } - protected MethodDesc GetMethod(TypeDesc type, string signature) - { - foreach (MethodDesc meth in type.GetMethods()) - if (signature == GetMethodSignature(meth, false)) - return meth; + protected virtual void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { } - return null; + void ProcessSelectedProperties(XPathNavigator nav, TypeDefinition type, object? customData) + { + foreach (XPathNavigator propertyNav in nav.SelectChildren(PropertyElementName, XmlNamespace)) + { + if (!ShouldProcessElement(propertyNav)) + continue; + ProcessProperty(type, propertyNav, customData); + } } - public static string GetMethodSignature(MethodDesc meth, bool includeGenericParameters) + protected virtual void ProcessProperty(TypeDefinition type, XPathNavigator nav, object? customData) { - StringBuilder sb = new StringBuilder(); - CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature.ReturnType); - sb.Append(' '); - sb.Append(meth.Name); - if (includeGenericParameters && meth.HasInstantiation) + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) { - sb.Append('`'); - sb.Append(meth.Instantiation.Length); + PropertyDefinition? property = GetProperty(type, signature); + if (property == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, signature, type.GetDisplayName()); + return; + } + + ProcessProperty(type, property, nav, customData, true); } - sb.Append('('); - for (int i = 0; i < meth.Signature.Length; i++) + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) { - if (i > 0) - sb.Append(','); + bool foundMatch = false; + foreach (PropertyDefinition property in type.Properties) + { + if (property.Name == name) + { + foundMatch = true; + ProcessProperty(type, property, nav, customData, false); + } + } - CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature[i]); + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, name, type.GetDisplayName()); + } } + } + + protected static PropertyDefinition? GetProperty(TypeDefinition type, string signature) + { + if (!type.HasProperties) + return null; + + foreach (PropertyDefinition property in type.Properties) + if (signature == property.PropertyType.FullName + " " + property.Name) + return property; - sb.Append(')'); - return sb.ToString(); + return null; } - private bool ShouldProcessElement() + protected virtual void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) { } +#endif + + protected virtual AssemblyName GetAssemblyName(XPathNavigator nav) { - string feature = _reader.GetAttribute("feature"); - if (string.IsNullOrEmpty(feature)) - return true; + return new AssemblyName(GetFullName(nav)); + } - string value = _reader.GetAttribute("featurevalue"); - if (string.IsNullOrEmpty(value)) - { - //context.LogError($"Failed to process '{documentLocation}'. Feature '{feature}' does not specify a 'featurevalue' attribute", 1001); - return false; - } + protected static string GetFullName(XPathNavigator nav) + { + return GetAttribute(nav, FullNameAttributeName); + } - if (!bool.TryParse(value, out bool bValue)) - { - //context.LogError($"Failed to process '{documentLocation}'. Unsupported non-boolean feature definition '{feature}'", 1002); - return false; - } + protected static string GetName(XPathNavigator nav) + { + return GetAttribute(nav, NameAttributeName); + } - var isDefault = _reader.GetAttribute("featuredefault"); - bool bIsDefault = false; - if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault)) - { - //context.LogError($"Failed to process '{documentLocation}'. Unsupported value for featuredefault attribute", 1014); - return false; - } + protected static string GetSignature(XPathNavigator nav) + { + return GetAttribute(nav, SignatureAttributeName); + } - if (!_featureSwitchValues.TryGetValue(feature, out bool featureSetting)) - return bIsDefault; + protected static string GetAttribute(XPathNavigator nav, string attribute) + { + return nav.GetAttribute(attribute, XmlNamespace); + } - return bValue == featureSetting; +#if false + protected MessageOrigin GetMessageOriginForPosition(XPathNavigator position) + { + return (position is IXmlLineInfo lineInfo) + ? new MessageOrigin(_xmlDocumentLocation, lineInfo.LineNumber, lineInfo.LinePosition, _resource?.Assembly) + : new MessageOrigin(_xmlDocumentLocation, 0, 0, _resource?.Assembly); + } + protected void LogWarning(string message, int warningCode, XPathNavigator position) + { + _context.LogWarning(message, warningCode, GetMessageOriginForPosition(position)); + } + + protected void LogWarning(XPathNavigator position, DiagnosticId id, params string[] args) + { + _context.LogWarning(GetMessageOriginForPosition(position), id, args); } +#endif class CecilTypeNameFormatter : TypeNameFormatter { @@ -399,6 +594,106 @@ protected override void AppendNameForNestedType(StringBuilder sb, DefType nested sb.Append('/'); sb.Append(nestedType.Name); } + +#if false + public bool TryConvertValue(string value, TypeDesc type, out object? result) + { + switch (type.UnderlyingType.Category) + { + case TypeFlags.Boolean: + if ((bool.TryParse(value, out bool bvalue))) + { + result = bvalue ? 1 : 0; + return true; + } + else + goto case TypeFlags.Int32; + + case TypeFlags.Byte: + if (!byte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out byte byteresult)) + break; + + result = (int)byteresult; + return true; + + case TypeFlags.SByte: + if (!sbyte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out sbyte sbyteresult)) + break; + + result = (int)sbyteresult; + return true; + + case TypeFlags.Int16: + if (!short.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out short shortresult)) + break; + + result = (int)shortresult; + return true; + + case TypeFlags.UInt16: + if (!ushort.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort ushortresult)) + break; + + result = (int)ushortresult; + return true; + + case TypeFlags.Int32: + if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult)) + break; + + result = iresult; + return true; + + case TypeFlags.UInt32: + if (!uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint uresult)) + break; + + result = (int)uresult; + return true; + + case TypeFlags.Double: + if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out double dresult)) + break; + + result = dresult; + return true; + + case TypeFlags.Single: + if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fresult)) + break; + + result = fresult; + return true; + + case TypeFlags.Int64: + if (!long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long lresult)) + break; + + result = lresult; + return true; + + case TypeFlags.UInt64: + if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong ulresult)) + break; + + result = (long)ulresult; + return true; + + case TypeFlags.Char: + if (!char.TryParse(value, out char chresult)) + break; + + result = (int)chresult; + return true; + + default: + throw new NotSupportedException(type.ToString()); + } + + result = null; + return false; + } +#endif } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs new file mode 100644 index 0000000000000..b00f56a0c2ce4 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs @@ -0,0 +1,404 @@ +// 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.Reflection; +using System.Text; +using System.Xml; + +using Internal.TypeSystem; + +namespace ILCompiler +{ + /// + /// Base class for readers of IL Linker XML file format. + /// + internal abstract class ProcessXmlBase + { + private readonly XmlReader _reader; + private readonly ModuleDesc _owningModule; + private readonly IReadOnlyDictionary _featureSwitchValues; + protected readonly TypeSystemContext _context; + + public ProcessXmlBase(TypeSystemContext context, XmlReader reader, ModuleDesc owningModule, IReadOnlyDictionary featureSwitchValues) + { + _reader = reader; + _owningModule = owningModule; + _featureSwitchValues = featureSwitchValues; + _context = context; + } + + public void ProcessXml() + { + if (_reader.IsStartElement() && _reader.Name == "linker") + { + if (!ShouldProcessElement()) + return; + + _reader.Read(); + + ProcessAssemblies(); + } + } + + protected string GetAttribute(string attribute) + { + return _reader.GetAttribute(attribute); + } + + protected bool IsEmpty() + { + return _reader.IsEmptyElement; + } + + private void ProcessAssemblies() + { + while (_reader.IsStartElement()) + { + if (_reader.Name == "assembly") + { + string assemblyName = _reader.GetAttribute("fullname"); + + if (assemblyName == "*") + { + // https://github.com/dotnet/runtimelab/issues/1381 + _reader.Skip(); + continue; + } + + // Errors for invalid assembly names should show up even if this element will be + // skipped due to feature conditions. + var name = new AssemblyName(assemblyName); + + if (!ShouldProcessElement()) + { + _reader.Skip(); + continue; + } + + ModuleDesc assembly = GetAssembly(name); + + if (assembly == null) + { + //Context.LogWarning($"Could not resolve assembly '{name.Name}'", 2007, _xmlDocumentLocation); + _reader.Skip(); + continue; + } + + _reader.Read(); + + ProcessAssembly(assembly); + } + else if (_reader.Name == "type") + { + ProcessType(_owningModule); + } + else if (_reader.Name == "resource") + { + ProcessResource(_owningModule); + } + else + { + _reader.Skip(); + } + } + } + + protected ModuleDesc GetAssembly(AssemblyName name) + { + return _context.ResolveAssembly(name); + } + + private void ProcessAssembly(ModuleDesc assembly) + { + while (_reader.IsStartElement()) + { + if (_reader.Name == "type") + { + ProcessType(assembly); + } + else if (_reader.Name == "resource") + { + ProcessResource(assembly); + } + + _reader.Skip(); + } + + _reader.ReadEndElement(); + } + + private void ProcessType(ModuleDesc assembly) + { + if (ShouldProcessElement()) + { + string typeName = _reader.GetAttribute("fullname"); + + if (typeName.Contains('*')) + throw new NotSupportedException(); + + TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, typeName, throwIfNotFound: false); + if (type == null) + { + //Context.LogWarning ($"Could not resolve type '{fullname}'", 2008, _xmlDocumentLocation); + _reader.Skip(); + return; + } + + _reader.Read(); + + while (_reader.IsStartElement()) + { + if (_reader.Name == "method") + { + ProcessMethod(type); + } + else if (_reader.Name == "field") + { + ProcessField(type); + } + else if (_reader.Name == "attribute") + { + ProcessAttribute(type); + } + + _reader.Skip(); + } + } + + _reader.Skip(); + } + + private void ProcessMethod(TypeDesc type) + { + if (ShouldProcessElement()) + { + string signature = _reader.GetAttribute("signature"); + if (!String.IsNullOrEmpty(signature)) + { + MethodDesc method = GetMethod(type, signature); + if (method == null) + { + //Context.LogWarning($"Could not find method '{signature}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation); + return; + } + + ProcessMethod(method); + } + + string methodName = _reader.GetAttribute("name"); + if (!String.IsNullOrEmpty(methodName)) + { + bool foundMatch = false; + foreach (MethodDesc method in type.GetMethods()) + { + if (method.Name == methodName) + { + foundMatch = true; + ProcessMethod(method); + } + } + + if (!foundMatch) + { + //Context.LogWarning($"Could not find method '{name}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation); + } + } + } + } + + protected virtual void ProcessMethod(MethodDesc method) + { + } + + private void ProcessField(TypeDesc type) + { + if (ShouldProcessElement()) + { + string fieldName = _reader.GetAttribute("name"); + if (!String.IsNullOrEmpty(fieldName)) + { + FieldDesc field = type.GetField(fieldName); + + if (field == null) + { + //Context.LogWarning($"Could not find field '{name}' on type '{type.GetDisplayName()}'", 2012, _xmlDocumentLocation); + } + else + { + ProcessField(field); + } + } + } + } + + protected virtual void ProcessField(FieldDesc field) + { + } + + protected virtual void ProcessAttribute(TypeDesc type) + { + } + + protected virtual void ProcessResource(ModuleDesc module) + { + } + + protected MethodDesc GetMethod(TypeDesc type, string signature) + { + foreach (MethodDesc meth in type.GetMethods()) + if (signature == GetMethodSignature(meth, false)) + return meth; + + return null; + } + + 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(); + } + + private bool ShouldProcessElement() + { + string feature = _reader.GetAttribute("feature"); + if (string.IsNullOrEmpty(feature)) + return true; + + string value = _reader.GetAttribute("featurevalue"); + if (string.IsNullOrEmpty(value)) + { + //context.LogError($"Failed to process '{documentLocation}'. Feature '{feature}' does not specify a 'featurevalue' attribute", 1001); + return false; + } + + if (!bool.TryParse(value, out bool bValue)) + { + //context.LogError($"Failed to process '{documentLocation}'. Unsupported non-boolean feature definition '{feature}'", 1002); + return false; + } + + var isDefault = _reader.GetAttribute("featuredefault"); + bool bIsDefault = false; + if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault)) + { + //context.LogError($"Failed to process '{documentLocation}'. Unsupported value for featuredefault attribute", 1014); + return false; + } + + if (!_featureSwitchValues.TryGetValue(feature, out bool featureSetting)) + return bIsDefault; + + return bValue == featureSetting; + } + + class CecilTypeNameFormatter : TypeNameFormatter + { + public static readonly CecilTypeNameFormatter Instance = new CecilTypeNameFormatter(); + + public override void AppendName(StringBuilder sb, ArrayType type) + { + AppendName(sb, type.ElementType); + sb.Append('['); + if (type.Rank > 1) + sb.Append(new string(',', type.Rank - 1)); + sb.Append(']'); + } + public override void AppendName(StringBuilder sb, ByRefType type) + { + AppendName(sb, type.ParameterType); + sb.Append('&'); + } + + public override void AppendName(StringBuilder sb, PointerType type) + { + AppendName(sb, type.ParameterType); + sb.Append('*'); + } + + public override void AppendName(StringBuilder sb, FunctionPointerType type) + { + sb.Append(" "); + AppendName(sb, type.Signature.ReturnType); + sb.Append(" *"); + + sb.Append("("); + + for (int i = 0; i < type.Signature.Length; i++) + { + var parameter = type.Signature[i]; + if (i > 0) + sb.Append(","); + + AppendName(sb, parameter); + } + + sb.Append(")"); + } + + public override void AppendName(StringBuilder sb, GenericParameterDesc type) + { + sb.Append(type.Name); + } + public override void AppendName(StringBuilder sb, SignatureMethodVariable type) + { + } + public override void AppendName(StringBuilder sb, SignatureTypeVariable type) + { + } + protected override void AppendNameForInstantiatedType(StringBuilder sb, DefType type) + { + AppendName(sb, type.GetTypeDefinition()); + + sb.Append('<'); + + for (int i = 0; i < type.Instantiation.Length; i++) + { + if (i != 0) + sb.Append(','); + + AppendName(sb, type.Instantiation[i]); + } + + sb.Append('>'); + } + protected override void AppendNameForNamespaceType(StringBuilder sb, DefType type) + { + if (!String.IsNullOrEmpty(type.Namespace)) + { + sb.Append(type.Namespace); + sb.Append('.'); + } + + sb.Append(type.Name); + } + + protected override void AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType) + { + AppendName(sb, containingType); + sb.Append('/'); + sb.Append(nestedType.Name); + } + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs new file mode 100644 index 0000000000000..403eb9207342e --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs @@ -0,0 +1,174 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml.XPath; +using ILLink.Shared; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public class BodySubstitutionParser : ProcessLinkerXmlBase + { + SubstitutionInfo? _substitutionInfo; + + public BodySubstitutionParser(LinkContext context, Stream documentStream, string xmlDocumentLocation) + : base(context, documentStream, xmlDocumentLocation) + { + } + + public BodySubstitutionParser(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") + : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation) + { + } + + public void Parse(SubstitutionInfo xmlInfo) + { + _substitutionInfo = xmlInfo; + bool stripSubstitutions = _context.IsOptimizationEnabled(CodeOptimizations.RemoveSubstitutions, _resource?.Assembly); + ProcessXml(stripSubstitutions, _context.IgnoreSubstitutions); + } + + protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) + { + ProcessTypes(assembly, nav, warnOnUnresolvedTypes); + ProcessResources(assembly, nav); + } + + protected override TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => null; + + protected override bool ProcessTypePattern(string fullname, AssemblyDefinition assembly, XPathNavigator nav) => false; + + protected override void ProcessType(TypeDefinition type, XPathNavigator nav) + { + Debug.Assert(ShouldProcessElement(nav)); + ProcessTypeChildren(type, nav); + } + + protected override void ProcessMethod(TypeDefinition type, XPathNavigator methodNav, object? _customData) + { + Debug.Assert(_substitutionInfo != null); + string signature = GetSignature(methodNav); + if (string.IsNullOrEmpty(signature)) + return; + + MethodDefinition? method = FindMethod(type, signature); + if (method == null) + { + LogWarning(methodNav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName()); + return; + } + + string action = GetAttribute(methodNav, "body"); + switch (action) + { + case "remove": + _substitutionInfo.SetMethodAction(method, MethodAction.ConvertToThrow); + return; + case "stub": + string value = GetAttribute(methodNav, "value"); + if (!string.IsNullOrEmpty(value)) + { + if (!TryConvertValue(value, method.ReturnType, out object? res)) + { + LogWarning(methodNav, DiagnosticId.XmlInvalidValueForStub, method.GetDisplayName()); + return; + } + + _substitutionInfo.SetMethodStubValue(method, res); + } + + _substitutionInfo.SetMethodAction(method, MethodAction.ConvertToStub); + return; + default: + LogWarning(methodNav, DiagnosticId.XmlUnkownBodyModification, action, method.GetDisplayName()); + return; + } + } + + protected override void ProcessField(TypeDefinition type, XPathNavigator fieldNav) + { + Debug.Assert(_substitutionInfo != null); + string name = GetAttribute(fieldNav, "name"); + if (string.IsNullOrEmpty(name)) + return; + + var field = type.Fields.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)) + { + LogWarning(fieldNav, DiagnosticId.XmlMissingSubstitutionValueForField, field.GetDisplayName()); + return; + } + if (!TryConvertValue(value, field.FieldType, out object? res)) + { + LogWarning(fieldNav, DiagnosticId.XmlInvalidSubstitutionValueForField, value, field.GetDisplayName()); + return; + } + + _substitutionInfo.SetFieldValue(field, res); + + string init = GetAttribute(fieldNav, "initialize"); + if (init?.ToLowerInvariant() == "true") + { + _substitutionInfo.SetFieldInit(field); + } + } + + void ProcessResources(AssemblyDefinition assembly, XPathNavigator nav) + { + foreach (XPathNavigator resourceNav in nav.SelectChildren("resource", "")) + { + if (!ShouldProcessElement(resourceNav)) + continue; + + string name = GetAttribute(resourceNav, "name"); + if (String.IsNullOrEmpty(name)) + { + LogWarning(resourceNav, DiagnosticId.XmlMissingNameAttributeInResource); + continue; + } + + string action = GetAttribute(resourceNav, "action"); + if (action != "remove") + { + LogWarning(resourceNav, DiagnosticId.XmlInvalidValueForAttributeActionForResource, action, name); + continue; + } + + EmbeddedResource? resource = assembly.FindEmbeddedResource(name); + if (resource == null) + { + LogWarning(resourceNav, DiagnosticId.XmlCouldNotFindResourceToRemoveInAssembly, name, assembly.Name.Name); + continue; + } + + _context.Annotations.AddResourceToRemove(assembly, resource); + } + } + + static MethodDefinition? FindMethod(TypeDefinition type, string signature) + { + if (!type.HasMethods) + return null; + + foreach (MethodDefinition meth in type.Methods) + if (signature == DescriptorMarker.GetMethodSignature(meth, includeGenericParameters: true)) + return meth; + + return null; + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs new file mode 100644 index 0000000000000..49404575e41f9 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs @@ -0,0 +1,292 @@ +// 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.Diagnostics; +using System.IO; +using System.Text; +using System.Xml.XPath; +using ILLink.Shared; + +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public class DescriptorMarker : ProcessLinkerXmlBase + { + const string NamespaceElementName = "namespace"; + + const string _required = "required"; + const string _preserve = "preserve"; + const string _accessors = "accessors"; + + static readonly string[] _accessorsAll = new string[] { "all" }; + static readonly char[] _accessorsSep = new char[] { ';' }; + + public DescriptorMarker(LinkContext context, Stream documentStream, string xmlDocumentLocation) + : base(context, documentStream, xmlDocumentLocation) + { + } + + public DescriptorMarker(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") + : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation) + { + } + + public void Mark() + { + bool stripDescriptors = _context.IsOptimizationEnabled(CodeOptimizations.RemoveDescriptors, _resource?.Assembly); + ProcessXml(stripDescriptors, _context.IgnoreDescriptors); + } + + protected override AllowedAssemblies AllowedAssemblySelector { get => AllowedAssemblies.AnyAssembly; } + + protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) + { + if (GetTypePreserve(nav) == TypePreserve.All) + { + foreach (var type in assembly.MainModule.Types) + MarkAndPreserveAll(type, nav); + + foreach (var exportedType in assembly.MainModule.ExportedTypes) + _context.MarkingHelpers.MarkExportedType(exportedType, assembly.MainModule, new DependencyInfo(DependencyKind.XmlDescriptor, assembly.MainModule), GetMessageOriginForPosition(nav)); + } + else + { + ProcessTypes(assembly, nav, warnOnUnresolvedTypes); + ProcessNamespaces(assembly, nav); + } + } + + void ProcessNamespaces(AssemblyDefinition assembly, XPathNavigator nav) + { + foreach (XPathNavigator namespaceNav in nav.SelectChildren(NamespaceElementName, XmlNamespace)) + { + if (!ShouldProcessElement(namespaceNav)) + continue; + + string fullname = GetFullName(namespaceNav); + bool foundMatch = false; + foreach (TypeDefinition type in assembly.MainModule.Types) + { + if (type.Namespace != fullname) + continue; + + foundMatch = true; + MarkAndPreserveAll(type, nav); + } + + if (!foundMatch) + { + LogWarning(namespaceNav, DiagnosticId.XmlCouldNotFindAnyTypeInNamespace, fullname); + } + } + } + + void MarkAndPreserveAll(TypeDefinition type, XPathNavigator nav) + { + _context.Annotations.Mark(type, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav)); + _context.Annotations.SetPreserve(type, TypePreserve.All); + + if (!type.HasNestedTypes) + return; + + foreach (TypeDefinition nested in type.NestedTypes) + MarkAndPreserveAll(nested, nav); + } + + protected override TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) + { + _context.MarkingHelpers.MarkExportedType(exported, assembly.MainModule, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav)); + return base.ProcessExportedType(exported, assembly, nav); + } + + protected override void ProcessType(TypeDefinition type, XPathNavigator nav) + { + Debug.Assert(ShouldProcessElement(nav)); + + TypePreserve preserve = GetTypePreserve(nav); + switch (preserve) + { + case TypePreserve.Fields when !type.HasFields: + LogWarning(nav, DiagnosticId.TypeHasNoFieldsToPreserve, type.GetDisplayName()); + break; + + case TypePreserve.Methods when !type.HasMethods: + LogWarning(nav, DiagnosticId.TypeHasNoMethodsToPreserve, type.GetDisplayName()); + break; + + case TypePreserve.Fields: + case TypePreserve.Methods: + case TypePreserve.All: + _context.Annotations.SetPreserve(type, preserve); + break; + } + + bool required = IsRequired(nav); + ProcessTypeChildren(type, nav, required); + + if (!required) + return; + + _context.Annotations.Mark(type, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav)); + + if (type.IsNested) + { + var currentType = type; + while (currentType.IsNested) + { + var parent = currentType.DeclaringType; + _context.Annotations.Mark(parent, new DependencyInfo(DependencyKind.DeclaringType, currentType), GetMessageOriginForPosition(nav)); + currentType = parent; + } + } + } + + static TypePreserve GetTypePreserve(XPathNavigator nav) + { + string attribute = GetAttribute(nav, _preserve); + if (string.IsNullOrEmpty(attribute)) + return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All; + + if (Enum.TryParse(attribute, true, out TypePreserve result)) + return result; + return TypePreserve.Nothing; + } + + protected override void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav) + { + if (_context.Annotations.IsMarked(field)) + LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, field.FullName); + + _context.Annotations.Mark(field, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav)); + } + + protected override void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) + { + if (_context.Annotations.IsMarked(method)) + LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, method.GetDisplayName()); + + _context.Annotations.MarkIndirectlyCalledMethod(method); + _context.Annotations.SetAction(method, MethodAction.Parse); + + if (customData is bool required && !required) + { + _context.Annotations.AddPreservedMethod(type, method); + } + else + { + _context.Annotations.Mark(method, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav)); + } + } + + void ProcessMethodIfNotNull(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) + { + if (method == null) + return; + + ProcessMethod(type, method, nav, customData); + } + + protected override MethodDefinition? GetMethod(TypeDefinition type, string signature) + { + if (type.HasMethods) + foreach (MethodDefinition meth in type.Methods) + if (signature == GetMethodSignature(meth, false)) + return meth; + + return null; + } + + public static string GetMethodSignature(MethodDefinition meth, bool includeGenericParameters) + { + StringBuilder sb = new StringBuilder(); + sb.Append(meth.ReturnType.FullName); + sb.Append(" "); + sb.Append(meth.Name); + if (includeGenericParameters && meth.HasGenericParameters) + { + sb.Append("`"); + sb.Append(meth.GenericParameters.Count); + } + + sb.Append("("); + if (meth.HasParameters) + { + for (int i = 0; i < meth.Parameters.Count; i++) + { + if (i > 0) + sb.Append(","); + + sb.Append(meth.Parameters[i].ParameterType.FullName); + } + } + sb.Append(")"); + return sb.ToString(); + } + + protected override void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) + { + if (_context.Annotations.IsMarked(@event)) + LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, @event.FullName); + + ProcessMethod(type, @event.AddMethod, nav, customData); + ProcessMethod(type, @event.RemoveMethod, nav, customData); + ProcessMethodIfNotNull(type, @event.InvokeMethod, nav, customData); + } + + protected override void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) + { + string[] accessors = fromSignature ? GetAccessors(nav) : _accessorsAll; + + if (_context.Annotations.IsMarked(property)) + LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, property.FullName); + + if (Array.IndexOf(accessors, "all") >= 0) + { + ProcessMethodIfNotNull(type, property.GetMethod, nav, customData); + ProcessMethodIfNotNull(type, property.SetMethod, nav, customData); + return; + } + + if (property.GetMethod != null && Array.IndexOf(accessors, "get") >= 0) + ProcessMethod(type, property.GetMethod, nav, customData); + else if (property.GetMethod == null) + LogWarning(nav, DiagnosticId.XmlCouldNotFindGetAccesorOfPropertyOnType, property.Name, type.FullName); + + if (property.SetMethod != null && Array.IndexOf(accessors, "set") >= 0) + ProcessMethod(type, property.SetMethod, nav, customData); + else if (property.SetMethod == null) + LogWarning(nav, DiagnosticId.XmlCouldNotFindSetAccesorOfPropertyOnType, property.Name, type.FullName); + } + + static bool IsRequired(XPathNavigator nav) + { + string attribute = GetAttribute(nav, _required); + if (attribute == null || attribute.Length == 0) + return true; + + return bool.TryParse(attribute, out bool result) && result; + } + + protected static string[] GetAccessors(XPathNavigator nav) + { + string accessorsValue = GetAttribute(nav, _accessors); + + if (accessorsValue != null) + { + string[] accessors = accessorsValue.Split( + _accessorsSep, StringSplitOptions.RemoveEmptyEntries); + + if (accessors.Length > 0) + { + for (int i = 0; i < accessors.Length; ++i) + accessors[i] = accessors[i].ToLower(); + + return accessors; + } + } + return _accessorsAll; + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs new file mode 100644 index 0000000000000..5e89376022684 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs @@ -0,0 +1,50 @@ +// 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.Xml.XPath; +using ILLink.Shared; + +namespace Mono.Linker +{ + public static class FeatureSettings + { + public static bool ShouldProcessElement(XPathNavigator nav, LinkContext context, string documentLocation) + { + var feature = GetAttribute(nav, "feature"); + if (string.IsNullOrEmpty(feature)) + return true; + + var value = GetAttribute(nav, "featurevalue"); + if (string.IsNullOrEmpty(value)) + { + context.LogError(null, DiagnosticId.XmlFeatureDoesNotSpecifyFeatureValue, documentLocation, feature); + return false; + } + + if (!bool.TryParse(value, out bool bValue)) + { + context.LogError(null, DiagnosticId.XmlUnsupportedNonBooleanValueForFeature, documentLocation, feature); + return false; + } + + var isDefault = GetAttribute(nav, "featuredefault"); + bool bIsDefault = false; + if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault)) + { + context.LogError(null, DiagnosticId.XmlDocumentLocationHasInvalidFeatureDefault, documentLocation); + return false; + } + + if (!context.FeatureSettings.TryGetValue(feature, out bool featureSetting)) + return bIsDefault; + + return bValue == featureSetting; + } + + public static string GetAttribute(XPathNavigator nav, string attribute) + { + return nav.GetAttribute(attribute, String.Empty); + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs new file mode 100644 index 0000000000000..0acfdda2dccbe --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs @@ -0,0 +1,578 @@ +// 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.XPath; +using ILLink.Shared; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public class LinkAttributesParser : ProcessLinkerXmlBase + { + AttributeInfo? _attributeInfo; + + public LinkAttributesParser(LinkContext context, Stream documentStream, string xmlDocumentLocation) + : base(context, documentStream, xmlDocumentLocation) + { + } + + public LinkAttributesParser(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") + : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation) + { + } + + public void Parse(AttributeInfo xmlInfo) + { + _attributeInfo = xmlInfo; + bool stripLinkAttributes = _context.IsOptimizationEnabled(CodeOptimizations.RemoveLinkAttributes, _resource?.Assembly); + ProcessXml(stripLinkAttributes, _context.IgnoreLinkAttributes); + } + + CustomAttribute[]? ProcessAttributes(XPathNavigator nav, ICustomAttributeProvider provider) + { + var builder = new ArrayBuilder(); + foreach (XPathNavigator argumentNav in nav.SelectChildren("attribute", string.Empty)) + { + if (!ShouldProcessElement(argumentNav)) + continue; + + TypeDefinition? attributeType; + string internalAttribute = GetAttribute(argumentNav, "internal"); + if (!string.IsNullOrEmpty(internalAttribute)) + { + attributeType = GenerateRemoveAttributeInstancesAttribute(); + if (attributeType == null) + continue; + + // TODO: Replace with IsAttributeType check once we have it + if (provider is not TypeDefinition) + { + LogWarning(argumentNav, DiagnosticId.XmlRemoveAttributeInstancesCanOnlyBeUsedOnType, attributeType.Name); + continue; + } + } + else + { + string attributeFullName = GetFullName(argumentNav); + if (string.IsNullOrEmpty(attributeFullName)) + { + LogWarning(argumentNav, DiagnosticId.XmlElementDoesNotContainRequiredAttributeFullname); + continue; + } + + if (!GetAttributeType(argumentNav, attributeFullName, out attributeType)) + continue; + } + + CustomAttribute? customAttribute = CreateCustomAttribute(argumentNav, attributeType); + if (customAttribute != null) + { + _context.LogMessage($"Assigning external custom attribute '{FormatCustomAttribute(customAttribute)}' instance to '{provider}'."); + builder.Add(customAttribute); + } + } + + return builder.ToArray(); + + static string FormatCustomAttribute(CustomAttribute ca) + { + StringBuilder sb = new StringBuilder(); + sb.Append(ca.Constructor.GetDisplayName()); + sb.Append(" { args: "); + for (int i = 0; i < ca.ConstructorArguments.Count; ++i) + { + if (i > 0) + sb.Append(", "); + + var caa = ca.ConstructorArguments[i]; + sb.Append($"{caa.Type.GetDisplayName()} {caa.Value}"); + } + sb.Append(" }"); + + return sb.ToString(); + } + } + + TypeDefinition? GenerateRemoveAttributeInstancesAttribute() + { + if (_context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition != null) + return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition; + + var voidType = BCL.FindPredefinedType("System", "Void", _context); + if (voidType == null) + return null; + + var attributeType = BCL.FindPredefinedType("System", "Attribute", _context); + if (attributeType == null) + return null; + + var objectType = BCL.FindPredefinedType("System", "Object", _context); + if (objectType == null) + return null; + + // + // Generates metadata information for internal type + // + // public sealed class RemoveAttributeInstancesAttribute : Attribute + // { + // public RemoveAttributeInstancesAttribute () {} + // public RemoveAttributeInstancesAttribute (object value1) {} + // } + // + var td = new TypeDefinition("", "RemoveAttributeInstancesAttribute", TypeAttributes.Public); + td.BaseType = attributeType; + + const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Final; + var ctor = new MethodDefinition(".ctor", ctorAttributes, voidType); + td.Methods.Add(ctor); + + ctor = new MethodDefinition(".ctor", ctorAttributes, voidType); + ctor.Parameters.Add(new ParameterDefinition(objectType)); + td.Methods.Add(ctor); + + return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td; + } + + CustomAttribute? CreateCustomAttribute(XPathNavigator nav, TypeDefinition attributeType) + { + CustomAttributeArgument[] arguments = ReadCustomAttributeArguments(nav, attributeType); + + MethodDefinition? constructor = FindBestMatchingConstructor(attributeType, arguments); + if (constructor == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindMatchingConstructorForCustomAttribute, attributeType.GetDisplayName()); + return null; + } + + CustomAttribute customAttribute = new CustomAttribute(constructor); + foreach (var argument in arguments) + customAttribute.ConstructorArguments.Add(argument); + + ReadCustomAttributeProperties(nav, attributeType, customAttribute); + + return customAttribute; + } + + MethodDefinition? FindBestMatchingConstructor(TypeDefinition attributeType, CustomAttributeArgument[] args) + { + var methods = attributeType.Methods; + for (int i = 0; i < attributeType.Methods.Count; ++i) + { + var m = methods[i]; + if (!m.IsInstanceConstructor()) + continue; + + var p = m.Parameters; + if (args.Length != p.Count) + continue; + + bool match = true; + for (int ii = 0; match && ii != args.Length; ++ii) + { + // + // No candidates betterness, only exact matches are supported + // + var parameterType = _context.TryResolve(p[ii].ParameterType); + if (parameterType == null || parameterType != _context.TryResolve(args[ii].Type)) + match = false; + } + + if (match) + return m; + } + + return null; + } + + void ReadCustomAttributeProperties(XPathNavigator nav, TypeDefinition attributeType, CustomAttribute customAttribute) + { + foreach (XPathNavigator propertyNav in nav.SelectChildren("property", string.Empty)) + { + string propertyName = GetName(propertyNav); + if (string.IsNullOrEmpty(propertyName)) + { + LogWarning(propertyNav, DiagnosticId.XmlPropertyDoesNotContainAttributeName); + continue; + } + + PropertyDefinition? property = attributeType.Properties.Where(prop => prop.Name == propertyName).FirstOrDefault(); + if (property == null) + { + LogWarning(propertyNav, DiagnosticId.XmlCouldNotFindProperty, propertyName); + continue; + } + + var caa = ReadCustomAttributeArgument(propertyNav, property); + if (caa is null) + continue; + + customAttribute.Properties.Add(new CustomAttributeNamedArgument(property.Name, caa.Value)); + } + } + + CustomAttributeArgument[] ReadCustomAttributeArguments(XPathNavigator nav, TypeDefinition attributeType) + { + var args = new ArrayBuilder(); + + foreach (XPathNavigator argumentNav in nav.SelectChildren("argument", string.Empty)) + { + CustomAttributeArgument? caa = ReadCustomAttributeArgument(argumentNav, attributeType); + if (caa is not null) + args.Add(caa.Value); + } + + return args.ToArray() ?? Array.Empty(); + } + + CustomAttributeArgument? ReadCustomAttributeArgument(XPathNavigator nav, IMemberDefinition memberWithAttribute) + { + TypeReference? typeref = ResolveArgumentType(nav, memberWithAttribute); + if (typeref is null) + return null; + + string svalue = nav.Value; + + // + // Builds CustomAttributeArgument in the same way as it would be + // represented in the metadata if encoded there. This simplifies + // any custom attributes handling in linker by using same attributes + // value extraction or mathing logic. + // + switch (typeref.MetadataType) + { + case MetadataType.Object: + var argumentIterator = nav.SelectChildren("argument", string.Empty); + if (argumentIterator?.MoveNext() != true) + { + _context.LogError(null, DiagnosticId.CustomAttributeArgumentForTypeRequiresNestedNode, "System.Object", "argument"); + return null; + } + + var typedef = _context.TryResolve(typeref); + if (typedef == null) + return null; + + var boxedValue = ReadCustomAttributeArgument(argumentIterator.Current!, typedef); + if (boxedValue is null) + return null; + + return new CustomAttributeArgument(typeref, boxedValue); + + case MetadataType.Char: + case MetadataType.Byte: + case MetadataType.SByte: + case MetadataType.Int16: + case MetadataType.UInt16: + case MetadataType.Int32: + case MetadataType.UInt32: + case MetadataType.UInt64: + case MetadataType.Int64: + case MetadataType.String: + return new CustomAttributeArgument(typeref, ConvertStringValue(svalue, typeref)); + + case MetadataType.ValueType: + var enumType = _context.Resolve(typeref); + if (enumType?.IsEnum != true) + goto default; + + var enumField = enumType.Fields.Where(f => f.IsStatic && f.Name == svalue).FirstOrDefault(); + object evalue = enumField?.Constant ?? svalue; + + typeref = enumType.GetEnumUnderlyingType(); + return new CustomAttributeArgument(enumType, ConvertStringValue(evalue, typeref)); + + case MetadataType.Class: + if (!typeref.IsTypeOf("System", "Type")) + goto default; + + if (!_context.TypeNameResolver.TryResolveTypeName(svalue, memberWithAttribute, out TypeReference? type, out _)) + { + _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue); + return null; + } + + return new CustomAttributeArgument(typeref, type); + default: + // No support for null and arrays, consider adding - dotnet/linker/issues/1957 + _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.UnexpectedAttributeArgumentType, typeref.GetDisplayName()); + return null; + } + + TypeReference? ResolveArgumentType(XPathNavigator nav, IMemberDefinition memberWithAttribute) + { + string typeName = GetAttribute(nav, "type"); + if (string.IsNullOrEmpty(typeName)) + typeName = "System.String"; + + if (!_context.TypeNameResolver.TryResolveTypeName(typeName, memberWithAttribute, out TypeReference? typeref, out _)) + { + _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value); + return null; + } + + return typeref; + } + } + + object? ConvertStringValue(object value, TypeReference targetType) + { + TypeCode typeCode; + switch (targetType.MetadataType) + { + case MetadataType.String: + typeCode = TypeCode.String; + break; + case MetadataType.Char: + typeCode = TypeCode.Char; + break; + case MetadataType.Byte: + typeCode = TypeCode.Byte; + break; + case MetadataType.SByte: + typeCode = TypeCode.SByte; + break; + case MetadataType.Int16: + typeCode = TypeCode.Int16; + break; + case MetadataType.UInt16: + typeCode = TypeCode.UInt16; + break; + case MetadataType.Int32: + typeCode = TypeCode.Int32; + break; + case MetadataType.UInt32: + typeCode = TypeCode.UInt32; + break; + case MetadataType.UInt64: + typeCode = TypeCode.UInt64; + break; + case MetadataType.Int64: + typeCode = TypeCode.Int64; + break; + case MetadataType.Boolean: + typeCode = TypeCode.Boolean; + break; + case MetadataType.Single: + typeCode = TypeCode.Single; + break; + case MetadataType.Double: + typeCode = TypeCode.Double; + break; + default: + throw new NotSupportedException(targetType.ToString()); + } + + try + { + return Convert.ChangeType(value, typeCode); + } + catch + { + _context.LogError(null, DiagnosticId.CannotConverValueToType, value.ToString() ?? "", targetType.GetDisplayName()); + return null; + } + } + + bool GetAttributeType(XPathNavigator nav, string attributeFullName, [NotNullWhen(true)] out TypeDefinition? attributeType) + { + string assemblyName = GetAttribute(nav, "assembly"); + if (string.IsNullOrEmpty(assemblyName)) + { + attributeType = _context.GetType(attributeFullName); + } + else + { + AssemblyDefinition? assembly; + try + { + assembly = _context.TryResolve(AssemblyNameReference.Parse(assemblyName)); + if (assembly == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotResolveAssemblyForAttribute, assemblyName, attributeFullName); + + attributeType = default; + return false; + } + } + catch (Exception) + { + LogWarning(nav, DiagnosticId.XmlCouldNotResolveAssemblyForAttribute, assemblyName, attributeFullName); + attributeType = default; + return false; + } + + attributeType = _context.TryResolve(assembly, attributeFullName); + } + + if (attributeType == null) + { + LogWarning(nav, DiagnosticId.XmlAttributeTypeCouldNotBeFound, attributeFullName); + return false; + } + + return true; + } + + protected override AllowedAssemblies AllowedAssemblySelector + { + get + { + if (_resource?.Assembly == null) + return AllowedAssemblies.AllAssemblies; + + // Corelib XML may contain assembly wildcard to support compiler-injected attribute types + if (_resource?.Assembly.Name.Name == PlatformAssemblies.CoreLib) + return AllowedAssemblies.AllAssemblies; + + return AllowedAssemblies.ContainingAssembly; + } + } + + protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) + { + PopulateAttributeInfo(assembly, nav); + ProcessTypes(assembly, nav, warnOnUnresolvedTypes); + } + + protected override void ProcessType(TypeDefinition type, XPathNavigator nav) + { + Debug.Assert(ShouldProcessElement(nav)); + + PopulateAttributeInfo(type, nav); + ProcessTypeChildren(type, nav); + + if (!type.HasNestedTypes) + return; + + foreach (XPathNavigator nestedTypeNav in nav.SelectChildren("type", string.Empty)) + { + foreach (TypeDefinition nested in type.NestedTypes) + { + if (nested.Name == GetAttribute(nestedTypeNav, "name") && ShouldProcessElement(nestedTypeNav)) + ProcessType(nested, nestedTypeNav); + } + } + } + + protected override void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav) + { + PopulateAttributeInfo(field, nav); + } + + protected override void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) + { + PopulateAttributeInfo(method, nav); + ProcessReturnParameters(method, nav); + ProcessParameters(method, nav); + } + + void ProcessParameters(MethodDefinition method, XPathNavigator nav) + { + Debug.Assert(_attributeInfo != null); + foreach (XPathNavigator parameterNav in nav.SelectChildren("parameter", string.Empty)) + { + var attributes = ProcessAttributes(parameterNav, method); + if (attributes != null) + { + string paramName = GetAttribute(parameterNav, "name"); + foreach (ParameterDefinition parameter in method.Parameters) + { + if (paramName == parameter.Name) + { + if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey(parameter)) + LogWarning(parameterNav, DiagnosticId.XmlMoreThanOneValyForParameterOfMethod, paramName, method.GetDisplayName()); + _attributeInfo.AddCustomAttributes(parameter, attributes); + break; + } + } + } + } + } + + void ProcessReturnParameters(MethodDefinition method, XPathNavigator nav) + { + bool firstAppearance = true; + foreach (XPathNavigator returnNav in nav.SelectChildren("return", string.Empty)) + { + if (firstAppearance) + { + firstAppearance = false; + PopulateAttributeInfo(method.MethodReturnType, returnNav); + } + else + { + LogWarning(returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName()); + } + } + } + + protected override MethodDefinition? GetMethod(TypeDefinition type, string signature) + { + if (type.HasMethods) + foreach (MethodDefinition method in type.Methods) + if (signature.Replace(" ", "") == GetMethodSignature(method) || signature.Replace(" ", "") == GetMethodSignature(method, true)) + return method; + + return null; + } + + static string GetMethodSignature(MethodDefinition method, bool includeReturnType = false) + { + StringBuilder sb = new StringBuilder(); + if (includeReturnType) + { + sb.Append(method.ReturnType.FullName); + } + sb.Append(method.Name); + if (method.HasGenericParameters) + { + sb.Append("<"); + for (int i = 0; i < method.GenericParameters.Count; i++) + { + if (i > 0) + sb.Append(","); + + sb.Append(method.GenericParameters[i].Name); + } + sb.Append(">"); + } + sb.Append("("); + if (method.HasParameters) + { + for (int i = 0; i < method.Parameters.Count; i++) + { + if (i > 0) + sb.Append(","); + + sb.Append(method.Parameters[i].ParameterType.FullName); + } + } + sb.Append(")"); + return sb.ToString(); + } + + protected override void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) + { + PopulateAttributeInfo(property, nav); + } + + protected override void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) + { + PopulateAttributeInfo(@event, nav); + } + + void PopulateAttributeInfo(ICustomAttributeProvider provider, XPathNavigator nav) + { + Debug.Assert(_attributeInfo != null); + var attributes = ProcessAttributes(nav, provider); + if (attributes != null) + _attributeInfo.AddCustomAttributes(provider, attributes); + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs new file mode 100644 index 0000000000000..842c56639fdd0 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs @@ -0,0 +1,662 @@ +// 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; +using ILLink.Shared; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + [Flags] + public enum AllowedAssemblies + { + ContainingAssembly = 0x1, + AnyAssembly = 0x2 | ContainingAssembly, + AllAssemblies = 0x4 | AnyAssembly + } + + public abstract class ProcessLinkerXmlBase + { + const string FullNameAttributeName = "fullname"; + const string LinkerElementName = "linker"; + const string TypeElementName = "type"; + const string SignatureAttributeName = "signature"; + const string NameAttributeName = "name"; + const string FieldElementName = "field"; + const string MethodElementName = "method"; + const string EventElementName = "event"; + const string PropertyElementName = "property"; + const string AllAssembliesFullName = "*"; + protected const string XmlNamespace = ""; + + protected readonly string _xmlDocumentLocation; + readonly XPathNavigator _document; + protected readonly (EmbeddedResource Resource, AssemblyDefinition Assembly)? _resource; + protected readonly LinkContext _context; + + protected ProcessLinkerXmlBase(LinkContext context, Stream documentStream, string xmlDocumentLocation) + { + _context = context; + using (documentStream) + { + _document = XDocument.Load(documentStream, LoadOptions.SetLineInfo).CreateNavigator(); + } + _xmlDocumentLocation = xmlDocumentLocation; + } + + protected ProcessLinkerXmlBase(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation) + : this(context, documentStream, xmlDocumentLocation) + { + _resource = ( + resource ?? throw new ArgumentNullException(nameof(resource)), + resourceAssembly ?? throw new ArgumentNullException(nameof(resourceAssembly)) + ); + } + + protected virtual bool ShouldProcessElement(XPathNavigator nav) => FeatureSettings.ShouldProcessElement(nav, _context, _xmlDocumentLocation); + + protected virtual void ProcessXml(bool stripResource, bool ignoreResource) + { + if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly) && _resource == null) + throw new InvalidOperationException("The containing assembly must be specified for XML which is restricted to modifying that assembly only."); + + try + { + XPathNavigator nav = _document.CreateNavigator(); + + // Initial structure check - ignore XML document which don't look like linker XML format + if (!nav.MoveToChild(LinkerElementName, XmlNamespace)) + return; + + if (_resource != null) + { + if (stripResource) + _context.Annotations.AddResourceToRemove(_resource.Value.Assembly, _resource.Value.Resource); + if (ignoreResource) + return; + } + + if (!ShouldProcessElement(nav)) + return; + + ProcessAssemblies(nav); + + // For embedded XML, allow not specifying the assembly explicitly in XML. + if (_resource != null) + ProcessAssembly(_resource.Value.Assembly, nav, warnOnUnresolvedTypes: true); + + } + catch (Exception ex) when (!(ex is LinkerFatalErrorException)) + { + throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.ErrorProcessingXmlLocation, _xmlDocumentLocation), ex); + } + } + + protected virtual AllowedAssemblies AllowedAssemblySelector { get => _resource != null ? AllowedAssemblies.ContainingAssembly : AllowedAssemblies.AnyAssembly; } + + bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyNameReference? assemblyName) + { + assemblyName = null; + if (GetFullName(nav) == AllAssembliesFullName) + return true; + + assemblyName = GetAssemblyName(nav); + return false; + } + + protected virtual void ProcessAssemblies(XPathNavigator nav) + { + foreach (XPathNavigator assemblyNav in nav.SelectChildren("assembly", "")) + { + // Errors for invalid assembly names should show up even if this element will be + // skipped due to feature conditions. + bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyNameReference? name); + if (processAllAssemblies && AllowedAssemblySelector != AllowedAssemblies.AllAssemblies) + { + LogWarning(assemblyNav, DiagnosticId.XmlUnsuportedWildcard); + continue; + } + + AssemblyDefinition? assemblyToProcess = null; + if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly)) + { + Debug.Assert(!processAllAssemblies); + Debug.Assert(_resource != null); + if (_resource.Value.Assembly.Name.Name != name!.Name) + { + LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _resource.Value.Assembly.Name.Name, name.ToString()); + continue; + } + assemblyToProcess = _resource.Value.Assembly; + } + + if (!ShouldProcessElement(assemblyNav)) + continue; + + if (processAllAssemblies) + { + // We could avoid loading all references in this case: https://github.com/dotnet/linker/issues/1708 + foreach (AssemblyDefinition assembly in _context.GetReferencedAssemblies()) + ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: false); + } + else + { + Debug.Assert(!processAllAssemblies); + AssemblyDefinition? assembly = assemblyToProcess ?? _context.TryResolve(name!); + + if (assembly == null) + { + LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name); + continue; + } + + ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: true); + } + } + } + + protected abstract void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes); + + protected virtual void ProcessTypes(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) + { + foreach (XPathNavigator typeNav in nav.SelectChildren(TypeElementName, XmlNamespace)) + { + + if (!ShouldProcessElement(typeNav)) + continue; + + string fullname = GetFullName(typeNav); + + if (fullname.IndexOf("*") != -1) + { + if (ProcessTypePattern(fullname, assembly, typeNav)) + continue; + } + + TypeDefinition type = assembly.MainModule.GetType(fullname); + + if (type == null && assembly.MainModule.HasExportedTypes) + { + foreach (var exported in assembly.MainModule.ExportedTypes) + { + if (fullname == exported.FullName) + { + var resolvedExternal = ProcessExportedType(exported, assembly, typeNav); + if (resolvedExternal != null) + { + type = resolvedExternal; + break; + } + } + } + } + + if (type == null) + { + if (warnOnUnresolvedTypes) + LogWarning(typeNav, DiagnosticId.XmlCouldNotResolveType, fullname); + continue; + } + + ProcessType(type, typeNav); + } + } + + protected virtual TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => exported.Resolve(); + + void MatchType(TypeDefinition type, Regex regex, XPathNavigator nav) + { + if (regex.Match(type.FullName).Success) + ProcessType(type, nav); + + if (!type.HasNestedTypes) + return; + + foreach (var nt in type.NestedTypes) + MatchType(nt, regex, nav); + } + + protected virtual bool ProcessTypePattern(string fullname, AssemblyDefinition assembly, XPathNavigator nav) + { + Regex regex = new Regex(fullname.Replace(".", @"\.").Replace("*", "(.*)")); + + foreach (TypeDefinition type in assembly.MainModule.Types) + { + MatchType(type, regex, nav); + } + + if (assembly.MainModule.HasExportedTypes) + { + foreach (var exported in assembly.MainModule.ExportedTypes) + { + if (regex.Match(exported.FullName).Success) + { + var type = ProcessExportedType(exported, assembly, nav); + if (type != null) + { + ProcessType(type, nav); + } + } + } + } + + return true; + } + + protected abstract void ProcessType(TypeDefinition type, XPathNavigator nav); + + protected void ProcessTypeChildren(TypeDefinition type, XPathNavigator nav, object? customData = null) + { + if (nav.HasChildren) + { + ProcessSelectedFields(nav, type); + ProcessSelectedMethods(nav, type, customData); + ProcessSelectedEvents(nav, type, customData); + ProcessSelectedProperties(nav, type, customData); + } + } + + void ProcessSelectedFields(XPathNavigator nav, TypeDefinition type) + { + foreach (XPathNavigator fieldNav in nav.SelectChildren(FieldElementName, XmlNamespace)) + { + if (!ShouldProcessElement(fieldNav)) + continue; + ProcessField(type, fieldNav); + } + } + + protected virtual void ProcessField(TypeDefinition type, XPathNavigator nav) + { + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) + { + FieldDefinition? field = GetField(type, signature); + if (field == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, signature, type.GetDisplayName()); + return; + } + + ProcessField(type, field, nav); + } + + string name = GetName(nav); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + if (type.HasFields) + { + foreach (FieldDefinition field in type.Fields) + { + if (field.Name == name) + { + foundMatch = true; + ProcessField(type, field, nav); + } + } + } + + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName()); + } + } + } + + protected static FieldDefinition? GetField(TypeDefinition type, string signature) + { + if (!type.HasFields) + return null; + + foreach (FieldDefinition field in type.Fields) + if (signature == field.FieldType.FullName + " " + field.Name) + return field; + + return null; + } + + protected virtual void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav) { } + + void ProcessSelectedMethods(XPathNavigator nav, TypeDefinition type, object? customData) + { + foreach (XPathNavigator methodNav in nav.SelectChildren(MethodElementName, XmlNamespace)) + { + if (!ShouldProcessElement(methodNav)) + continue; + ProcessMethod(type, methodNav, customData); + } + } + + protected virtual void ProcessMethod(TypeDefinition type, XPathNavigator nav, object? customData) + { + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) + { + MethodDefinition? method = GetMethod(type, signature); + if (method == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName()); + return; + } + + ProcessMethod(type, method, nav, customData); + } + + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + if (type.HasMethods) + { + foreach (MethodDefinition method in type.Methods) + { + if (name == method.Name) + { + foundMatch = true; + ProcessMethod(type, method, nav, customData); + } + } + } + + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, name, type.GetDisplayName()); + } + } + } + + protected virtual MethodDefinition? GetMethod(TypeDefinition type, string signature) => null; + + protected virtual void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) { } + + void ProcessSelectedEvents(XPathNavigator nav, TypeDefinition type, object? customData) + { + foreach (XPathNavigator eventNav in nav.SelectChildren(EventElementName, XmlNamespace)) + { + if (!ShouldProcessElement(eventNav)) + continue; + ProcessEvent(type, eventNav, customData); + } + } + + protected virtual void ProcessEvent(TypeDefinition type, XPathNavigator nav, object? customData) + { + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) + { + EventDefinition? @event = GetEvent(type, signature); + if (@event == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, signature, type.GetDisplayName()); + return; + } + + ProcessEvent(type, @event, nav, customData); + } + + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + foreach (EventDefinition @event in type.Events) + { + if (@event.Name == name) + { + foundMatch = true; + ProcessEvent(type, @event, nav, customData); + } + } + + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, name, type.GetDisplayName()); + } + } + } + + protected static EventDefinition? GetEvent(TypeDefinition type, string signature) + { + if (!type.HasEvents) + return null; + + foreach (EventDefinition @event in type.Events) + if (signature == @event.EventType.FullName + " " + @event.Name) + return @event; + + return null; + } + + protected virtual void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { } + + void ProcessSelectedProperties(XPathNavigator nav, TypeDefinition type, object? customData) + { + foreach (XPathNavigator propertyNav in nav.SelectChildren(PropertyElementName, XmlNamespace)) + { + if (!ShouldProcessElement(propertyNav)) + continue; + ProcessProperty(type, propertyNav, customData); + } + } + + protected virtual void ProcessProperty(TypeDefinition type, XPathNavigator nav, object? customData) + { + string signature = GetSignature(nav); + if (!String.IsNullOrEmpty(signature)) + { + PropertyDefinition? property = GetProperty(type, signature); + if (property == null) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, signature, type.GetDisplayName()); + return; + } + + ProcessProperty(type, property, nav, customData, true); + } + + string name = GetAttribute(nav, NameAttributeName); + if (!String.IsNullOrEmpty(name)) + { + bool foundMatch = false; + foreach (PropertyDefinition property in type.Properties) + { + if (property.Name == name) + { + foundMatch = true; + ProcessProperty(type, property, nav, customData, false); + } + } + + if (!foundMatch) + { + LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, name, type.GetDisplayName()); + } + } + } + + protected static PropertyDefinition? GetProperty(TypeDefinition type, string signature) + { + if (!type.HasProperties) + return null; + + foreach (PropertyDefinition property in type.Properties) + if (signature == property.PropertyType.FullName + " " + property.Name) + return property; + + return null; + } + + protected virtual void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) { } + + protected virtual AssemblyNameReference GetAssemblyName(XPathNavigator nav) + { + return AssemblyNameReference.Parse(GetFullName(nav)); + } + + protected static string GetFullName(XPathNavigator nav) + { + return GetAttribute(nav, FullNameAttributeName); + } + + protected static string GetName(XPathNavigator nav) + { + return GetAttribute(nav, NameAttributeName); + } + + protected static string GetSignature(XPathNavigator nav) + { + return GetAttribute(nav, SignatureAttributeName); + } + + protected static string GetAttribute(XPathNavigator nav, string attribute) + { + return nav.GetAttribute(attribute, XmlNamespace); + } + + protected MessageOrigin GetMessageOriginForPosition(XPathNavigator position) + { + return (position is IXmlLineInfo lineInfo) + ? new MessageOrigin(_xmlDocumentLocation, lineInfo.LineNumber, lineInfo.LinePosition, _resource?.Assembly) + : new MessageOrigin(_xmlDocumentLocation, 0, 0, _resource?.Assembly); + } + protected void LogWarning(string message, int warningCode, XPathNavigator position) + { + _context.LogWarning(message, warningCode, GetMessageOriginForPosition(position)); + } + + protected void LogWarning(XPathNavigator position, DiagnosticId id, params string[] args) + { + _context.LogWarning(GetMessageOriginForPosition(position), id, args); + } + + public override string ToString() => GetType().Name + ": " + _xmlDocumentLocation; + + public bool TryConvertValue(string value, TypeReference target, out object? result) + { + switch (target.MetadataType) + { + case MetadataType.Boolean: + if (bool.TryParse(value, out bool bvalue)) + { + result = bvalue ? 1 : 0; + return true; + } + + goto case MetadataType.Int32; + + case MetadataType.Byte: + if (!byte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out byte byteresult)) + break; + + result = (int)byteresult; + return true; + + case MetadataType.SByte: + if (!sbyte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out sbyte sbyteresult)) + break; + + result = (int)sbyteresult; + return true; + + case MetadataType.Int16: + if (!short.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out short shortresult)) + break; + + result = (int)shortresult; + return true; + + case MetadataType.UInt16: + if (!ushort.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort ushortresult)) + break; + + result = (int)ushortresult; + return true; + + case MetadataType.Int32: + if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult)) + break; + + result = iresult; + return true; + + case MetadataType.UInt32: + if (!uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint uresult)) + break; + + result = (int)uresult; + return true; + + case MetadataType.Double: + if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out double dresult)) + break; + + result = dresult; + return true; + + case MetadataType.Single: + if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fresult)) + break; + + result = fresult; + return true; + + case MetadataType.Int64: + if (!long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long lresult)) + break; + + result = lresult; + return true; + + case MetadataType.UInt64: + if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong ulresult)) + break; + + result = (long)ulresult; + return true; + + case MetadataType.Char: + if (!char.TryParse(value, out char chresult)) + break; + + result = (int)chresult; + return true; + + case MetadataType.String: + if (value is string || value == null) + { + result = value; + return true; + } + + break; + + case MetadataType.ValueType: + if (value is string && + _context.TryResolve(target) is TypeDefinition typeDefinition && + typeDefinition.IsEnum) + { + var enumField = typeDefinition.Fields.Where(f => f.IsStatic && f.Name == value).FirstOrDefault(); + if (enumField != null) + { + result = Convert.ToInt32(enumField.Constant); + return true; + } + } + + break; + } + + result = null; + return false; + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md new file mode 100644 index 0000000000000..a75e53a1f949a --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md @@ -0,0 +1 @@ +Sources taken from https://github.com/dotnet/linker/tree/c4abaf33f967a8fa42eb20fc386b774ad74ef319/src/linker/Linker.Steps. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs index a1e931e172539..430c77f98f905 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs @@ -30,7 +30,7 @@ public UsageBasedInteropStubManager(InteropStateManager interopStateManager, PIn public override void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { - if (method.IsPInvoke) + if (method.IsPInvoke && method.OwningType is MetadataType type && MarshalHelpers.IsRuntimeMarshallingEnabled(type.Module)) { dependencies = dependencies ?? new DependencyList(); @@ -61,12 +61,19 @@ private void AddParameterMarshallingDependencies(ref DependencyList dependencies if ((type.IsWellKnownType(WellKnownType.MulticastDelegate) || type == context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType)) { - var message = new DiagnosticString(DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(method)); - _logger.LogWarning( - message, - (int)DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, - method, - MessageSubCategory.AotAnalysis); + // If we hit this p/invoke as part of delegate marshalling (i.e. this is a delegate + // that has another delegate in the signature), blame the delegate type, not the marshalling thunk. + // This should ideally warn from the use site (e.g. where GetDelegateForFunctionPointer + // is called) but it's currently hard to get a warning from those spots and this guarantees + // we won't miss a spot (e.g. a p/invoke that has a delegate and that delegate contains + // a System.Delegate parameter). + MethodDesc reportedMethod = method; + if (reportedMethod is Internal.IL.Stubs.DelegateMarshallingMethodThunk delegateThunkMethod) + { + reportedMethod = delegateThunkMethod.InvokeMethod; + } + + _logger.LogWarning(reportedMethod, DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, DiagnosticUtilities.GetMethodSignatureDisplayName(method)); } // struct may contain delegate fields, hence we need to add dependencies for it diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index bd649904129bf..46702412ba73a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -15,6 +15,7 @@ using ILCompiler.Metadata; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; +using ILLink.Shared; using FlowAnnotations = ILCompiler.Dataflow.FlowAnnotations; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; @@ -682,16 +683,12 @@ public override void NoteOverridingMethod(MethodDesc baseMethod, MethodDesc over if (baseMethodRequiresUnreferencedCode != overridingMethodRequiresUnreferencedCode) { - Logger.LogWarning( - $"Presence of 'RequiresUnreferencedCodeAttribute' on method '{overridingMethod.GetDisplayName()}' doesn't match overridden method '{baseMethod.GetDisplayName()}'. " + - $"All overridden methods must have 'RequiresUnreferencedCodeAttribute'.", 2046, overridingMethod, MessageSubCategory.TrimAnalysis); + Logger.LogWarning(overridingMethod, DiagnosticId.RequiresUnreferencedCodeAttributeMismatch, overridingMethod.GetDisplayName(), baseMethod.GetDisplayName()); } if (baseMethodRequiresDynamicCode != overridingMethodRequiresDynamicCode) { - Logger.LogWarning( - $"Presence of 'RequiresDynamicCodeAttribute' on method '{overridingMethod.GetDisplayName()}' doesn't match overridden method '{baseMethod.GetDisplayName()}'. " + - $"All overridden methods must have 'RequiresDynamicCodeAttribute'.", 2046, overridingMethod, MessageSubCategory.AotAnalysis); + Logger.LogWarning(overridingMethod, DiagnosticId.RequiresDynamicCodeAttributeMismatch, overridingMethod.GetDisplayName(), baseMethod.GetDisplayName()); } if (baseMethodRequiresDataflow || overridingMethodRequiresDataflow) @@ -973,7 +970,7 @@ public AssemblyFeatureInfo(EcmaModule module, IReadOnlyDictionary } } - private class LinkAttributesReader : ProcessLinkerXmlBase + private class LinkAttributesReader : ProcessXmlBase { private readonly HashSet _removedAttributes; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs index 830fb11d1ef21..93fb4cc376c07 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs @@ -30,9 +30,9 @@ public override MethodIL GetMethodIL(MethodDesc method) return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager); } - public MethodDesc GetCalliStub(MethodSignature signature) + public MethodDesc GetCalliStub(MethodSignature signature, ModuleDesc moduleContext) { - return _interopStateManager.GetPInvokeCalliStub(signature); + return _interopStateManager.GetPInvokeCalliStub(signature, moduleContext); } public string GetDirectCallExternName(MethodDesc method) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 3420564b0715e..d2df0a825ca40 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -373,6 +373,7 @@ + @@ -527,6 +528,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj index 97c97bb7de720..0d1b23ad73b3c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj @@ -15,6 +15,7 @@ binaries are up to date and which are stale. --> false Debug;Release;Checked + true diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs new file mode 100644 index 0000000000000..d9972da41f76c --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs @@ -0,0 +1,32 @@ + +using System; +using System.Collections; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Microsoft.DiaSymReader +{ + internal unsafe sealed class ILCompilerComWrappers : ComWrappers + { + protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + // passing the managed object to COM is not currently supported + throw new NotImplementedException(); + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flags) + { + // Assert use of the UniqueInstance flag since the returned Native Object Wrapper always + // supports IDisposable and its Dispose will always release and suppress finalization. + // If the wrapper doesn't always support IDisposable the assert can be relaxed. + Debug.Assert(flags.HasFlag(CreateObjectFlags.UniqueInstance)); + + // Throw an exception if the type is not supported by the implementation. + // Null can be returned as well, but an ArgumentNullException will be thrown for + // the consumer of this ComWrappers instance. + return SymNgenWriterWrapper.CreateIfSupported(externalComObject) ?? throw new NotSupportedException(); + } + + protected override void ReleaseObjects(IEnumerable objects) => throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs index 4c4b6b97d60a9..40702fd187a75 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#pragma warning disable 436 // SuppressUnmanagedCodeSecurityAttribute defined in source and mscorlib +#pragma warning disable 436 // SuppressUnmanagedCodeSecurityAttribute defined in source and mscorlib using System; using System.Collections.Generic; @@ -11,9 +11,39 @@ namespace Microsoft.DiaSymReader { - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D682FD12-43dE-411C-811B-BE8404CEA126"), SuppressUnmanagedCodeSecurity] + /// + /// IUnknown COM type for writing NGen PDBs + /// + /// + /// + /// [ + /// object, + /// uuid(d682fd12-43de-411c-811b-be8404cea126), + /// pointer_default(unique) + /// ] + /// interface ISymNGenWriter : IUnknown + /// { + /// /* + /// * Add a new public symbol to the NGEN PDB. + /// */ + /// HRESULT AddSymbol([in] BSTR pSymbol, + /// [in] USHORT iSection, + /// [in] ULONGLONG rva); + /// + /// /* + /// * Adds a new section to the NGEN PDB. + /// */ + /// HRESULT AddSection([in] USHORT iSection, + /// [in] USHORT flags, + /// [in] long offset, + /// [in] long cb); + /// }; + /// + /// internal interface ISymNGenWriter { + public static readonly Guid IID = new Guid("D682FD12-43dE-411C-811B-BE8404CEA126"); + // Add a new public symbol to the NGEN PDB. void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, ushort iSection, @@ -46,9 +76,46 @@ internal enum OMF : ushort } - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4"), SuppressUnmanagedCodeSecurity] + /// + /// IUnknown COM type for writing NGen PDBs + /// + /// + /// + /// [ + /// object, + /// local, + /// uuid(B029E51B-4C55-4fe2-B993-9F7BC1F10DB4), + /// pointer_default(unique) + /// ] + /// interface ISymNGenWriter2 : ISymNGenWriter + /// { + /// HRESULT OpenModW([in] const wchar_t* wszModule, + /// [in] const wchar_t* wszObjFile, + /// [out] BYTE** ppmod); + /// + /// HRESULT CloseMod([in] BYTE* pmod); + /// + /// HRESULT ModAddSymbols([in] BYTE* pmod, [in] BYTE* pbSym, [in] long cb); + /// + /// HRESULT ModAddSecContribEx( + /// [in] BYTE* pmod, + /// [in] USHORT isect, + /// [in] long off, + /// [in] long cb, + /// [in] ULONG dwCharacteristics, + /// [in] DWORD dwDataCrc, + /// [in] DWORD dwRelocCrc); + /// + /// HRESULT QueryPDBNameExW( + /// [out, size_is(cchMax)] wchar_t wszPDB[], + /// [in] SIZE_T cchMax); + /// }; + /// + /// internal interface ISymNGenWriter2 : ISymNGenWriter { + public readonly static new Guid IID = new Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4"); + // Add a new public symbol to the NGEN PDB. new void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, ushort iSection, @@ -78,7 +145,7 @@ void ModAddSecContribEx( uint dwRelocCrc); void QueryPDBNameExW( - [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pdb, + [MarshalAs(UnmanagedType.LPWStr)] char[] pdb, IntPtr cchMax); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index a16d5bf19a8e6..be0d8af909f72 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -89,7 +89,7 @@ public class PdbWriter Dictionary _documentToChecksumOffsetMapping; UIntPtr _pdbMod; - ISymNGenWriter2 _ngenWriter; + SymNgenWriterWrapper _ngenWriter; static PdbWriter() { @@ -116,7 +116,7 @@ private static IntPtr DllImportResolver(string libraryName, Assembly assembly, D private extern static void CreateNGenPdbWriter( [MarshalAs(UnmanagedType.LPWStr)] string ngenImagePath, [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, - [MarshalAs(UnmanagedType.Interface)] out ISymNGenWriter2 ngenPdbWriter); + out IntPtr ngenPdbWriterPtr); public PdbWriter(string pdbPath, PDBExtraData pdbExtraData, TargetDetails target) { @@ -138,23 +138,14 @@ public void WritePDBData(string dllPath, IEnumerable methods) { try { - try - { - WritePDBDataHelper(dllPath, methods); - } - finally - { - if ((_ngenWriter != null) && (_pdbMod != UIntPtr.Zero)) - { - _ngenWriter.CloseMod(_pdbMod); - } - } + WritePDBDataHelper(dllPath, methods); } finally { - if (_ngenWriter != null) + if ((_ngenWriter != null) && (_pdbMod != UIntPtr.Zero)) { - Marshal.FinalReleaseComObject(_ngenWriter); + _ngenWriter.CloseMod(_pdbMod); + _ngenWriter?.Dispose(); } } @@ -217,14 +208,16 @@ private void WritePDBDataHelper(string dllPath, IEnumerable methods) // Delete any preexisting PDB file upfront, otherwise CreateNGenPdbWriter silently opens it File.Delete(_pdbFilePath); - CreateNGenPdbWriter(dllPath, _pdbFilePath, out _ngenWriter); + var comWrapper = new ILCompilerComWrappers(); + CreateNGenPdbWriter(dllPath, _pdbFilePath, out var pdbWriterInst); + _ngenWriter = (SymNgenWriterWrapper)comWrapper.GetOrCreateObjectForComInstance(pdbWriterInst, CreateObjectFlags.UniqueInstance); { // PDB file is now created. Get its path and update _pdbFilePath so the PDB file // can be deleted if we don't make it successfully to the end. - StringBuilder pdbFilePathBuilder = new StringBuilder(); - pdbFilePathBuilder.Capacity = 1024; - _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(pdbFilePathBuilder.Capacity)); + const int capacity = 1024; + var pdbFilePathBuilder = new char[capacity]; + _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(capacity - 1) /* remove 1 byte for null */); _pdbFilePath = pdbFilePathBuilder.ToString(); } @@ -428,9 +421,9 @@ private void WriteCompilerVersion() byte iLanguage = (byte)CV_CFL_LANG.CV_CFL_MSIL; writer.Write(iLanguage); // Write rest of flags - writer.Write((byte)0); - writer.Write((byte)0); - writer.Write((byte)0); + writer.Write((byte)0); + writer.Write((byte)0); + writer.Write((byte)0); switch (_target.Architecture) { diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs new file mode 100644 index 0000000000000..8a1166f43a39b --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs @@ -0,0 +1,149 @@ + +using System; +using System.Runtime.InteropServices; +using System.Text; + +#nullable enable + +namespace Microsoft.DiaSymReader +{ + internal class SymNgenWriterWrapper : ISymNGenWriter2, IDisposable + { + private bool _isDisposed = false; + public IntPtr ISymNGenWriter2Inst { get; } + + private SymNgenWriterWrapper(IntPtr writer2Inst) + { + ISymNGenWriter2Inst = writer2Inst; + } + + public static SymNgenWriterWrapper? CreateIfSupported(IntPtr ptr) + { + var iid = ISymNGenWriter2.IID; + int hr = Marshal.QueryInterface(ptr, ref iid, out IntPtr ngenWriterInst); + if (hr != 0) + { + return null; + } + + return new SymNgenWriterWrapper(ngenWriterInst); + } + + ~SymNgenWriterWrapper() + { + DisposeInternal(); + } + + public void Dispose() + { + DisposeInternal(); + GC.SuppressFinalize(this); + } + + private void DisposeInternal() + { + if (_isDisposed) + { + return; + } + Marshal.Release(ISymNGenWriter2Inst); + _isDisposed = true; + } + + public unsafe void AddSymbol(string pSymbol, ushort iSection, ulong rva) + { + IntPtr strLocal = Marshal.StringToBSTR(pSymbol); + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 3 /* ISymNGenWriter2.AddSymbol slot */)); + int hr = func(inst, strLocal, iSection, rva); + Marshal.FreeBSTR(strLocal); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void AddSection(ushort iSection, OMF flags, int offset, int cb) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 4)); + int hr = func(inst, iSection, flags, offset, cb); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void OpenModW(string wszModule, string wszObjFile, out UIntPtr ppmod) + { + var inst = ISymNGenWriter2Inst; + fixed (char* wszModulePtr = wszModule) + fixed (char* wszObjFilePtr = wszObjFile) + { + UIntPtr ppmodPtr; + var func = (delegate* unmanaged)(*(*(void***)inst + 5)); + int hr = func(inst, wszModulePtr, wszObjFilePtr, &ppmodPtr); + ppmod = ppmodPtr; + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + public unsafe void CloseMod(UIntPtr pmod) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 6)); + int hr = func(inst, pmod); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void ModAddSymbols(UIntPtr pmod, byte[] pbSym, int cb) + { + fixed (byte* pbSymPtr = pbSym) + { + var pbSymLocal = (IntPtr)pbSymPtr; + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 7)); + int hr = func(inst, pmod, pbSymLocal, cb); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + public unsafe void ModAddSecContribEx(UIntPtr pmod, ushort isect, int off, int cb, uint dwCharacteristics, uint dwDataCrc, uint dwRelocCrc) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 8)); + int hr = func(inst, pmod, isect, off, cb, dwCharacteristics, dwDataCrc, dwRelocCrc); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void QueryPDBNameExW(char[] pdb, IntPtr cchMax) + { + fixed (char* pdbPtr = pdb) + { + var pdbLocal = (IntPtr)pdbPtr; + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 9)); + int hr = func(inst, pdbPtr, cchMax); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + void ISymNGenWriter.AddSymbol(string pSymbol, ushort iSection, ulong rva) => AddSymbol(pSymbol, iSection, rva); + void ISymNGenWriter.AddSection(ushort iSection, OMF flags, int offset, int cb) => AddSection(iSection, flags, offset, cb); + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs index e8596cf24c894..a8ff518ac7591 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs @@ -46,15 +46,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); - builder.RequireInitialPointerAlignment(); + byte[] rvaData = GetRvaData(factory.Target.PointerSize, out int requiredAlignment); + builder.RequireInitialAlignment(requiredAlignment); builder.AddSymbol(this); - builder.EmitBytes(GetRvaData(factory.Target.PointerSize)); + builder.EmitBytes(rvaData); return builder.ToObjectData(); } - private unsafe byte[] GetRvaData(int targetPointerSize) + private unsafe byte[] GetRvaData(int targetPointerSize, out int requiredAlignment) { int size = 0; + requiredAlignment = targetPointerSize; MetadataReader metadataReader = _module.MetadataReader; BlobReader metadataBlob = new BlobReader(_module.PEReader.GetMetadata().Pointer, _module.PEReader.GetMetadata().Length); @@ -80,6 +82,7 @@ private unsafe byte[] GetRvaData(int targetPointerSize) Debug.Assert(field.HasRva); int currentSize = field.FieldType.GetElementSize().AsInt; + requiredAlignment = Math.Max(requiredAlignment, (field.FieldType as MetadataType)?.GetClassLayout().PackingSize ?? 1); if (currentSize > size) { // We need to handle overlapping fields by reusing blobs based on the rva, and just update diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 8f468f78b3977..46ed11d236a95 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -24,7 +24,6 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private readonly IEnumerable _inputFiles; private readonly string _compositeRootPath; private bool _ibcTuning; - private bool _resilient; private bool _generateMapFile; private bool _generateMapCsvFile; private bool _generatePdbFile; @@ -117,12 +116,6 @@ public ReadyToRunCodegenCompilationBuilder UseIbcTuning(bool ibcTuning) return this; } - public ReadyToRunCodegenCompilationBuilder UseResilience(bool resilient) - { - _resilient = resilient; - return this; - } - public ReadyToRunCodegenCompilationBuilder UseProfileData(ProfileDataManager profileData) { _profileData = profileData; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs index e506bb8b3b6ef..9380a829b8f3c 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs @@ -34,10 +34,10 @@ public static int NameHashCode(string name) byte[] src = Encoding.UTF8.GetBytes(name); for (int i = 0; i < src.Length; i += 2) { - hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ src[i]; + hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ (int)unchecked((sbyte)src[i]); if (i + 1 < src.Length) { - hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ src[i + 1]; + hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ (int)unchecked((sbyte)src[i + 1]); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs index a8e42ec37b9bc..6fc1687d7a7f9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs @@ -46,6 +46,13 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { + if (!MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module)) + { + // When runtime marshalling is disabled, we don't support generating the stub IL + // in Ready-to-Run so we can correctly throw an exception at runtime when the user tries to + // use SetLastError=true when marshalling is disabled. + throw new NotSupportedException(); + } callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( stubHelpersType.GetKnownMethod("ClearLastError", null))); } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 5154db358a8b8..6c7d67517a9ee 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -283,4 +283,5 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs index 927148cf006e2..ddb1d24c1b535 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs @@ -43,7 +43,8 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind) private static Marshaller[] GetMarshallers( MethodSignature methodSig, PInvokeFlags flags, - ParameterMetadata[] parameterMetadataArray) + ParameterMetadata[] parameterMetadataArray, + bool runtimeMarshallingEnabled) { Marshaller[] marshallers = new Marshaller[methodSig.Length + 1]; @@ -64,39 +65,55 @@ private static Marshaller[] GetMarshallers( } TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1]; //first item is the return type - marshallers[i] = CreateMarshaller(parameterType, - parameterIndex, - methodSig.GetEmbeddedSignatureData(), - MarshallerType.Argument, - parameterMetadata.MarshalAsDescriptor, - MarshalDirection.Forward, - marshallers, - parameterMetadata.Index, - flags, - parameterMetadata.In, - parameterMetadata.Out, - parameterMetadata.Return); + if (runtimeMarshallingEnabled) + { + marshallers[i] = CreateMarshaller(parameterType, + parameterIndex, + methodSig.GetEmbeddedSignatureData(), + MarshallerType.Argument, + parameterMetadata.MarshalAsDescriptor, + MarshalDirection.Forward, + marshallers, + parameterMetadata.Index, + flags, + parameterMetadata.In, + parameterMetadata.Out, + parameterMetadata.Return); + } + else + { + marshallers[i] = CreateDisabledMarshaller( + parameterType, + parameterIndex, + MarshallerType.Argument, + MarshalDirection.Forward, + marshallers, + parameterMetadata.Index, + flags, + parameterMetadata.Return); + } } return marshallers; } - public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); return GetMarshallers( targetMethod.Signature, targetMethod.GetPInvokeMethodMetadata().Flags, - targetMethod.GetParameterMetadata()); + targetMethod.GetParameterMetadata(), + MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)targetMethod.OwningType).Module)); } - public static Marshaller[] GetMarshallersForSignature(MethodSignature methodSig, ParameterMetadata[] paramMetadata) + public static Marshaller[] GetMarshallersForSignature(MethodSignature methodSig, ParameterMetadata[] paramMetadata, ModuleDesc moduleContext) { return GetMarshallers( methodSig, new PInvokeFlags(PInvokeAttributes.None), - paramMetadata); + paramMetadata, + MarshalHelpers.IsRuntimeMarshallingEnabled(moduleContext)); } public static bool IsMarshallingRequired(MethodDesc targetMethod) @@ -128,9 +145,9 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod) return false; } - public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata) + public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata, ModuleDesc moduleContext) { - Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata); + Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata, moduleContext); for (int i = 0; i < marshallers.Length; i++) { if (marshallers[i].IsMarshallingRequired()) 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 f8282ab82cd27..c2dcc6b397016 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -1811,7 +1811,7 @@ private void ceeInfoGetCallInfo( pResult->wrapperDelegateInvoke = false; - Get_CORINFO_SIG_INFO(methodToCall, &pResult->sig, useInstantiatingStub); + Get_CORINFO_SIG_INFO(methodToCall, &pResult->sig, scope: null, useInstantiatingStub); } private uint getMethodAttribs(CORINFO_METHOD_STRUCT_* ftn) @@ -2579,7 +2579,7 @@ private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_S else { var sig = HandleToObject(callSiteSig->methodSignature); - return Marshaller.IsMarshallingRequired(sig, Array.Empty()); + return Marshaller.IsMarshallingRequired(sig, Array.Empty(), ((MetadataType)HandleToObject(callSiteSig->scope).OwningMethod.OwningType).Module); } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs index 0d8b11c51f82e..7e2b624a3131f 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs @@ -9,6 +9,7 @@ using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; +using ILLink.Shared; using Internal.IL; using Internal.IL.Stubs; @@ -92,6 +93,9 @@ protected override void CompileInternal(string outputFile, ObjectDumper dumper) NodeFactory.SetMarkingComplete(); ObjectWritingOptions options = default; + if ((_compilationOptions & RyuJitCompilationOptions.UseDwarf5) != 0) + options |= ObjectWritingOptions.UseDwarf5; + if (_debugInformationProvider is not NullDebugInformationProvider) options |= ObjectWritingOptions.GenerateDebugInfo; @@ -195,8 +199,6 @@ private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeN if (exception != null) { - // TODO: fail compilation if a switch was passed - // Try to compile the method again, but with a throwing method body this time. MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception); corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL); @@ -205,12 +207,12 @@ private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeN && method.OwningType is MetadataType mdOwningType && mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute")) { - Logger.LogWarning("COM interop is not supported with full ahead of time compilation", 3052, method, MessageSubCategory.AotAnalysis); + Logger.LogWarning(method, DiagnosticId.COMInteropNotSupportedInFullAOT); } + if ((_compilationOptions & RyuJitCompilationOptions.UseResilience) != 0) + Logger.LogMessage($"Ignoring unresolved method {method}, because: {exception.Message}"); else - { - Logger.LogWarning($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis); - } + Logger.LogError($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis); } } @@ -242,5 +244,7 @@ public enum RyuJitCompilationOptions { MethodBodyFolding = 0x1, ControlFlowGuardAnnotations = 0x2, + UseDwarf5 = 0x4, + UseResilience = 0x8, } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs index 8b753c7103994..a1446f9d3ff27 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs @@ -110,6 +110,12 @@ public override ICompilation ToCompilation() if ((_mitigationOptions & SecurityMitigationOptions.ControlFlowGuardAnnotations) != 0) options |= RyuJitCompilationOptions.ControlFlowGuardAnnotations; + if (_useDwarf5) + options |= RyuJitCompilationOptions.UseDwarf5; + + if (_resilient) + options |= RyuJitCompilationOptions.UseResilience; + var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider, GetPreinitializationManager()); JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions); 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 5966efead0066..1b1fbdf550777 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -1027,7 +1027,7 @@ private CorInfoHelpFunc getNewHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, TypeDesc type = HandleToObject(pResolvedToken.hClass); Debug.Assert(!type.IsString && !type.IsArray && !type.IsCanonicalDefinitionType(CanonicalFormKind.Any)); - + pHasSideEffects = type.HasFinalizer; if (type.RequiresAlign8()) @@ -1520,7 +1520,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO targetIsFatFunctionPointer |= (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0 && !(pResult->kind == CORINFO_CALL_KIND.CORINFO_CALL); - Get_CORINFO_SIG_INFO(targetMethod, &pResult->sig, targetIsFatFunctionPointer); + Get_CORINFO_SIG_INFO(targetMethod, &pResult->sig, scope: null, targetIsFatFunctionPointer); if (useFatCallTransform) { pResult->sig.flags |= CorInfoSigInfoFlags.CORINFO_SIGFLAG_FAT_CALL; @@ -1531,7 +1531,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO if (pResult->hMethod != pResolvedToken.hMethod) { pResult->verMethodFlags = getMethodAttribsInternal(targetMethod); - Get_CORINFO_SIG_INFO(targetMethod, &pResult->verSig); + Get_CORINFO_SIG_INFO(targetMethod, &pResult->verSig, scope: null); } else { @@ -1791,7 +1791,9 @@ private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_S #if DEBUG MethodSignature methodSignature = (MethodSignature)HandleToObject((IntPtr)callSiteSig->pSig); - MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(methodSignature); + MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub( + methodSignature, + ((MetadataType)HandleToObject(callSiteSig->scope).OwningMethod.OwningType).Module); Debug.Assert(!IsPInvokeStubRequired(stub)); #endif @@ -1825,7 +1827,9 @@ private bool convertPInvokeCalliToCall(ref CORINFO_RESOLVED_TOKEN pResolvedToken if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == 0) return false; - MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(signature); + MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub( + signature, + ((MetadataType)methodIL.OwningMethod.OwningType).Module); if (!mustConvert && !IsPInvokeStubRequired(stub)) return false; diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs index f6cd2e187d46c..4bcf3432f522f 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs @@ -202,6 +202,21 @@ public void TestNullableCasting() Assert.True(intType.CanCastTo(nullableOfIntType)); } + [Fact] + public void TestGenericParameterArrayCasting() + { + TypeDesc baseArrayType = _testModule.GetType("Casting", "Base").MakeArrayType(); + TypeDesc iFooArrayType = _testModule.GetType("Casting", "IFoo").MakeArrayType(); + + TypeDesc paramArrayWithBaseClassConstraint = + _testModule.GetType("Casting", "ClassWithBaseClassConstraint`1").Instantiation[0].MakeArrayType(); + TypeDesc paramArrayWithInterfaceConstraint = + _testModule.GetType("Casting", "ClassWithInterfaceConstraint`1").Instantiation[0].MakeArrayType(); + + Assert.True(paramArrayWithBaseClassConstraint.CanCastTo(baseArrayType)); + Assert.False(paramArrayWithInterfaceConstraint.CanCastTo(iFooArrayType)); + } + [Fact] public void TestRecursiveCanCast() { diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs index a6ae700e942a1..03ce4ae4332cd 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs @@ -3,6 +3,8 @@ namespace Casting { + class Base { } + interface IFoo { } interface IContravariant { } @@ -21,6 +23,8 @@ class ClassWithNoConstraint { } class ClassWithValueTypeConstraint where T : struct { } + class ClassWithBaseClassConstraint where T : Base { } + class ClassWithInterfaceConstraint where T : IFoo { } class ClassWithRecursiveImplementation : IContravariant> { } diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index 6c559924f405c..6c5a4a6d377d8 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -1,4 +1,4 @@ - + ilc true @@ -121,10 +121,6 @@ On Linux renaming the library makes it difficult to debug it. --> - + diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index e973c05b08c2c..51400a9e939be 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -61,6 +61,7 @@ internal class Program private string _instructionSet; private string _guard; private int _maxGenericCycle = CompilerTypeSystemContext.DefaultGenericCycleCutoffPoint; + private bool _useDwarf5; private string _singleMethodTypeName; private string _singleMethodName; @@ -84,6 +85,8 @@ internal class Program private IReadOnlyList _directPInvokeLists = Array.Empty(); + private bool _resilient; + private IReadOnlyList _rootedAssemblies = Array.Empty(); private IReadOnlyList _conditionallyRootedAssemblies = Array.Empty(); private IReadOnlyList _trimmedAssemblies = Array.Empty(); @@ -178,6 +181,7 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("Ot", ref optimizeTime, "Enable optimizations, favor code speed"); syntax.DefineOptionList("m|mibc", ref _mibcFilePaths, "Mibc file(s) for profile guided optimization"); ; syntax.DefineOption("g", ref _enableDebugInfo, "Emit debugging information"); + syntax.DefineOption("gdwarf-5", ref _useDwarf5, "Generate source-level debug information with dwarf version 5"); syntax.DefineOption("nativelib", ref _nativeLib, "Compile as static or shared library"); syntax.DefineOption("exportsfile", ref _exportsFile, "File to write exported method definitions"); syntax.DefineOption("dgmllog", ref _dgmlLogFileName, "Save result of dependency analysis as DGML"); @@ -188,6 +192,7 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("systemmodule", ref _systemModuleName, "System module name (default: System.Private.CoreLib)"); syntax.DefineOption("multifile", ref _multiFile, "Compile only input files (do not compile referenced assemblies)"); syntax.DefineOption("waitfordebugger", ref waitForDebugger, "Pause to give opportunity to attach debugger"); + syntax.DefineOption("resilient", ref _resilient, "Ignore unresolved types, methods, and assemblies. Defaults to false"); syntax.DefineOptionList("codegenopt", ref _codegenOptions, "Define a codegen option"); syntax.DefineOptionList("rdxml", ref _rdXmlFilePaths, "RD.XML file(s) for compilation"); syntax.DefineOption("map", ref _mapFileName, "Generate a map file"); @@ -769,7 +774,8 @@ static string ILLinkify(string rootedAssembly) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode) .UseSecurityMitigationOptions(securityMitigationOptions) - .UseDebugInfoProvider(debugInfoProvider); + .UseDebugInfoProvider(debugInfoProvider) + .UseDwarf5(_useDwarf5); if (scanResults != null) { @@ -798,6 +804,8 @@ static string ILLinkify(string rootedAssembly) builder.UseMethodImportationErrorProvider(scanResults.GetMethodImportationErrorProvider()); } + builder.UseResilience(_resilient); + ICompilation compilation = builder.ToCompilation(); ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null; diff --git a/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj index 52b0f44fc4891..c0df3bfd2c6ee 100644 --- a/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj +++ b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj @@ -9,7 +9,7 @@ linux-x64;win-x64;osx-x64 Debug;Release;Checked true - 649;169;414 + false $"IL{(int)diagnosticId}"; + + public static string GetDiagnosticSubcategory(this DiagnosticId diagnosticId) => + (int)diagnosticId switch + { + 2026 => MessageSubCategory.TrimAnalysis, + 2032 => MessageSubCategory.TrimAnalysis, + 2041 => MessageSubCategory.TrimAnalysis, + 2042 => MessageSubCategory.TrimAnalysis, + 2043 => MessageSubCategory.TrimAnalysis, + 2045 => MessageSubCategory.TrimAnalysis, + 2046 => MessageSubCategory.TrimAnalysis, + 2050 => MessageSubCategory.TrimAnalysis, + >= 2055 and <= 2099 => MessageSubCategory.TrimAnalysis, + 2103 => MessageSubCategory.TrimAnalysis, + 2106 => MessageSubCategory.TrimAnalysis, + 2107 => MessageSubCategory.TrimAnalysis, + >= 2109 and <= 2116 => MessageSubCategory.TrimAnalysis, + >= 3050 and <= 3052 => MessageSubCategory.AotAnalysis, + >= 3054 and <= 3055 => MessageSubCategory.AotAnalysis, + _ => MessageSubCategory.None, + }; } } diff --git a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs index 103b93ed28bb0..f14b58b060083 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs +++ b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs @@ -1,6 +1,8 @@ // 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 ILLink.Shared { public readonly struct DiagnosticString @@ -11,15 +13,15 @@ public readonly struct DiagnosticString public DiagnosticString(DiagnosticId diagnosticId) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString($"{diagnosticId}Title") ?? string.Empty; - _messageFormat = resourceManager.GetString($"{diagnosticId}Message") ?? string.Empty; + _titleFormat = resourceManager.GetString($"{diagnosticId}Title") ?? throw new InvalidOperationException($"{diagnosticId} does not have a matching resource called {diagnosticId}Title"); + _messageFormat = resourceManager.GetString($"{diagnosticId}Message") ?? throw new InvalidOperationException($"{diagnosticId} does not have a matching resource called {diagnosticId}Message"); } public DiagnosticString(string diagnosticResourceStringName) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString($"{diagnosticResourceStringName}Title") ?? string.Empty; - _messageFormat = resourceManager.GetString($"{diagnosticResourceStringName}Message") ?? string.Empty; + _titleFormat = resourceManager.GetString($"{diagnosticResourceStringName}Title") ?? throw new InvalidOperationException($"{diagnosticResourceStringName} does not have a matching resource called {diagnosticResourceStringName}Title"); + _messageFormat = resourceManager.GetString($"{diagnosticResourceStringName}Message") ?? throw new InvalidOperationException($"{diagnosticResourceStringName} does not have a matching resource called {diagnosticResourceStringName}Message"); } public string GetMessage(params string[] args) => diff --git a/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd b/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd new file mode 100644 index 0000000000000..f1156b0a4d690 --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems b/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems index 0a61390d8d025..ffbfab3b98417 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems +++ b/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems @@ -13,6 +13,7 @@ + @@ -21,4 +22,9 @@ Designer - \ No newline at end of file + + + Designer + + + diff --git a/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs b/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs new file mode 100644 index 0000000000000..92c1077b14baf --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ILLink.Shared +{ + public static class MessageSubCategory + { + public const string None = ""; + public const string TrimAnalysis = "Trim analysis"; + public const string UnresolvedAssembly = "Unresolved assembly"; + public const string AotAnalysis = "AOT analysis"; + } +} diff --git a/src/coreclr/tools/aot/ILLink.Shared/README.md b/src/coreclr/tools/aot/ILLink.Shared/README.md new file mode 100644 index 0000000000000..229b67e492bf0 --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/README.md @@ -0,0 +1 @@ +Sources taken from https://github.com/dotnet/linker/tree/890591b13da936d2c38a52afdaeac0db69858d4f/src/ILLink.Shared. diff --git a/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx b/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx index 0d53dff7e254e..fe39e38906517 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx +++ b/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx @@ -53,7 +53,6 @@ value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. - mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter @@ -117,12 +116,954 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + An Xml Feature does not specify a 'featurevalue' attribute. + + + Failed to process '{0}'. Feature '{1}' does not specify a 'featurevalue' attribute. + + + Feature definition has to be a boolean. + + + Failed to process '{0}'. Unsupported non-boolean feature definition '{1}'. + + + An exception was thrown while processing the xml file. + + + Error processing '{0}': {1}. + + + An error ocurred while processing a method in assembly. + + + Error processing method '{0}' in assembly '{1}'. + + + Cannot stub constructor of a type when base type does not have default constructor. Constructors of derived types marked for substitution require to have a default constructor in its base type. + + + Cannot stub constructor on '{0}' when base type does not have default constructor. + + + Could not find predefined type". + + + Missing predefined '{0}' type". + + + Could not find constructor. + + + Could not find constructor on '{0}'. + + + Assembly reference could not be resolved. + + + Assembly reference '{0}' could not be resolved. + + + Assembly cannot be loaded due to failure in processing the reference assembly. + + + Assembly '{0}' cannot be loaded due to failure in processing '{1}' reference + + + There was an error writing the linked assembly 'output'. + + + Failed to write '{0}'. + + + There was an unexpected error while trimming. An exception with more details is printed to the MSBuild log. Please share this stack trace with the IL Linker team to further investigate the cause and possible solution. + + + IL Trimmer has encountered an unexpected error. Please report the issue at https://github.com/dotnet/linker/issues + + + There was an error processing 'XML document location' xml file. The most likely reason for this is that the XML file has syntactical errors. + + + Error processing '{0}'. + + + Element in XML document contains a 'featuredefault' attribute with an invalid value. + + + Failed to process '{0}'. Unsupported value for featuredefault attribute. + + + The string passed to the command-line does not correspond to a valid command-line option. + + + Unrecognized command-line option: '{0}'. + + + The value given for the --warn argument was not a valid warning version. + + + Invalid warning version '{0}'. + + + Invalid value 'value' was used for command-line option '--generate-warning-suppressions'; must be 'cs' or 'xml'. + + + Invalid value '{0}' for '--generate-warning-suppressions' option. + + + The command-line option 'optionName' was specified but no argument was given. + + + Missing argument for '{0}' option. + + + The command-line option --custom-data receives a key-value pair using the format KEY=VALUE. + + + Value used with '--custom-data' has to be in the KEY=VALUE format. + + + No input files were specified. Use one of the resolver options. + + + No input files were specified. Use one of '{0}' options. + + + Options '--new-mvid' and '--deterministic' cannot be used at the same time. + + + Options '--new-mvid' and '--deterministic' cannot be used at the same time. + + + The assembly argument specified for '--custom-step' option could not be found. + + + The assembly '{0}' specified for '--custom-step' option could not be found. + + + The path to the assembly specified for '--custom-step' must be fully qualified. + + + The path to the assembly '{0}' specified for '--custom-step' must be fully qualified. + + + An invalid value was specified for '--custom-step' option. + + + Invalid value '{0}' specified for '--custom-step' option. + + + A custom step that is inserted relative to an existing step in the pipeline must specify whether to be added before (-) or after (+) the step it's relative to. + + + Expected '+' or '-' to control new step insertion. + + + A custom step was specified for insertion relative to a non existent step. + + + Pipeline step '{0}' could not be found. + + + The custom step could not be found in the given assembly. + + + Custom step '{0}' could not be found. + + + Custom step is incompatible with this trimmer version. + + + Custom step '{0}' is incompatible with this trimmer version. + + + The optimization 'text' is invalid. Optimization values can either be 'beforefieldinit', 'overrideremoval', 'unreachablebodies', 'unusedinterfaces', 'ipconstprop', or 'sealer'. + + + Invalid optimization value '{0}'. + + + Invalid argument for 'token' option. + + + Invalid argument for '{0}' option. + + + Invalid assembly action. + + + Invalid assembly action '{0}'. + + + Root assembly could not be found. + + + Root assembly '{0}' could not be found. + + + XML descriptor file could not be found'. + + + XML descriptor file '{0}' could not be found'. + + + Root assembly does not have entry point. + + + Root assembly '{0}' does not have entry point. + + + Referenced root assembly cannot use the specified action. + + + Root assembly '{0}' cannot use action '{1}'. + + + Invalid assembly name. + + + Invalid assembly name '{0}'. + + + Invalid assembly root mode. + + + Invalid assembly root mode '{0}'. + + + Exported type cannot be resolved. + + + Exported type '{0}' cannot be resolved. + + + A reference assembly input passed via -reference could not be loaded. + + + Reference assembly '{0}' could not be loaded. + + + Metadata element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + {0}. + + + Field element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Field '{0}' reference could not be resolved. + + + Method element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Method '{0}' reference could not be resolved. + + + Type element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Type '{0}' reference could not be resolved. + + + The type name used to define custom attribute value could not be resolved. + + + The type '{0}' used with attribute value '{1}' could not be found. + + + The 'value' specified for the custom attribute value cannot be converted to specified argument type 'typeName'. + + + Cannot convert value '{0}' to type '{1}'. + + + The syntax for custom attribute value for 'type' requires to also specify the underlying attribute type. + + + Custom attribute argument for '{0}' requires nested '{1}' node. + + + The value specified for the custom attribute of System.Type type could not be resolved. + + + Could not resolve custom attribute type value '{0}'. + + + The type name used with attribute type is not one of the supported types. + + + Unexpected attribute argument type '{0}'. + + + Invalid metadata value. + + + Invalid metadata value '{0}'. + + + The XML descriptor preserves fields on type, but this type has no fields. + + + Type '{0}' has no fields to preserve. + + + The XML descriptor preserves methods on type, but this type has no methods. + + + Type '{0}' has no methods to preserve. + + + The assembly in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency assembly '{0}' specified in a 'PreserveDependency' attribute. + + + The type in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency type '{0}' specified in a 'PreserveDependency' attribute. + + + The member in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency member '{0}' declared in type '{1}' specified in a 'PreserveDependency' attribute. + + + The assembly in the XML could not be resolved. + + + Could not resolve assembly '{0}'. + + + The type in the XML could not be resolved. + + + Could not resolve type '{0}'. + + + The XML defined a method on a type, but the method was not found. + + + Could not find method '{0}' on type '{1}'. + + + Invalid value for 'signature' stub in the substitution XML. + + + Invalid value for '{0}' stub. + + + The value of the body attribute used in the substitution XML is invalid (the only supported options are remove and stub). + + + Unknown body modification '{0}' for '{1}'. + + + The XML defined a field on a type, but the field was not found. + + + Could not find field '{0}' on type '{1}'. + + + The substituted field 'field' was non-static or constant. Only static non-constant fields are supported. + + + Substituted field '{0}' needs to be static field. + + + A field was specified for substitution but no value to be substituted was given. + + + Missing 'value' attribute for field '{0}'. + + + The value used in the substitution XML for field is not a built-in type, or does not match the type of the field. + + + Invalid value '{0}' for '{1}'. + + + The XML defined a event on a type, but the event was not found. + + + Could not find event '{0}' on type '{1}'. + + + The XML defined a property on a type, but the property was not found. + + + Could not find property '{0}' on type '{1}'. + + + The XML defined the get accessor of property on a type, but the accessor was not found. + + + Could not find the get accessor of property '{0}' on type '{1}'. + + + The XML defined the set accessor of property on a type, but the accessor was not found. + + + Could not find the set accessor of property '{0}' in type '{1}'. + + + The XML attribute arguments use values or types which don't match to any constructor + + + Could not find matching constructor for custom attribute '{0}' arguments. + + + Method 'method' has more than one return element specified. There can only be one return element. + + + There is more than one 'return' child element specified for method '{0}'. + + + Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter. + + + More than one value specified for parameter '{0}' of method '{1}'. + + + The XML descriptor marks for preservation the member more than once. + + + Duplicate preserve of '{0}'. + Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code Using member '{0}' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.{1}{2} + + Using dynamic types might cause types or members to be removed by trimmer. + + + Invoking members on dynamic types is not trimming-compatible. Types or members might have been removed by the trimmer. + + + The linker found multiple instances of attribute on a member. This attribute is only allowed to have one instance. + + + Attribute '{0}' should only be used once on '{1} + + + Attribute doesn't have the required number of parameters specified. + + + Attribute '{0}' doesn't have the required number of parameters specified. + + + 'attribute' element does not contain attribute 'fullname' or it's empty. + + + 'attribute' element does not contain attribute 'fullname' or it's empty. + + + The assembly name specified for attribute could not be resolved. + + + Could not resolve assembly '{0}' for attribute '{1}'. + + + The described attribute type could not be found in the assemblies. + + + Attribute type '{0}' could not be found. + + + The value passed as the assembly name or type name to the CreateInstance method can't be statically analyzed. + + + Unrecognized value passed to the parameter '{0}' of method '{1}'. It's not possible to guarantee the availability of the target type. + + + 'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead. + + + 'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead. + + + The input contains an invalid use of DynamicDependencyAttribute. + + + The 'DynamicDependencyAttribute' could not be analyzed. + + + The assembly string given in a DynamicDependencyAttribute constructor could not be resolved. + + + Unresolved assembly '{0}' in 'DynamicDependencyAttribute'. + + + The type in a DynamicDependencyAttribute constructor could not be resolved. + + + Unresolved type '{0}' in 'DynamicDependencyAttribute'. + + + The member signature or DynamicallyAccessedMemberTypes in a DynamicDependencyAttribute constructor did not resolve to any members on the type. + + + No members were resolved for '{0}'. + + + The resource element in a substitution file did not have a 'name' attribute. + + + Missing 'name' attribute for resource. + + + The resource element in a substitution file did not have a valid 'action' attribute. + + + Invalid value '{0}' for attribute 'action' for resource '{1}'. + + + The resource name in a substitution file could not be found in the specified assembly. + + + Could not find embedded resource '{0}' to remove in assembly '{1}'. + + + The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters. + + + The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters though. + + + Could not find a unique backing field for property to propagate 'DynamicallyAccessedMembersAttribute'. + + + Could not find a unique backing field for property '{0}' to propagate 'DynamicallyAccessedMembersAttribute'. + + + 'DynamicallyAccessedMembersAttribute' on property conflicts with the same attribute on its accessor. + + + 'DynamicallyAccessedMembersAttribute' on property '{0}' conflicts with the same attribute on its accessor '{1}'. + + + The XML descriptor specifies a namespace but there are no types found in such namespace. + + + Could not find any type in namespace '{0}'. + + + An attribute is being referenced in the code but the attribute instances have been removed using the 'RemoveAttributeInstances' internal attribute. + + + Attribute '{0}' is being referenced in code but the trimmer was instructed to remove all instances of this attribute. If the attribute instances are necessary make sure to either remove the trimmer attribute XML portion which removes the attribute instances, or override the removal by using the trimmer XML descriptor to keep the attribute type (which in turn keeps all of its instances). + + + 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + + {0}. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + + Internal attribute 'RemoveAttributeInstances' can only be used on attribute types. + + + Internal attribute '{0}' can only be used on attribute types. + + + Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. + + + P/invoke method '{0}' declares a parameter with COM marshalling. Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. + + + An attribute element has property but this could not be found. + + + Property element does not contain attribute 'name'. + + + An attribute element has property but this could not be found. + + + Property '{0}' could not be found. + + + Either the type on which the MakeGenericType is called can't be statically determined, or the type parameters to be used for generic arguments can't be statically determined. + + + Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. + + + 'DynamicallyAccessedMemberAttribute' on property conflicts with the same attribute on its backing field. + + + 'DynamicallyAccessedMemberAttribute' on property '{0}' conflicts with the same attribute on its backing field '{1}'. + + + Unrecognized value passed to the parameter of method. It's not possible to guarantee the availability of the target type. + + + Unrecognized value passed to the parameter 'typeName' of method '{0}'. It's not possible to guarantee the availability of the target type. + + + Parameters passed to method cannot be analyzed. Consider using methods 'System.Type.GetType' and `System.Activator.CreateInstance` instead. + + + Parameters passed to method '{0}' cannot be analyzed. Consider using methods 'System.Type.GetType' and `System.Activator.CreateInstance` instead. + + + The type passed to the RunClassConstructor is not statically known, Trimmer can't make sure that its static constructor is available. + + + Unrecognized value passed to the parameter 'type' of method '{0}'. It's not possible to guarantee the availability of the target static constructor. + + + Call to 'System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. + + + Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. + + + Calling CreateInstance with assembly name which can't be resolved. + + + The assembly name '{0}' passed to method '{1}' references assembly which is not available. + + + The parameter of method has a DynamicallyAccessedMembersAttribute, but the value passed to it can not be statically analyzed. + + + Value passed to parameter '{0}' of method '{1}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The return value of method has a DynamicallyAccessedMembersAttribute, but the value returned from the method can not be statically analyzed. + + + Value returned from method '{0}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The field has a DynamicallyAccessedMembersAttribute, but the value assigned to it can not be statically analyzed. + + + Value assigned to {0} can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The method has a DynamicallyAccessedMembersAttribute (which applies to the implicit 'this' parameter), but the value used for the 'this' parameter can not be statically analyzed. + + + Value passed to implicit 'this' parameter of method '{0}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The generic parameter of type or method has a DynamicallyAccessedMembersAttribute, but the value used for it can not be statically analyzed. + + + Type passed to generic parameter '{0}' of '{1}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations. + + + '{0}' argument does not satisfy {4} in call to '{1}'. The parameter '{2}' of method '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The parameter of method does not have matching annotations. + + + '{0}' method return value does not satisfy {3} requirements. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The parameter of method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {3} requirements. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations. + + + 'this' argument does not satisfy {3} in call to '{0}'. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The parameter of method does not have matching annotations. + + + '{0}' generic argument does not satisfy {4} in '{1}'. The parameter '{2}' of method '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The return value of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The return value of the source method does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The return value of the source method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The return value of the source method does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The return value of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The field '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The source field does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The source field does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The source field does not have matching annotations. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The field '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The implicit 'this' argument of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The implicit 'this' argument of source method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The implicit 'this' argument of source method does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The implicit 'this' argument of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' argument does not satisfy {4} in call to '{1}'. The generic parameter '{2}' of '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' method return value does not satisfy {3} requirements. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The generic parameter of the source method or type does not have matching annotations. + + + value stored in field '{0}' does not satisfy {3} requirements. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations. + + + 'this' argument does not satisfy {3} in call to '{0}'. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' generic argument does not satisfy {4} in '{1}'. The generic parameter '{2}' of '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'DynamicallyAccessedMemberTypes' on the parameter of method don't match overridden parameter of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter '{0}' of method '{1}' don't match overridden parameter '{2}' of method '{3}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the return value of method don't match overridden return value of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method '{0}' don't match overridden return value of method '{1}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the implicit 'this' parameter of method don't match overridden implicit 'this' parameter of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the implicit 'this' parameter of method '{0}' don't match overridden implicit 'this' parameter of method '{1}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the generic parameter of method or type don't match overridden generic parameter method or type. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the generic parameter '{0}' of '{1}' don't match overridden generic parameter '{2}' of '{3}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + Call to 'Type.GetType' method can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types. + + + Call to '{0}' can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types. + + + Field has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'. + + + Field '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'. + + + Parameter of method has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'. + + + Parameter '{0}' of method '{1}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'. + + + Property has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Property '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + XML contains unsupported wildcard for assembly 'fullname' attribute. + + + XML contains unsupported wildcard for assembly 'fullname' attribute. + + + Embedded XML in assembly contains assembly "fullname" attribute for another assembly + + + Embedded XML in assembly '{0}' contains assembly "fullname" attribute for another assembly '{1}' + + + Invalid AssemblyMetadata 'IsTrimmable' attribute in assembly. Value must be "True". + + + Invalid AssemblyMetadata("IsTrimmable", "{0}") attribute in assembly '{1}'. Value must be "True". + + + Value passed to the parameter of method cannot be statically determined as a property accessor. + + + Value passed to the '{0}' parameter of method '{1}' cannot be statically determined as a property accessor. + + + Assembly produced trim warnings. + + + Assembly '{0}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries + + + Type 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. + + + Type '{0}' 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. + + + Return type of method has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Return type of method '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Trimmer currently can't correctly handle if the same compiler generated state machine type is associated (via the state machine attributes) with two different methods. + + + Methods '{0}' and '{1}' are both associated with state machine type '{2}'. This is currently unsupported and may lead to incorrectly reported warnings. + + + Invalid scope used in 'UnconditionalSuppressMessageAttribute'. The only scopes supported on global unconditional suppressions are 'module', 'type' and 'member'. + + + Invalid scope '{0}' used in 'UnconditionalSuppressMessageAttribute' on module '{1}' with target '{2}'. + + + Types that derive from a base class with 'RequiresUnreferencedCodeAttribute' need to explicitly use the 'RequiresUnreferencedCodeAttribute' or suppress this warning + + + Type '{0}' derives from '{1}' which has 'RequiresUnreferencedCodeAttribute'. {2}{3} + + + Field with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field. + + + Field '{0}' with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field. + + + Method with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. + + + Method '{0}' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which requires unreferenced code. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.{2}{3} + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which requires unreferenced code. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.{2}{3} + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements. + + + The use of 'RequiresUnreferencedCodeAttribute' on static constructors is disallowed since is a method not callable by the user, is only called by the runtime. Placing the attribute directly on the static constructor will have no effect, instead use 'RequiresUnreferencedCodeAttribute' on the type which will handle warning and silencing from the static constructor. + + + 'RequiresUnreferencedCodeAttribute' cannot be placed directly on static constructor '{0}', consider placing 'RequiresUnreferencedCodeAttribute' on the type declaration instead. + Avoid accessing Assembly file path when publishing as a single file @@ -141,29 +1082,47 @@ Using member '{0}' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app.{1}{2} + + 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + + {0}. 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling. Using member '{0}' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling.{1}{2} - - {0}. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. - - - 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. {0}. 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. - - 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. + + COM interop is not supported with full ahead of time compilation. - - {0}. 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + COM interop is not supported with full ahead of time compilation. - - 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + Assembly produced AOT analysis warnings. + + + Assembly '{0}' produced AOT analysis warnings. + + + Generic expansion to was aborted due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. + + + Generic expansion to '{0}' was aborted due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. Generic recursion also negatively affects compilation speed and the size of the compilation output. It is advisable to remove the source of the generic recursion by restructuring the program around the source of recursion. The source of generic recursion might include: {1} + + + P/invoke method declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation. + + + P/invoke method '{0}' declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation: the marshalling code for the delegate might not be available. Use a non-abstract delegate type or ensure any delegate instance passed as parameter is marked with `UnmanagedFunctionPointerAttribute`. Base member '{2}' with '{0}' has a derived member '{1}' without '{0}' @@ -177,40 +1136,4 @@ Interface member '{2}' with '{0}' has an implementation member '{1}' without '{0}' - - Type '{0}' derives from '{1}' which has 'RequiresUnreferencedCodeAttribute'. {2}{3} - - - Types that derive from a base class with 'RequiresUnreferencedCodeAttribute' need to explicitly use the 'RequiresUnreferencedCodeAttribute' or suppress this warning - - - Invoking members on dynamic types is not trimming-compatible. Types or members might have been removed by the trimmer. - - - Using dynamic types might cause types or members to be removed by trimmer. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. - - - 'RequiresUnreferencedCodeAttribute' cannot be placed directly on static constructor '{0}', consider placing 'RequiresUnreferencedCodeAttribute' on the type declaration instead. - - - The use of 'RequiresUnreferencedCodeAttribute' on static constructors is disallowed since is a method not callable by the user, is only called by the runtime. Placing the attribute directly on the static constructor will have no effect, instead use 'RequiresUnreferencedCodeAttribute' on the type which will handle warning and silencing from the static constructor. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. - - - Value passed to the '{0}' parameter of method '{1}' cannot be statically determined as a property accessor. - - - P/invoke method '{0}' declares a parameter with COM marshalling. Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. - - - P/invoke method '{0}' declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation: the marshalling code for the delegate might not be available. Use a non-abstract delegate type or ensure any delegate instance passed as parameter is marked with `UnmanagedFunctionPointerAttribute`. - diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index ff538c05fd64c..6eedd33da4a6d 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -730,7 +730,6 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru builder .UseIbcTuning(_commandLineOptions.Tuning) - .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseMapCsvFile(_commandLineOptions.MapCsv) .UsePdbFile(_commandLineOptions.Pdb, _commandLineOptions.PdbPath) @@ -748,6 +747,7 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) .UseParallelism(_commandLineOptions.Parallelism) + .UseResilience(_commandLineOptions.Resilient) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(optimizationMode); diff --git a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs index 09e2f52ea053a..afdb148089b26 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs @@ -260,7 +260,7 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); @@ -278,12 +278,9 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/ToolBox/superpmi/.clang-format b/src/coreclr/tools/superpmi/.clang-format similarity index 100% rename from src/coreclr/ToolBox/superpmi/.clang-format rename to src/coreclr/tools/superpmi/.clang-format diff --git a/src/coreclr/ToolBox/superpmi/CMakeLists.txt b/src/coreclr/tools/superpmi/CMakeLists.txt similarity index 100% rename from src/coreclr/ToolBox/superpmi/CMakeLists.txt rename to src/coreclr/tools/superpmi/CMakeLists.txt diff --git a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt b/src/coreclr/tools/superpmi/mcs/CMakeLists.txt similarity index 96% rename from src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt rename to src/coreclr/tools/superpmi/mcs/CMakeLists.txt index 56dcaff658cc5..8ce4c19725082 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/mcs/CMakeLists.txt @@ -68,4 +68,4 @@ else() endif(CLR_CMAKE_HOST_UNIX) -install_clr(TARGETS mcs DESTINATIONS .) +install_clr(TARGETS mcs DESTINATIONS . COMPONENT spmi) diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp b/src/coreclr/tools/superpmi/mcs/commandline.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/commandline.cpp rename to src/coreclr/tools/superpmi/mcs/commandline.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.h b/src/coreclr/tools/superpmi/mcs/commandline.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/commandline.h rename to src/coreclr/tools/superpmi/mcs/commandline.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp b/src/coreclr/tools/superpmi/mcs/mcs.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/mcs.cpp rename to src/coreclr/tools/superpmi/mcs/mcs.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/mcs.h b/src/coreclr/tools/superpmi/mcs/mcs.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/mcs.h rename to src/coreclr/tools/superpmi/mcs/mcs.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/removedup.cpp b/src/coreclr/tools/superpmi/mcs/removedup.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/removedup.cpp rename to src/coreclr/tools/superpmi/mcs/removedup.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/removedup.h b/src/coreclr/tools/superpmi/mcs/removedup.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/removedup.h rename to src/coreclr/tools/superpmi/mcs/removedup.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbasmdump.cpp b/src/coreclr/tools/superpmi/mcs/verbasmdump.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbasmdump.cpp rename to src/coreclr/tools/superpmi/mcs/verbasmdump.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbasmdump.h b/src/coreclr/tools/superpmi/mcs/verbasmdump.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbasmdump.h rename to src/coreclr/tools/superpmi/mcs/verbasmdump.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbconcat.cpp b/src/coreclr/tools/superpmi/mcs/verbconcat.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbconcat.cpp rename to src/coreclr/tools/superpmi/mcs/verbconcat.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbconcat.h b/src/coreclr/tools/superpmi/mcs/verbconcat.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbconcat.h rename to src/coreclr/tools/superpmi/mcs/verbconcat.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdump.cpp b/src/coreclr/tools/superpmi/mcs/verbdump.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdump.cpp rename to src/coreclr/tools/superpmi/mcs/verbdump.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdump.h b/src/coreclr/tools/superpmi/mcs/verbdump.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdump.h rename to src/coreclr/tools/superpmi/mcs/verbdump.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp b/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp rename to src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.h b/src/coreclr/tools/superpmi/mcs/verbdumpmap.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.h rename to src/coreclr/tools/superpmi/mcs/verbdumpmap.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.cpp b/src/coreclr/tools/superpmi/mcs/verbdumptoc.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.cpp rename to src/coreclr/tools/superpmi/mcs/verbdumptoc.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.h b/src/coreclr/tools/superpmi/mcs/verbdumptoc.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.h rename to src/coreclr/tools/superpmi/mcs/verbdumptoc.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbfracture.cpp b/src/coreclr/tools/superpmi/mcs/verbfracture.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbfracture.cpp rename to src/coreclr/tools/superpmi/mcs/verbfracture.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbfracture.h b/src/coreclr/tools/superpmi/mcs/verbfracture.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbfracture.h rename to src/coreclr/tools/superpmi/mcs/verbfracture.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbildump.cpp b/src/coreclr/tools/superpmi/mcs/verbildump.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbildump.cpp rename to src/coreclr/tools/superpmi/mcs/verbildump.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbildump.h b/src/coreclr/tools/superpmi/mcs/verbildump.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbildump.h rename to src/coreclr/tools/superpmi/mcs/verbildump.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbinteg.cpp b/src/coreclr/tools/superpmi/mcs/verbinteg.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbinteg.cpp rename to src/coreclr/tools/superpmi/mcs/verbinteg.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbinteg.h b/src/coreclr/tools/superpmi/mcs/verbinteg.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbinteg.h rename to src/coreclr/tools/superpmi/mcs/verbinteg.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp b/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp rename to src/coreclr/tools/superpmi/mcs/verbjitflags.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h b/src/coreclr/tools/superpmi/mcs/verbjitflags.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h rename to src/coreclr/tools/superpmi/mcs/verbjitflags.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbmerge.cpp rename to src/coreclr/tools/superpmi/mcs/verbmerge.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbmerge.h b/src/coreclr/tools/superpmi/mcs/verbmerge.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbmerge.h rename to src/coreclr/tools/superpmi/mcs/verbmerge.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.cpp b/src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.cpp rename to src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.h b/src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.h rename to src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbremovedup.cpp b/src/coreclr/tools/superpmi/mcs/verbremovedup.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbremovedup.cpp rename to src/coreclr/tools/superpmi/mcs/verbremovedup.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbremovedup.h b/src/coreclr/tools/superpmi/mcs/verbremovedup.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbremovedup.h rename to src/coreclr/tools/superpmi/mcs/verbremovedup.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstat.cpp b/src/coreclr/tools/superpmi/mcs/verbstat.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbstat.cpp rename to src/coreclr/tools/superpmi/mcs/verbstat.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstat.h b/src/coreclr/tools/superpmi/mcs/verbstat.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbstat.h rename to src/coreclr/tools/superpmi/mcs/verbstat.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstrip.cpp b/src/coreclr/tools/superpmi/mcs/verbstrip.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbstrip.cpp rename to src/coreclr/tools/superpmi/mcs/verbstrip.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstrip.h b/src/coreclr/tools/superpmi/mcs/verbstrip.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbstrip.h rename to src/coreclr/tools/superpmi/mcs/verbstrip.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbtoc.cpp b/src/coreclr/tools/superpmi/mcs/verbtoc.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbtoc.cpp rename to src/coreclr/tools/superpmi/mcs/verbtoc.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbtoc.h b/src/coreclr/tools/superpmi/mcs/verbtoc.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/mcs/verbtoc.h rename to src/coreclr/tools/superpmi/mcs/verbtoc.h diff --git a/src/coreclr/ToolBox/superpmi/readme.md b/src/coreclr/tools/superpmi/readme.md similarity index 99% rename from src/coreclr/ToolBox/superpmi/readme.md rename to src/coreclr/tools/superpmi/readme.md index c3de3dfe94288..b84e8d01697bd 100644 --- a/src/coreclr/ToolBox/superpmi/readme.md +++ b/src/coreclr/tools/superpmi/readme.md @@ -1,6 +1,6 @@ # Overview -This directory (`src/coreclr/ToolBox/superpmi` in the GitHub +This directory (`src/coreclr/tools/superpmi` in the GitHub https://github.com/dotnet/runtime repository) contains the SuperPMI tool used for testing the .NET just-in-time (JIT) compiler. diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h rename to src/coreclr/tools/superpmi/superpmi-shared/agnostic.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/asmdumper.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/asmdumper.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.h b/src/coreclr/tools/superpmi/superpmi-shared/asmdumper.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.h rename to src/coreclr/tools/superpmi/superpmi-shared/asmdumper.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.cpp b/src/coreclr/tools/superpmi/superpmi-shared/callutils.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/callutils.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.h b/src/coreclr/tools/superpmi/superpmi-shared/callutils.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.h rename to src/coreclr/tools/superpmi/superpmi-shared/callutils.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.h b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.h rename to src/coreclr/tools/superpmi/superpmi-shared/compileresult.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/crlwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/crlwmlist.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/crlwmlist.h rename to src/coreclr/tools/superpmi/superpmi-shared/crlwmlist.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.cpp b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.h b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.h rename to src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/hash.cpp b/src/coreclr/tools/superpmi/superpmi-shared/hash.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/hash.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/hash.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/hash.h b/src/coreclr/tools/superpmi/superpmi-shared/hash.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/hash.h rename to src/coreclr/tools/superpmi/superpmi-shared/hash.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjitcompilerimpl.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h rename to src/coreclr/tools/superpmi/superpmi-shared/icorjitcompilerimpl.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjithostimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjithostimpl.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjithostimpl.h rename to src/coreclr/tools/superpmi/superpmi-shared/icorjithostimpl.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjitinfoimpl.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h rename to src/coreclr/tools/superpmi/superpmi-shared/icorjitinfoimpl.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/lightweightmap.h b/src/coreclr/tools/superpmi/superpmi-shared/lightweightmap.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/lightweightmap.h rename to src/coreclr/tools/superpmi/superpmi-shared/lightweightmap.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/logging.cpp b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/logging.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/logging.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/logging.h b/src/coreclr/tools/superpmi/superpmi-shared/logging.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/logging.h rename to src/coreclr/tools/superpmi/superpmi-shared/logging.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h rename to src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.cpp b/src/coreclr/tools/superpmi/superpmi-shared/mclist.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/mclist.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.h b/src/coreclr/tools/superpmi/superpmi-shared/mclist.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.h rename to src/coreclr/tools/superpmi/superpmi-shared/mclist.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.h rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.h rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/runtimedetails.h b/src/coreclr/tools/superpmi/superpmi-shared/runtimedetails.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/runtimedetails.h rename to src/coreclr/tools/superpmi/superpmi-shared/runtimedetails.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.cpp b/src/coreclr/tools/superpmi/superpmi-shared/simpletimer.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/simpletimer.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.h b/src/coreclr/tools/superpmi/superpmi-shared/simpletimer.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.h rename to src/coreclr/tools/superpmi/superpmi-shared/simpletimer.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h rename to src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h b/src/coreclr/tools/superpmi/superpmi-shared/spmirecordhelper.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h rename to src/coreclr/tools/superpmi/superpmi-shared/spmirecordhelper.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.h b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.h rename to src/coreclr/tools/superpmi/superpmi-shared/spmiutil.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h b/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h rename to src/coreclr/tools/superpmi/superpmi-shared/standardpch.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.cpp b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/tocfile.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.h b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.h rename to src/coreclr/tools/superpmi/superpmi-shared/tocfile.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.cpp b/src/coreclr/tools/superpmi/superpmi-shared/typeutils.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.cpp rename to src/coreclr/tools/superpmi/superpmi-shared/typeutils.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.h b/src/coreclr/tools/superpmi/superpmi-shared/typeutils.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.h rename to src/coreclr/tools/superpmi/superpmi-shared/typeutils.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt similarity index 95% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt rename to src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt index 1eb640c4cb9c0..5090fd411dfc9 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt @@ -61,4 +61,4 @@ else() ) endif(CLR_CMAKE_HOST_UNIX) -install_clr(TARGETS superpmi-shim-collector DESTINATIONS .) +install_clr(TARGETS superpmi-shim-collector DESTINATIONS . COMPONENT spmi) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.h rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.h rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.h rename to src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.def b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.def similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.def rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.def diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.h rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt similarity index 96% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt rename to src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt index 602a6751b02da..403841d95c8ed 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt @@ -63,4 +63,4 @@ else() ) endif(CLR_CMAKE_HOST_UNIX) -install_clr(TARGETS superpmi-shim-counter DESTINATIONS .) +install_clr(TARGETS superpmi-shim-counter DESTINATIONS . COMPONENT spmi) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.h rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.h rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.h rename to src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.h rename to src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.def b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.def similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.def rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.def diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.h rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt similarity index 96% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt rename to src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt index b6f4d52ea4cab..e1c168ef9d9dd 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt @@ -62,4 +62,4 @@ else() ) endif(CLR_CMAKE_HOST_UNIX) -install_clr(TARGETS superpmi-shim-simple DESTINATIONS .) +install_clr(TARGETS superpmi-shim-simple DESTINATIONS . COMPONENT spmi) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.h rename to src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.def similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.def diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi/CMakeLists.txt similarity index 96% rename from src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt rename to src/coreclr/tools/superpmi/superpmi/CMakeLists.txt index 4827c195dc299..63237450898e3 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/superpmi/CMakeLists.txt @@ -64,4 +64,4 @@ else() ) endif(CLR_CMAKE_HOST_UNIX) -install_clr(TARGETS superpmi DESTINATIONS .) +install_clr(TARGETS superpmi DESTINATIONS . COMPONENT spmi) diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp b/src/coreclr/tools/superpmi/superpmi/commandline.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp rename to src/coreclr/tools/superpmi/superpmi/commandline.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.h b/src/coreclr/tools/superpmi/superpmi/commandline.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/commandline.h rename to src/coreclr/tools/superpmi/superpmi/commandline.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/cycletimer.cpp b/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/cycletimer.cpp rename to src/coreclr/tools/superpmi/superpmi/cycletimer.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/cycletimer.h b/src/coreclr/tools/superpmi/superpmi/cycletimer.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/cycletimer.h rename to src/coreclr/tools/superpmi/superpmi/cycletimer.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp rename to src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.h rename to src/coreclr/tools/superpmi/superpmi/icorjitinfo.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.cpp b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.cpp rename to src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.h b/src/coreclr/tools/superpmi/superpmi/jitdebugger.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.h rename to src/coreclr/tools/superpmi/superpmi/jitdebugger.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jithost.cpp b/src/coreclr/tools/superpmi/superpmi/jithost.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jithost.cpp rename to src/coreclr/tools/superpmi/superpmi/jithost.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jithost.h b/src/coreclr/tools/superpmi/superpmi/jithost.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jithost.h rename to src/coreclr/tools/superpmi/superpmi/jithost.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp rename to src/coreclr/tools/superpmi/superpmi/jitinstance.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h b/src/coreclr/tools/superpmi/superpmi/jitinstance.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h rename to src/coreclr/tools/superpmi/superpmi/jitinstance.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.cpp b/src/coreclr/tools/superpmi/superpmi/methodstatsemitter.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.cpp rename to src/coreclr/tools/superpmi/superpmi/methodstatsemitter.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h b/src/coreclr/tools/superpmi/superpmi/methodstatsemitter.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h rename to src/coreclr/tools/superpmi/superpmi/methodstatsemitter.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp b/src/coreclr/tools/superpmi/superpmi/metricssummary.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp rename to src/coreclr/tools/superpmi/superpmi/metricssummary.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h b/src/coreclr/tools/superpmi/superpmi/metricssummary.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h rename to src/coreclr/tools/superpmi/superpmi/metricssummary.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/neardiffer.cpp b/src/coreclr/tools/superpmi/superpmi/neardiffer.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/neardiffer.cpp rename to src/coreclr/tools/superpmi/superpmi/neardiffer.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/neardiffer.h b/src/coreclr/tools/superpmi/superpmi/neardiffer.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/neardiffer.h rename to src/coreclr/tools/superpmi/superpmi/neardiffer.h diff --git a/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp rename to src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp rename to src/coreclr/tools/superpmi/superpmi/superpmi.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.h b/src/coreclr/tools/superpmi/superpmi/superpmi.h similarity index 100% rename from src/coreclr/ToolBox/superpmi/superpmi/superpmi.h rename to src/coreclr/tools/superpmi/superpmi/superpmi.h diff --git a/src/coreclr/utilcode/securitywrapper.cpp b/src/coreclr/utilcode/securitywrapper.cpp index 8f7ac38f444a0..67b462bf00a26 100644 --- a/src/coreclr/utilcode/securitywrapper.cpp +++ b/src/coreclr/utilcode/securitywrapper.cpp @@ -206,117 +206,6 @@ HRESULT GetSidFromProcessWorker(DWORD dwProcessId, SidType sidType, PSID *ppSid) return hr; } -#ifndef FEATURE_CORESYSTEM -//----------------------------------------------------------------------------- -// get the sid of a given process id using WTSEnumerateProcesses -// @todo: Make this function fail when WTSEnumerateProcesses is not available -// Or is it always available on all of our platform? -// -// Caller remember to call delete on *ppSid -//----------------------------------------------------------------------------- -HRESULT GetSidFromProcessEXWorker(DWORD dwProcessId, PSID *ppSid) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - PRECONDITION(CheckPointer(ppSid)); - } - CONTRACTL_END; - - HRESULT hr = S_OK; - PWTS_PROCESS_INFOW rgProcessInfo = NULL; - DWORD dwNumProcesses; - DWORD iProc; - DWORD cbSid; - PSID pSid = NULL; - - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx: 0x%08x\n", - dwProcessId)); - - - *ppSid = NULL; - if (!WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, // use local server - 0, // Reserved must be zero - 1, // version must be 1 - &rgProcessInfo, // Receives pointer to process list - &dwNumProcesses)) - { - hr = HRESULT_FROM_GetLastError(); - goto exit; - } - - for (iProc = 0; iProc < dwNumProcesses; iProc++) - { - - if (rgProcessInfo[iProc].ProcessId == dwProcessId) - { - if (rgProcessInfo[iProc].pUserSid == NULL) - { - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx is not able to retrieve SID\n")); - - // if there is no Sid for the user, don't call GetLengthSid. - // It will crash! It is ok to return E_FAIL as caller will ignore it. - hr = E_FAIL; - goto exit; - } - cbSid = GetLengthSid(rgProcessInfo[iProc].pUserSid); - pSid = new (nothrow) BYTE[cbSid]; - if (pSid == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - if (!CopySid(cbSid, pSid, rgProcessInfo[iProc].pUserSid)) - { - hr = HRESULT_FROM_GetLastError(); - } - else - { - // We are done. Go to exit - hr = S_OK; - } - } - - // we already find a match. Even if we fail from memory allocation of CopySid, still - // goto exit. - goto exit; - } - } - - // Walk the whole list and cannot find the matching PID - // Find a better error code. - hr = E_FAIL; - -exit: - - if (rgProcessInfo) - { - WTSFreeMemory(rgProcessInfo); - } - - if (FAILED(hr) && pSid) - { - delete [] (reinterpret_cast(pSid)); - } - - if (SUCCEEDED(hr)) - { - _ASSERTE(pSid); - *ppSid = pSid; - } - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx return hr : 0x%08x\n", - hr)); - - - return hr; -} -#endif // !FEATURE_CORESYSTEM - //----------------------------------------------------------------------------- // The functions below initialize this SidBuffer instance with a Sid from // the token of the specified process. The first pair use the OWNER sid from @@ -361,12 +250,6 @@ HRESULT SidBuffer::InitFromProcessNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kOwnerSid, (PSID *) &m_pBuffer); -#ifndef FEATURE_CORESYSTEM - if (FAILED(hr)) - { - hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); - } -#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; @@ -526,12 +409,6 @@ HRESULT SidBuffer::InitFromProcessUserNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kUserSid, (PSID *) &m_pBuffer); -#ifndef FEATURE_CORESYSTEM - if (FAILED(hr)) - { - hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); - } -#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index 6b5f7af901ac1..9ab6790efb3f6 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -2137,11 +2137,7 @@ void SString::PVPrintf(const WCHAR *format, va_list args) { // First, try to use the existing buffer va_copy(ap, args); -#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); -#else - int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); -#endif va_end(ap); if (result >= 0) { @@ -2171,11 +2167,7 @@ void SString::PVPrintf(const WCHAR *format, va_list args) errno = 0; va_copy(ap, args); -#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); -#else - int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); -#endif va_end(ap); if (result >= 0) diff --git a/src/coreclr/utilcode/stresslog.cpp b/src/coreclr/utilcode/stresslog.cpp index a9e36516b6dcd..5d13b2ec7695c 100644 --- a/src/coreclr/utilcode/stresslog.cpp +++ b/src/coreclr/utilcode/stresslog.cpp @@ -345,6 +345,12 @@ void StressLog::AddModule(uint8_t* moduleBase) } #endif //MEMORY_MAPPED_STRESSLOG theLog.modules[moduleIndex].size = PAL_CopyModuleData(moduleBase, destination, destination_end); +#ifdef MEMORY_MAPPED_STRESSLOG + if (hdr != nullptr) + { + hdr->modules[moduleIndex].size = theLog.modules[moduleIndex].size; + } +#endif //MEMORY_MAPPED_STRESSLOG #endif //HOST_WINDOWS } @@ -884,7 +890,6 @@ void StressLog::LogMsg(unsigned level, unsigned facility, const StressLogMsg &ms if (InlinedStressLogOn(facility, level)) { -#ifdef HOST_WINDOWS // On Linux, this cast: (va_list)msg.m_args gives a compile error ThreadStressLog* msgs = t_pCurrentThreadLog; if (msgs == 0) @@ -894,7 +899,15 @@ void StressLog::LogMsg(unsigned level, unsigned facility, const StressLogMsg &ms if (msgs == 0) return; } +#ifdef HOST_WINDOWS + // On Linux, this cast: (va_list)msg.m_args gives a compile error msgs->LogMsg(facility, msg.m_cArgs, msg.m_format, (va_list)msg.m_args); +#else + msgs->LogMsg(facility, msg.m_cArgs, msg.m_format, + msg.m_args[0], msg.m_args[1], msg.m_args[2], msg.m_args[3], + msg.m_args[4], msg.m_args[5], msg.m_args[6], msg.m_args[7], + msg.m_args[8], msg.m_args[9], msg.m_args[10], msg.m_args[11], + msg.m_args[12], msg.m_args[13], msg.m_args[14], msg.m_args[15]); #endif //HOST_WINDOWS } diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index afc0c057d3ee5..ee90f9db6c538 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -19,66 +19,12 @@ #include "corinfo.h" #include "volatile.h" #include "mdfileformat.h" +#include #ifndef DACCESS_COMPILE UINT32 g_nClrInstanceId = 0; #endif //!DACCESS_COMPILE -//********** Code. ************************************************************ - -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -extern WinRTStatusEnum gWinRTStatus = WINRT_STATUS_UNINITED; -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM - -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -//------------------------------------------------------------------------------ -// -// Attempt to detect the presense of Windows Runtime support on the current OS. -// Our algorithm to do this is to ensure that: -// 1. combase.dll exists -// 2. combase.dll contains a RoInitialize export -// - -void InitWinRTStatus() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - WinRTStatusEnum winRTStatus = WINRT_STATUS_UNSUPPORTED; - - const WCHAR wszComBaseDll[] = W("\\combase.dll"); - const SIZE_T cchComBaseDll = ARRAY_SIZE(wszComBaseDll); - - WCHAR wszComBasePath[MAX_LONGPATH + 1]; - const SIZE_T cchComBasePath = ARRAY_SIZE(wszComBasePath); - - ZeroMemory(wszComBasePath, cchComBasePath * sizeof(wszComBasePath[0])); - - UINT cchSystemDirectory = WszGetSystemDirectory(wszComBasePath, MAX_LONGPATH); - - // Make sure that we're only probing in the system directory. If we can't find the system directory, or - // we find it but combase.dll doesn't fit into it, we'll fall back to a safe default of saying that WinRT - // is simply not present. - if (cchSystemDirectory > 0 && cchComBasePath - cchSystemDirectory >= cchComBaseDll) - { - if (wcscat_s(wszComBasePath, wszComBaseDll) == 0) - { - HModuleHolder hComBase(WszLoadLibrary(wszComBasePath)); - if (hComBase != NULL) - { - FARPROC activateInstace = GetProcAddress(hComBase, "RoInitialize"); - if (activateInstace != NULL) - { - winRTStatus = WINRT_STATUS_SUPPORTED; - } - } - } - } - - gWinRTStatus = winRTStatus; -} -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM //***************************************************************************** // Convert a string of hex digits into a hex value of the specified # of bytes. //***************************************************************************** @@ -827,7 +773,7 @@ DWORD LCM(DWORD u, DWORD v) CONTRACTL_END; #if !defined(FEATURE_REDHAWK) && (defined(TARGET_AMD64) || defined(TARGET_ARM64)) - BOOL enableGCCPUGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCCpuGroup) != 0; + BOOL enableGCCPUGroups = Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup); if (!enableGCCPUGroups) return; @@ -1805,9 +1751,7 @@ HRESULT validateOneArg( // Validate the referenced type. if(FAILED(hr = validateOneArg(tk, pSig, pulNSentinels, pImport, FALSE))) IfFailGo(hr); break; - case ELEMENT_TYPE_BYREF: //fallthru - if(TypeFromToken(tk)==mdtFieldDef) IfFailGo(VLDTR_E_SIG_BYREFINFIELD); - FALLTHROUGH; + case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_PINNED: case ELEMENT_TYPE_SZARRAY: // Validate the referenced type. diff --git a/src/coreclr/utilcode/utilmessagebox.cpp b/src/coreclr/utilcode/utilmessagebox.cpp index 5a8b1f5e2d69b..8ae1d046169e7 100644 --- a/src/coreclr/utilcode/utilmessagebox.cpp +++ b/src/coreclr/utilcode/utilmessagebox.cpp @@ -17,12 +17,6 @@ #include "clrversion.h" #include "../dlls/mscorrc/resource.h" #include "ex.h" -#if !defined(FEATURE_CORESYSTEM) -#undef NTDDI_VERSION -#define NTDDI_VERSION NTDDI_WIN7 -#include "commctrl.h" -#endif - BOOL ShouldDisplayMsgBoxOnCriticalFailure() { @@ -193,48 +187,46 @@ int UtilMessageBoxNonLocalizedVA( } #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) - // If the current process isn't interactive (a service for example), then we report the message - // in the event log and via OutputDebugString. +#ifdef HOST_UNIX + // For non-interactive processes, we report the message in the event log and via OutputDebugString. // // We may still however attempt to display the message box if the MB_SERVICE_NOTIFICATION // message box style was specified. - if (!RunningInteractive()) + StackSString message; + + message.Printf(W(".NET Runtime version : %s - "), CLR_PRODUCT_VERSION_L); + if (lpTitle) + message.Append(lpTitle); + if (!formattedMessage.IsEmpty()) + message.Append(formattedMessage); + + ClrReportEvent(W(".NET Runtime"), + EVENTLOG_ERROR_TYPE, // event type + 0, // category zero + 1024, // event identifier + NULL, // no user security identifier + message.GetUnicode()); + + if(lpTitle != NULL) + WszOutputDebugString(lpTitle); + if(!formattedMessage.IsEmpty()) + WszOutputDebugString(formattedMessage); + + // If we are running as a service and displayForNonInteractive is FALSE then IDABORT is + // the best value to return as it will most likely cause callers of this API to abort the process. + // This is the right thing to do since attaching a debugger doesn't make much sense when the process isn't + // running in interactive mode. + if(!displayForNonInteractive) { - StackSString message; - - message.Printf(W(".NET Runtime version : %s - "), CLR_PRODUCT_VERSION_L); - if (lpTitle) - message.Append(lpTitle); - if (!formattedMessage.IsEmpty()) - message.Append(formattedMessage); - - ClrReportEvent(W(".NET Runtime"), - EVENTLOG_ERROR_TYPE, // event type - 0, // category zero - 1024, // event identifier - NULL, // no user security identifier - message.GetUnicode()); - - if(lpTitle != NULL) - WszOutputDebugString(lpTitle); - if(!formattedMessage.IsEmpty()) - WszOutputDebugString(formattedMessage); - - // If we are running as a service and displayForNonInteractive is FALSE then IDABORT is - // the best value to return as it will most likely cause callers of this API to abort the process. - // This is the right thing to do since attaching a debugger doesn't make much sense when the process isn't - // running in interactive mode. - if(!displayForNonInteractive) - { - fDisplayMsgBox = FALSE; - result = IDABORT; - } - else - { - // Include in the MB_DEFAULT_DESKTOP_ONLY style. - uType |= MB_DEFAULT_DESKTOP_ONLY; - } + fDisplayMsgBox = FALSE; + result = IDABORT; + } + else + { + // Include in the MB_DEFAULT_DESKTOP_ONLY style. + uType |= MB_DEFAULT_DESKTOP_ONLY; } +#endif // HOST_UNIX #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) if (fDisplayMsgBox) diff --git a/src/coreclr/utilcode/winfix.cpp b/src/coreclr/utilcode/winfix.cpp index d572c8edb26ef..c6733767e77bf 100644 --- a/src/coreclr/utilcode/winfix.cpp +++ b/src/coreclr/utilcode/winfix.cpp @@ -217,39 +217,6 @@ void EnsureCharSetInfoInitialized() return; } - -// Running with an interactive workstation. -BOOL RunningInteractive() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_FORBID_FAULT; - - static int fInteractive = -1; - if (fInteractive != -1) - return fInteractive != 0; - -#if !defined(FEATURE_CORESYSTEM) - HWINSTA hwinsta = NULL; - - if ((hwinsta = GetProcessWindowStation() ) != NULL) - { - DWORD lengthNeeded; - USEROBJECTFLAGS flags; - - if (GetUserObjectInformationW (hwinsta, UOI_FLAGS, &flags, sizeof(flags), &lengthNeeded)) - { - if ((flags.dwFlags & WSF_VISIBLE) == 0) - fInteractive = 0; - } - } -#endif // !FEATURE_CORESYSTEM - - if (fInteractive != 0) - fInteractive = 1; - - return fInteractive != 0; -} - typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription); extern pfnSetThreadDescription g_pfnSetThreadDescription; diff --git a/src/coreclr/vm/.vscode/c_cpp_properties.json b/src/coreclr/vm/.vscode/c_cpp_properties.json index 3e0fa37196a65..16279d8db9e74 100644 --- a/src/coreclr/vm/.vscode/c_cpp_properties.json +++ b/src/coreclr/vm/.vscode/c_cpp_properties.json @@ -50,7 +50,6 @@ "FEATURE_COMINTEROP_UNMANAGED_ACTIVATION", "FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION", "FEATURE_CORECLR", - "FEATURE_CORESYSTEM", "FEATURE_DATABREAKPOINT", "FEATURE_DEFAULT_INTERFACES", "FEATURE_EVENT_TRACE=1", diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 2f34d2c0ceaa1..08a5bb92a66ed 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -63,7 +63,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON debuginfostore.cpp decodemd.cpp disassembler.cpp - domainfile.cpp + domainassembly.cpp dynamicmethod.cpp ecall.cpp eedbginterfaceimpl.cpp @@ -161,8 +161,7 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON debuginfostore.h decodemd.h disassembler.h - domainfile.h - domainfile.inl + domainassembly.h dynamicmethod.h ecall.h eedbginterfaceimpl.h @@ -289,7 +288,6 @@ set(GC_HEADERS_DAC set(VM_SOURCES_WKS ${VM_SOURCES_DAC_AND_WKS_COMMON} appdomainnative.cpp - assemblyname.cpp assemblynative.cpp assemblyspec.cpp baseassemblyspec.cpp @@ -392,7 +390,6 @@ set(VM_HEADERS_WKS ${VM_HEADERS_DAC_AND_WKS_COMMON} ../inc/jithelpers.h appdomainnative.hpp - assemblyname.hpp assemblynative.hpp assemblyspec.hpp assemblyspecbase.h diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index 29b9dddfb7de4..33589c27bae39 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -415,8 +415,6 @@ extern "C" void setFPReturn(int fpSize, INT64 retVal); extern "C" void getFPReturn(int fpSize, INT64 *retval); -struct ComToManagedExRecord; // defined in cgencpu.cpp - #include struct DECLSPEC_ALIGN(8) UMEntryThunkCode { diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 0194f960809d9..80e22d4f7f209 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -11,7 +11,6 @@ #include "eeconfig.h" #include "gcheaputilities.h" #include "eventtrace.h" -#include "assemblyname.hpp" #include "eeprofinterfaces.h" #include "dbginterface.h" #ifndef DACCESS_COMPILE @@ -1322,10 +1321,10 @@ void SystemDomain::LoadBaseSystemClasses() // Only partially load the system assembly. Other parts of the code will want to access // the globals in this function before finishing the load. - m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetCurrentAssembly(); + m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetAssembly(); // Set up binder for CoreLib - CoreLibBinder::AttachModule(m_pSystemAssembly->GetManifestModule()); + CoreLibBinder::AttachModule(m_pSystemAssembly->GetModule()); // Load Object g_pObjectClass = CoreLibBinder::GetClass(CLASS__OBJECT); @@ -2174,7 +2173,7 @@ BOOL AppDomain::ContainsAssembly(Assembly * assem) while (i.Next(pDomainAssembly.This())) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly == assem) return TRUE; } @@ -2239,7 +2238,7 @@ DispIDCache* AppDomain::SetupRefDispIDCache() #endif // FEATURE_COMINTEROP -FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) +FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainAssembly *pDomainAssembly) { CONTRACTL { @@ -2252,7 +2251,7 @@ FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssemb } CONTRACTL_END; - NewHolder result(new FileLoadLock(pLock, pPEAssembly, pDomainFile)); + NewHolder result(new FileLoadLock(pLock, pPEAssembly, pDomainAssembly)); pLock->AddElement(result); result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel. @@ -2272,10 +2271,10 @@ FileLoadLock::~FileLoadLock() ((PEAssembly *) m_data)->Release(); } -DomainFile *FileLoadLock::GetDomainFile() +DomainAssembly *FileLoadLock::GetDomainAssembly() { LIMITED_METHOD_CONTRACT; - return m_pDomainFile; + return m_pDomainAssembly; } FileLoadLevel FileLoadLock::GetLoadLevel() @@ -2357,7 +2356,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) if (level > m_level) { // Must complete each level in turn, unless we have an error - CONSISTENCY_CHECK(m_pDomainFile->IsError() || (level == (m_level+1))); + CONSISTENCY_CHECK(m_pDomainAssembly->IsError() || (level == (m_level+1))); // Remove the lock from the list if the load is completed if (level >= FILE_ACTIVE) { @@ -2371,18 +2370,18 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) m_pList->Unlink(this); _ASSERTE(fDbgOnly_SuccessfulUnlink); - m_pDomainFile->ClearLoading(); + m_pDomainAssembly->ClearLoading(); - CONSISTENCY_CHECK(m_dwRefCount >= 2); // Caller (LoadDomainFile) should have 1 refcount and m_pList should have another which was acquired in FileLoadLock::Create. + CONSISTENCY_CHECK(m_dwRefCount >= 2); // Caller (LoadDomainAssembly) should have 1 refcount and m_pList should have another which was acquired in FileLoadLock::Create. m_level = (FileLoadLevel)level; // Dev11 bug 236344 // In AppDomain::IsLoading, if the lock is taken on m_pList and then FindFileLock returns NULL, - // we depend on the DomainFile's load level being up to date. Hence we must update the load + // we depend on the DomainAssembly's load level being up to date. Hence we must update the load // level while the m_pList lock is held. if (success) - m_pDomainFile->SetLoadLevel(level); + m_pDomainAssembly->SetLoadLevel(level); } @@ -2394,7 +2393,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) m_level = (FileLoadLevel)level; if (success) - m_pDomainFile->SetLoadLevel(level); + m_pDomainAssembly->SetLoadLevel(level); } #ifndef DACCESS_COMPILE @@ -2405,7 +2404,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) case FILE_LOAD_DELIVER_EVENTS: case FILE_LOADED: case FILE_ACTIVE: // The timing of stress logs is not critical, so even for the FILE_ACTIVE stage we need not do it while the m_pList lock is held. - STRESS_LOG3(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainFile %p - success = %i\n", fileLoadLevelName[level], m_pDomainFile, success); + STRESS_LOG3(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainAssembly %p - success = %i\n", fileLoadLevelName[level], m_pDomainAssembly, success); break; default: break; @@ -2434,9 +2433,9 @@ void FileLoadLock::SetError(Exception *ex) m_cachedHR = ex->GetHR(); LOG((LF_LOADER, LL_WARNING, "LOADER: %x:***%s*\t!!!Non-transient error 0x%x\n", - m_pDomainFile->GetAppDomain(), m_pDomainFile->GetSimpleName(), m_cachedHR)); + m_pDomainAssembly->GetAppDomain(), m_pDomainAssembly->GetSimpleName(), m_cachedHR)); - m_pDomainFile->SetError(ex); + m_pDomainAssembly->SetError(ex); CompleteLoadLevel(FILE_ACTIVE, FALSE); } @@ -2464,10 +2463,10 @@ UINT32 FileLoadLock::Release() return count; } -FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) +FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainAssembly *pDomainAssembly) : ListLockEntry(pLock, pPEAssembly, "File load lock"), m_level((FileLoadLevel) (FILE_LOAD_CREATE)), - m_pDomainFile(pDomainFile), + m_pDomainAssembly(pDomainAssembly), m_cachedHR(S_OK) { WRAPPER_NO_CONTRACT; @@ -2522,26 +2521,6 @@ void AppDomain::LoadSystemAssemblies() LoadAssembly(NULL, SystemDomain::System()->SystemPEAssembly(), FILE_ACTIVE); } -FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END - - LoadLockHolder lock(this); - - FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); - - if (pLockEntry == NULL) - return pFile->GetLoadLevel(); - else - return pLockEntry->GetLoadLevel(); -} - // This checks if the thread has initiated (or completed) loading at the given level. A false guarantees that // (a) The current thread (or a thread blocking on the current thread) has not started loading the file // at the given level, and @@ -2555,7 +2534,7 @@ FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) // thread has completed the load step. // -BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level) +BOOL AppDomain::IsLoading(DomainAssembly *pFile, FileLoadLevel level) { // Cheap out if (pFile->GetLoadLevel() < level) @@ -2592,7 +2571,7 @@ BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level) // CheckLoading is a weaker form of IsLoading, which will not block on // other threads waiting for their status. This is appropriate for asserts. -CHECK AppDomain::CheckLoading(DomainFile *pFile, FileLoadLevel level) +CHECK AppDomain::CheckLoading(DomainAssembly *pFile, FileLoadLevel level) { // Cheap out if (pFile->GetLoadLevel() < level) @@ -2626,7 +2605,7 @@ CHECK AppDomain::CheckCanLoadTypes(Assembly *pAssembly) MODE_ANY; } CONTRACTL_END; - CHECK_MSG(CheckValidModule(pAssembly->GetManifestModule()), + CHECK_MSG(CheckValidModule(pAssembly->GetModule()), "Type loading can occur only when executing in the assembly's app domain"); CHECK_OK; } @@ -2658,7 +2637,7 @@ CHECK AppDomain::CheckCanExecuteManagedCode(MethodDesc* pMD) #endif // !DACCESS_COMPILE -void AppDomain::LoadDomainFile(DomainFile *pFile, +void AppDomain::LoadDomainAssembly(DomainAssembly *pFile, FileLoadLevel targetLevel) { CONTRACTL @@ -2698,7 +2677,7 @@ void AppDomain::LoadDomainFile(DomainFile *pFile, lock.Release(); - LoadDomainFile(pLockEntry, targetLevel); + LoadDomainAssembly(pLockEntry, targetLevel); } #else // DACCESS_COMPILE @@ -2875,12 +2854,12 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (result == NULL) { - // We pass our ref on fileLock to LoadDomainFile to release. + // We pass our ref on fileLock to LoadDomainAssembly to release. // Note that if we throw here, we will poison fileLock with an error condition, // so it will not be removed until app domain unload. So there is no need // to release our ref count. - result = (DomainAssembly *)LoadDomainFile(fileLock, targetLevel); + result = (DomainAssembly *)LoadDomainAssembly(fileLock, targetLevel); } else { @@ -2889,20 +2868,12 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (registerNewAssembly) { - pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetCurrentAssembly()); + pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetAssembly()); } } else result->EnsureLoadLevel(targetLevel); - // Malformed metadata may contain a Module reference to what is actually - // an Assembly. In this case we need to throw an exception, since returning - // a DomainModule as a DomainAssembly is a type safety violation. - if (!result->IsAssembly()) - { - ThrowHR(COR_E_ASSEMBLYEXPECTED); - } - // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity if (pIdentity == NULL) { @@ -2918,28 +2889,20 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, RETURN result; } // AppDomain::LoadDomainAssembly - -struct LoadFileArgs +DomainAssembly *AppDomain::LoadDomainAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel) { - FileLoadLock *pLock; - FileLoadLevel targetLevel; - DomainFile *result; -}; - -DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetLevel) -{ - CONTRACT(DomainFile *) + CONTRACT(DomainAssembly *) { STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pLock)); - PRECONDITION(pLock->GetDomainFile()->GetAppDomain() == this); + PRECONDITION(pLock->GetDomainAssembly()->GetAppDomain() == this); POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel() || RETVAL->GetLoadLevel() >= targetLevel); POSTCONDITION(RETVAL->CheckNoError(targetLevel)); } CONTRACT_END; - DomainFile *pFile = pLock->GetDomainFile(); + DomainAssembly *pFile = pLock->GetDomainAssembly(); // Make sure we release the lock on exit FileLoadLockRefHolder lockRef(pLock); @@ -3034,7 +2997,7 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL // lower level. In such a case, we throw an exception which transiently fails the current // load, since it is likely we have not satisfied the caller. // (An alternate, and possibly preferable, strategy here would be for all callers to explicitly - // identify the minimum load level acceptable via CheckLoadDomainFile and throw from there.) + // specify the minimum load level acceptable and throw if not reached.) pFile->RequireLoadLevel((FileLoadLevel)(immediateTargetLevel-1)); @@ -3042,7 +3005,7 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL RETURN pFile; } -void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder) +void AppDomain::TryIncrementalLoad(DomainAssembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder) { STANDARD_VM_CONTRACT; @@ -3056,7 +3019,7 @@ void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, F // Special case: for LoadLibrary, we cannot hold the lock during the // actual LoadLibrary call, because we might get a callback from _CorDllMain on any - // other thread. (Note that this requires DomainFile's LoadLibrary to be independently threadsafe.) + // other thread. (Note that this requires DomainAssembly's LoadLibrary to be independently threadsafe.) if (workLevel == FILE_LOAD_LOADLIBRARY) { @@ -3140,7 +3103,7 @@ CHECK AppDomain::CheckValidModule(Module * pModule) } CONTRACTL_END; - if (pModule->GetDomainFile() != NULL) + if (pModule->GetDomainAssembly() != NULL) CHECK_OK; CHECK_OK; @@ -3827,7 +3790,7 @@ PEAssembly *AppDomain::TryResolveAssemblyUsingEvent(AssemblySpec *pSpec) Assembly *pAssembly = RaiseAssemblyResolveEvent(pSpec); if (pAssembly != nullptr) { - PEAssembly* pPEAssembly = pAssembly->GetManifestFile(); + PEAssembly* pPEAssembly = pAssembly->GetPEAssembly(); pPEAssembly->AddRef(); result = pPEAssembly; } @@ -4215,7 +4178,7 @@ DWORD DomainLocalModule::GetClassFlags(MethodTable* pMT, DWORD iClassIndex /*=(D } CONTRACTL_END; { - CONSISTENCY_CHECK(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + CONSISTENCY_CHECK(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); } if (pMT->IsDynamicStatics()) @@ -4246,7 +4209,7 @@ void DomainLocalModule::SetClassInitialized(MethodTable* pMT) } CONTRACTL_END; - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); _ASSERTE(!IsClassInitialized(pMT)); _ASSERTE(!IsClassInitError(pMT)); @@ -4258,7 +4221,7 @@ void DomainLocalModule::SetClassInitError(MethodTable* pMT) { WRAPPER_NO_CONTRACT; - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); SetClassFlags(pMT, ClassInitFlags::ERROR_FLAG); } @@ -4268,9 +4231,9 @@ void DomainLocalModule::SetClassFlags(MethodTable* pMT, DWORD dwFlags) CONTRACTL { THROWS; GC_TRIGGERS; - PRECONDITION(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + PRECONDITION(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; if (pMT->IsDynamicStatics()) @@ -4295,7 +4258,7 @@ void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID) MODE_ANY; INJECT_FAULT(COMPlusThrowOM();); // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; @@ -4313,7 +4276,7 @@ void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID) DynamicClassInfo* pNewDynamicClassTable; pNewDynamicClassTable = (DynamicClassInfo*) - (void*)GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem( + (void*)GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem( S_SIZE_T(sizeof(DynamicClassInfo)) * S_SIZE_T(aDynamicEntries)); memcpy(pNewDynamicClassTable, m_pDynamicClassTable, sizeof(DynamicClassInfo) * m_aDynamicEntries); @@ -4337,13 +4300,13 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) THROWS; GC_TRIGGERS; // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; _ASSERTE(!pMT->ContainsGenericVariables()); _ASSERTE(!pMT->IsSharedByGenericInstantiations()); - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); _ASSERTE(pMT->IsDynamicStatics()); DWORD dynamicEntryIDIndex = pMT->GetModuleDynamicEntryID(); @@ -4368,7 +4331,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) { if (pDynamicStatics == NULL) { - LoaderHeap * pLoaderAllocator = GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap(); + LoaderHeap * pLoaderAllocator = GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap(); if (pMT->Collectible()) { @@ -4407,7 +4370,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) else #endif nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwStaticBytes); - ((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray); + ((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray); GCPROTECT_END(); } if (dwNumHandleStatics > 0) @@ -4423,7 +4386,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) OBJECTREF gcStaticsArray = NULL; GCPROTECT_BEGIN(gcStaticsArray); gcStaticsArray = AllocateObjectArray(dwNumHandleStatics, g_pObjectClass); - ((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray); + ((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray); GCPROTECT_END(); } } @@ -4448,7 +4411,7 @@ void DomainLocalModule::PopulateClass(MethodTable *pMT) if (!IsClassAllocated(pMT, iClassIndex)) { - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); if (!IsClassAllocated(pMT, iClassIndex)) { @@ -4903,7 +4866,7 @@ AppDomain::AssemblyIterator::Next_Unlocked( // Un-tenured collectible assemblies should not be returned. (This can only happen in a brief // window during collectible assembly creation. No thread should need to have a pointer // to the just allocated DomainAssembly at this stage.) - if (!pDomainAssembly->GetAssembly()->GetManifestModule()->IsTenured()) + if (!pDomainAssembly->GetAssembly()->GetModule()->IsTenured()) { continue; // reject } @@ -5186,9 +5149,9 @@ DomainLocalModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // sizeof(DomainLocalModule) == 0x28 DAC_ENUM_DTHIS(); - if (m_pDomainFile.IsValid()) + if (m_pDomainAssembly.IsValid()) { - m_pDomainFile->EnumMemoryRegions(flags); + m_pDomainAssembly->EnumMemoryRegions(flags); } if (m_pDynamicClassTable.Load().IsValid()) diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index a369823a53937..fbe728ff7e1c0 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -21,7 +21,7 @@ #include "arraylist.h" #include "comreflectioncache.hpp" #include "comutilnative.h" -#include "domainfile.h" +#include "domainassembly.h" #include "fptrstubs.h" #include "gcheaputilities.h" #include "gchandleutilities.h" @@ -201,18 +201,18 @@ struct DomainLocalModule static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); } static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); } - inline DomainFile* GetDomainFile() + inline DomainAssembly* GetDomainAssembly() { LIMITED_METHOD_CONTRACT SUPPORTS_DAC; - return m_pDomainFile; + return m_pDomainAssembly; } #ifndef DACCESS_COMPILE - inline void SetDomainFile(DomainFile* pDomainFile) + inline void SetDomainAssembly(DomainAssembly* pDomainAssembly) { LIMITED_METHOD_CONTRACT - m_pDomainFile = pDomainFile; + m_pDomainAssembly = pDomainAssembly; } #endif @@ -236,7 +236,7 @@ struct DomainLocalModule if (pMT->IsDynamicStatics()) { - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator()); } else @@ -252,7 +252,7 @@ struct DomainLocalModule if (pMT->IsDynamicStatics()) { - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator()); } else @@ -403,7 +403,7 @@ struct DomainLocalModule FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID) { DWORD rid = (DWORD)(dwClassDomainID) + 1; - TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef)); + TypeHandle th = GetDomainAssembly()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef)); _ASSERTE(!th.IsNull()); MethodTable * pMT = th.AsMethodTable(); PREFIX_ASSUME(pMT != NULL); @@ -416,7 +416,7 @@ struct DomainLocalModule void SetClassFlags(MethodTable* pMT, DWORD dwFlags); DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex); - PTR_DomainFile m_pDomainFile; + PTR_DomainAssembly m_pDomainAssembly; VolatilePtr m_pDynamicClassTable; // used for generics and reflection.emit in memory Volatile m_aDynamicEntries; // number of entries in dynamic table VolatilePtr m_pADThunkTable; @@ -747,7 +747,7 @@ typedef PEFileListLock::Holder PEFileListLockHolder; // Loading infrastructure: // -// a DomainFile is a file being loaded. Files are loaded in layers to enable loading in the +// a DomainAssembly is a file being loaded. Files are loaded in layers to enable loading in the // presence of dependency loops. // // FileLoadLevel describes the various levels available. These are implemented slightly @@ -773,14 +773,14 @@ class FileLoadLock : public ListLockEntry { private: FileLoadLevel m_level; - DomainFile *m_pDomainFile; + DomainAssembly *m_pDomainAssembly; HRESULT m_cachedHR; public: - static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); + static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainAssembly *pDomainAssembly); ~FileLoadLock(); - DomainFile *GetDomainFile(); + DomainAssembly *GetDomainAssembly(); FileLoadLevel GetLoadLevel(); // CanAcquire will return FALSE if Acquire will definitely not take the lock due @@ -807,7 +807,7 @@ class FileLoadLock : public ListLockEntry private: - FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); + FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainAssembly *pDomainAssembly); static void HolderLeave(FileLoadLock *pThis); @@ -1307,7 +1307,7 @@ enum AssemblyIterationFlags // (all m_level values) kIncludeAvailableToProfilers = 0x00000020, // include assemblies available to profilers - // See comment at code:DomainFile::IsAvailableToProfilers + // See comment at code:DomainAssembly::IsAvailableToProfilers // Execution / introspection flags kIncludeExecution = 0x00000004, // include assemblies that are loaded for execution only @@ -1797,13 +1797,12 @@ class AppDomain : public BaseDomain CHECK CheckCanLoadTypes(Assembly *pAssembly); CHECK CheckCanExecuteManagedCode(MethodDesc* pMD); - CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level); + CHECK CheckLoading(DomainAssembly *pFile, FileLoadLevel level); - FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile); - BOOL IsLoading(DomainFile *pFile, FileLoadLevel level); + BOOL IsLoading(DomainAssembly *pFile, FileLoadLevel level); static FileLoadLevel GetThreadFileLoadLevel(); - void LoadDomainFile(DomainFile *pFile, + void LoadDomainAssembly(DomainAssembly *pFile, FileLoadLevel targetLevel); enum FindAssemblyOptions @@ -1839,10 +1838,10 @@ class AppDomain : public BaseDomain // private: void LoadSystemAssemblies(); - DomainFile *LoadDomainFile(FileLoadLock *pLock, + DomainAssembly *LoadDomainAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel); - void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder); + void TryIncrementalLoad(DomainAssembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder); #ifndef DACCESS_COMPILE // needs AssemblySpec @@ -2453,7 +2452,7 @@ class SystemDomain : public BaseDomain { WRAPPER_NO_CONTRACT; - return SystemAssembly()->GetManifestModule(); + return SystemAssembly()->GetModule(); } static BOOL IsSystemLoaded() @@ -2580,7 +2579,7 @@ class SystemDomain : public BaseDomain // Or, it might be the location of CoreLib if (System()->SystemAssembly() != NULL - && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath())) + && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetPEAssembly()->GetPath())) return TRUE; return FALSE; diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index 7d8b3c7dd88b2..e7725cd16e63b 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -551,152 +551,6 @@ LOCAL_LABEL(LNullThis): LEAF_END SinglecastDelegateInvokeStub, _TEXT -#ifdef FEATURE_COMINTEROP - -#define ComCallPreStub_FrameSize (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) -#define ComCallPreStub_FirstStackAdjust (8 + SIZEOF__ArgumentRegisters + 2 * 8) // x8, reg args , fp & lr already pushed -#define ComCallPreStub_StackAlloc0 (ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust) -#define ComCallPreStub_StackAlloc1 (ComCallPreStub_StackAlloc0 + SIZEOF__FloatArgumentRegisters + 8)// 8 for ErrorReturn -#define ComCallPreStub_StackAlloc (ComCallPreStub_StackAlloc1 + (ComCallPreStub_StackAlloc1 & 8)) - -#define ComCallPreStub_FrameOffset (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust)) -#define ComCallPreStub_ErrorReturnOffset0 SIZEOF__FloatArgumentRegisters - -#define ComCallPreStub_FirstStackAdjust (ComCallPreStub_ErrorReturnOffset0 + (ComCallPreStub_ErrorReturnOffset0 & 8)) - -// ------------------------------------------------------------------ -// COM to CLR stub called the first time a particular method is invoked.// -// -// On entry: -// x12 : ComCallMethodDesc* provided by prepad thunk -// plus user arguments in registers and on the stack -// -// On exit: -// tail calls to real method -// -NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler - - // Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, -ComCallPreStub_FirstStackAdjust! - PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc - - SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) - - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 - - str x12, [sp, #(ComCallPreStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] - add x0, sp, #(ComCallPreStub_FrameOffset) - add x1, sp, #(ComCallPreStub_ErrorReturnOffset) - bl C_FUNC(ComPreStubWorker) - - cbz x0, LOCAL_LABEL(ComCallPreStub_ErrorExit) - - mov x12, x0 - - // pop the stack and restore original register state - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0 - RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) - - EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! - - // and tailcall to the actual method - EPILOG_BRANCH_REG x12 - -ComCallPreStub_ErrorExit - ldr x0, [sp, #(ComCallPreStub_ErrorReturnOffset)] // ErrorReturn - - // pop the stack - EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! - - EPILOG_RETURN - -NESTED_END ComCallPreStub, _TEXT - -// ------------------------------------------------------------------ -// COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker. -// -// On entry: -// x12 : ComCallMethodDesc* provided by prepad thunk -// plus user arguments in registers and on the stack -// -// On exit: -// Result in x0/d0 as per the real method being called -// - NESTED_ENTRY GenericComCallStub, _TEXT, NoHandler - - // Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, -GenericComCallStub_FirstStackAdjust! - PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc - - SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc) - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 - - str x12, [sp, #(GenericComCallStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] - add x1, sp, #GenericComCallStub_FrameOffset - bl C_FUNC(COMToCLRWorker) - - // pop the stack - EPILOG_STACK_FREE GenericComCallStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, GenericComCallStub_FirstStackAdjust! - - EPILOG_RETURN - - NESTED_END GenericComCallStub, _TEXT - -// ------------------------------------------------------------------ -// COM to CLR stub called from COMToCLRWorker that actually dispatches to the real managed method. -// -// On entry: -// x0 : dwStackSlots, count of argument stack slots to copy -// x1 : pFrame, ComMethodFrame pushed by GenericComCallStub above -// x2 : pTarget, address of code to call -// x3 : pSecretArg, hidden argument passed to target above in x12 -// x4 : pDangerousThis, managed 'this' reference -// -// On exit: -// Result in x0/d0 as per the real method being called -// - NESTED_ENTRY COMToCLRDispatchHelper, _TEXT,CallDescrWorkerUnwindFrameChainHandler - - PROLOG_SAVE_REG_PAIR fp, lr, -16! - - cbz x0, LOCAL_LABEL(COMToCLRDispatchHelper_RegSetup) - - add x9, x1, #SIZEOF__ComMethodFrame - add x9, x9, x0, LSL #3 -COMToCLRDispatchHelper_StackLoop - ldr x8, [x9, #-8]! - str x8, [sp, #-8]! - sub x0, x0, #1 - cbnz x0, LOCAL_LABEL(COMToCLRDispatchHelper_StackLoop) - -COMToCLRDispatchHelper_RegSetup - - RESTORE_FLOAT_ARGUMENT_REGISTERS x1, -1 * GenericComCallStub_FrameOffset - - mov lr, x2 - mov x12, x3 - - mov x0, x4 - - ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)] - ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)] - ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)] - ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 8)] - - ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)] - - blr lr - - EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG_PAIR fp, lr, 16! - EPILOG_RETURN - - NESTED_END COMToCLRDispatchHelper, _TEXT - -#endif // FEATURE_COMINTEROP // // x12 = UMEntryThunk* // @@ -1039,39 +893,6 @@ DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj #endif -#ifdef FEATURE_COMINTEROP - -// Function used by COM interop to get floating point return value (since it's not in the same -// register(s) as non-floating point values). -// -// On entry// -// x0 : size of the FP result (4 or 8 bytes) -// x1 : pointer to 64-bit buffer to receive result -// -// On exit: -// buffer pointed to by x1 on entry contains the float or double argument as appropriate -// -LEAF_ENTRY getFPReturn, _TEXT - str d0, [x1] -LEAF_END getFPReturn, _TEXT - -// ------------------------------------------------------------------ -// Function used by COM interop to set floating point return value (since it's not in the same -// register(s) as non-floating point values). -// -// On entry: -// x0 : size of the FP result (4 or 8 bytes) -// x1 : 32-bit or 64-bit FP result -// -// On exit: -// s0 : float result if x0 == 4 -// d0 : double result if x0 == 8 -// -LEAF_ENTRY setFPReturn, _TEXT - fmov d0, x1 -LEAF_END setFPReturn, _TEXT -#endif - // // JIT Static access helpers when coreclr host specifies single appdomain flag // diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 09c6ff22c2f83..83840af5b5138 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -17,9 +17,6 @@ #include "assembly.hpp" #include "appdomain.hpp" -#include "assemblyname.hpp" - - #include "eeprofinterfaces.h" #include "reflectclasswriter.h" @@ -126,14 +123,13 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pPEAssembly, DebuggerAssembl m_pDomain(pDomain), m_pClassLoader(NULL), m_pEntryPoint(NULL), - m_pManifest(NULL), - m_pManifestFile(clr::SafeAddRef(pPEAssembly)), + m_pModule(NULL), + m_pPEAssembly(clr::SafeAddRef(pPEAssembly)), m_pFriendAssemblyDescriptor(NULL), m_isDynamic(false), #ifdef FEATURE_COLLECTIBLE_TYPES m_isCollectible(fIsCollectible), #endif - m_nextAvailableModuleIndex(1), m_pLoaderAllocator(NULL), #ifdef FEATURE_COMINTEROP m_pITypeLib(NULL), @@ -189,7 +185,7 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat m_pClassLoader = new ClassLoader(this); m_pClassLoader->Init(pamTracker); - PEAssembly* pPEAssembly = GetManifestFile(); + PEAssembly* pPEAssembly = GetPEAssembly(); // "Module::Create" will initialize R2R support, if there is an R2R header. // make sure the PE is loaded or R2R will be disabled. @@ -197,17 +193,15 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat if (pPEAssembly->IsDynamic()) // manifest modules of dynamic assemblies are always transient - m_pManifest = ReflectionModule::Create(this, pPEAssembly, pamTracker, REFEMIT_MANIFEST_MODULE_NAME); + m_pModule = ReflectionModule::Create(this, pPEAssembly, pamTracker, REFEMIT_MANIFEST_MODULE_NAME); else - m_pManifest = Module::Create(this, mdFileNil, pPEAssembly, pamTracker); + m_pModule = Module::Create(this, mdFileNil, pPEAssembly, pamTracker); FastInterlockIncrement((LONG*)&g_cAssemblies); - PrepareModuleForAssembly(m_pManifest, pamTracker); - - CacheManifestFiles(); + PrepareModuleForAssembly(m_pModule, pamTracker); - if (!m_pManifest->IsReadyToRun()) + if (!m_pModule->IsReadyToRun()) CacheManifestExportedTypes(pamTracker); // We'll load the friend assembly information lazily. For the ngen case we should avoid @@ -231,7 +225,7 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat FAULT_FORBID(); //Cannot fail after this point. - PublishModuleIntoAssembly(m_pManifest); + PublishModuleIntoAssembly(m_pModule); return; // Explicit return to let you know you are NOT welcome to add code after the CANNOTTHROW/FAULT_FORBID expires } @@ -252,9 +246,9 @@ Assembly::~Assembly() if (m_pFriendAssemblyDescriptor != NULL) m_pFriendAssemblyDescriptor->Release(); - if (m_pManifestFile) + if (m_pPEAssembly) { - m_pManifestFile->Release(); + m_pPEAssembly->Release(); } #ifdef FEATURE_COMINTEROP @@ -334,7 +328,7 @@ void Assembly::Terminate( BOOL signalProfiler ) Assembly * Assembly::Create( BaseDomain * pDomain, - PEAssembly * pFile, + PEAssembly * pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker * pamTracker, @@ -342,7 +336,7 @@ Assembly * Assembly::Create( { STANDARD_VM_CONTRACT; - NewHolder pAssembly (new Assembly(pDomain, pFile, debuggerFlags, fIsCollectible)); + NewHolder pAssembly (new Assembly(pDomain, pPEAssembly, debuggerFlags, fIsCollectible)); #ifdef PROFILING_SUPPORTED { @@ -429,7 +423,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C || name.Find(i, ':') || name.Find(i, '/')) { - COMPlusThrow(kArgumentException, W("Argument_InvalidAssemblyName")); + COMPlusThrow(kArgumentException, W("InvalidAssemblyName")); } // Set up the assembly manifest metadata @@ -516,7 +510,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C IfFailThrow(pAssemblyEmit->DefineAssembly(publicKey, publicKey.GetSize(), ulHashAlgId, name, &assemData, dwFlags, &ma)); - pPEAssembly = PEAssembly::Create(pCallerAssembly->GetManifestFile(), pAssemblyEmit); + pPEAssembly = PEAssembly::Create(pCallerAssembly->GetPEAssembly(), pAssemblyEmit); AssemblyBinder* pFallbackBinder = pBinder; @@ -531,7 +525,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C // and will have a fallback load context binder associated with it. // There is always a manifest file - wehther working with static or dynamic assemblies. - PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetManifestFile(); + PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetPEAssembly(); _ASSERTE(pCallerAssemblyManifestFile != NULL); if (!pCallerAssemblyManifestFile->IsDynamic()) @@ -625,7 +619,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C // Assembly::Create will call SuppressRelease on the NewHolder that holds the LoaderAllocator when it transfers ownership pAssem = Assembly::Create(pDomain, pPEAssembly, pDomainAssembly->GetDebuggerInfoBits(), pLoaderAllocator->IsCollectible(), pamTracker, pLoaderAllocator); - ReflectionModule* pModule = (ReflectionModule*) pAssem->GetManifestModule(); + ReflectionModule* pModule = (ReflectionModule*) pAssem->GetModule(); pModule->SetCreatingAssembly( pCallerAssembly ); @@ -696,7 +690,7 @@ void Assembly::SetDomainAssembly(DomainAssembly *pDomainAssembly) } CONTRACTL_END; - GetManifestModule()->SetDomainFile(pDomainAssembly); + GetModule()->SetDomainAssembly(pDomainAssembly); } // Assembly::SetDomainAssembly @@ -705,7 +699,7 @@ void Assembly::SetDomainAssembly(DomainAssembly *pDomainAssembly) DomainAssembly *Assembly::GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return GetManifestModule()->GetDomainAssembly(); + return GetModule()->GetDomainAssembly(); } PTR_LoaderHeap Assembly::GetLowFrequencyHeap() @@ -798,9 +792,9 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, mdToken mdLinkRef; mdToken mdBinding; - IMDInternalImport *pManifestImport = GetManifestImport(); + IMDInternalImport *pMDImport = GetMDImport(); - IfFailThrow(pManifestImport->GetExportedTypeProps( + IfFailThrow(pMDImport->GetExportedTypeProps( mdType, NULL, NULL, @@ -809,7 +803,7 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, NULL)); // dwflags // Don't trust the returned tokens. - if (!pManifestImport->IsValidToken(mdLinkRef)) + if (!pMDImport->IsValidToken(mdLinkRef)) { if (loadFlag != Loader::Load) { @@ -834,27 +828,27 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, #ifndef DACCESS_COMPILE // LoadAssembly never returns NULL DomainAssembly * pDomainAssembly = - GetManifestModule()->LoadAssembly(mdLinkRef); + GetModule()->LoadAssembly(mdLinkRef); PREFIX_ASSUME(pDomainAssembly != NULL); - RETURN pDomainAssembly->GetCurrentModule(); + RETURN pDomainAssembly->GetModule(); #else _ASSERTE(!"DAC shouldn't attempt to trigger loading"); return NULL; #endif // !DACCESS_COMPILE }; case Loader::DontLoad: - pAssembly = GetManifestModule()->GetAssemblyIfLoaded(mdLinkRef); + pAssembly = GetModule()->GetAssemblyIfLoaded(mdLinkRef); break; case Loader::SafeLookup: - pAssembly = GetManifestModule()->LookupAssemblyRef(mdLinkRef); + pAssembly = GetModule()->LookupAssemblyRef(mdLinkRef); break; default: _ASSERTE(FALSE); } if (pAssembly) - RETURN pAssembly->GetManifestModule(); + RETURN pAssembly->GetModule(); else RETURN NULL; @@ -871,7 +865,7 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, // Note that we don't want to attempt a LoadModule if a GetModuleIfLoaded will // succeed, because it has a stronger contract. - Module *pModule = GetManifestModule()->GetModuleIfLoaded(mdLinkRef); + Module *pModule = GetModule()->GetModuleIfLoaded(mdLinkRef); #ifdef DACCESS_COMPILE return pModule; #else @@ -884,17 +878,17 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, // We should never get here in the GC case - the above should have succeeded. CONSISTENCY_CHECK(!FORBIDGC_LOADER_USE_ENABLED()); - DomainFile* pDomainModule = NULL; + DomainAssembly* pDomainModule = NULL; if (loadFlag == Loader::Load) { - pDomainModule = GetManifestModule()->LoadModule(::GetAppDomain(), mdLinkRef); + pDomainModule = GetModule()->LoadModule(::GetAppDomain(), mdLinkRef); } if (pDomainModule == NULL) RETURN NULL; else { - pModule = pDomainModule->GetCurrentModule(); + pModule = pDomainModule->GetModule(); if (pModule == NULL) { _ASSERTE(loadFlag!=Loader::Load); @@ -1017,8 +1011,8 @@ Module * Assembly::FindModuleByTypeRef( #ifndef DACCESS_COMPILE if (loadFlag == Loader::Load) { - DomainFile* pActualDomainFile = pModule->LoadModule(::GetAppDomain(), tkType); - RETURN(pActualDomainFile->GetModule()); + DomainAssembly* pActualDomainAssembly = pModule->LoadModule(::GetAppDomain(), tkType); + RETURN(pActualDomainAssembly->GetModule()); } else { @@ -1054,7 +1048,7 @@ Module * Assembly::FindModuleByTypeRef( if (pAssembly != NULL) { - RETURN pAssembly->m_pManifest; + RETURN pAssembly->m_pModule; } #ifdef DACCESS_COMPILE @@ -1072,14 +1066,14 @@ Module * Assembly::FindModuleByTypeRef( if (pDomainAssembly == NULL) RETURN NULL; - pAssembly = pDomainAssembly->GetCurrentAssembly(); + pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly == NULL) { RETURN NULL; } else { - RETURN pAssembly->m_pManifest; + RETURN pAssembly->m_pModule; } #endif //!DACCESS_COMPILE } @@ -1114,9 +1108,9 @@ Module *Assembly::FindModuleByName(LPCSTR pszModuleName) ThrowHR(COR_E_UNAUTHORIZEDACCESS); if (this == SystemDomain::SystemAssembly()) - RETURN m_pManifest->GetModuleIfLoaded(kFile); + RETURN m_pModule->GetModuleIfLoaded(kFile); else - RETURN m_pManifest->LoadModule(::GetAppDomain(), kFile)->GetModule(); + RETURN m_pModule->LoadModule(::GetAppDomain(), kFile)->GetModule(); } void Assembly::CacheManifestExportedTypes(AllocMemTracker *pamTracker) @@ -1132,28 +1126,24 @@ void Assembly::CacheManifestExportedTypes(AllocMemTracker *pamTracker) // Prejitted assemblies are expected to have their table prebuilt. // If not, we do it here at load time (as if we would jit the assembly). - if (m_pManifest->IsPersistedObject(m_pManifest->m_pAvailableClasses)) + if (m_pModule->IsPersistedObject(m_pModule->m_pAvailableClasses)) RETURN; mdToken mdExportedType; - HENUMInternalHolder phEnum(GetManifestImport()); + HENUMInternalHolder phEnum(GetMDImport()); phEnum.EnumInit(mdtExportedType, mdTokenNil); ClassLoader::AvailableClasses_LockHolder lh(m_pClassLoader); - for(int i = 0; GetManifestImport()->EnumNext(&phEnum, &mdExportedType); i++) - m_pClassLoader->AddExportedTypeHaveLock(GetManifestModule(), + for(int i = 0; GetMDImport()->EnumNext(&phEnum, &mdExportedType); i++) + m_pClassLoader->AddExportedTypeHaveLock(GetModule(), mdExportedType, pamTracker); RETURN; } -void Assembly::CacheManifestFiles() -{ -} - //@TODO: if module is not signed it needs to acquire the //permissions from the assembly. @@ -1186,7 +1176,7 @@ void Assembly::PrepareModuleForAssembly(Module* module, AllocMemTracker *pamTrac module->GetDebuggerInfoBits())); #endif // DEBUGGING_SUPPORTED - m_pManifest->EnsureFileCanBeStored(module->GetModuleRef()); + m_pModule->EnsureFileCanBeStored(module->GetModuleRef()); } // This is the final step of publishing a Module into an Assembly. This step cannot fail. @@ -1200,7 +1190,7 @@ void Assembly::PublishModuleIntoAssembly(Module *module) } CONTRACTL_END - GetManifestModule()->EnsuredStoreFile(module->GetModuleRef(), module); + GetModule()->EnsuredStoreFile(module->GetModuleRef(), module); FastInterlockIncrement((LONG*)&m_pClassLoader->m_cUnhashedModules); } @@ -1222,7 +1212,7 @@ void Assembly::CacheFriendAssemblyInfo() if (m_pFriendAssemblyDescriptor == NULL) { - ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetManifestFile()); + ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetPEAssembly()); _ASSERTE(pFriendAssemblies != NULL); CrstHolder friendDescriptorLock(&g_friendAssembliesCrst); @@ -1257,7 +1247,7 @@ void Assembly::UpdateCachedFriendAssemblyInfo() while (true) { - ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetManifestFile()); + ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetPEAssembly()); FriendAssemblyDescriptor* pFriendAssemblyDescriptorNextLoop = NULL; { @@ -1699,14 +1689,14 @@ MethodDesc* Assembly::GetEntryPoint() if (m_pEntryPoint) RETURN m_pEntryPoint; - mdToken mdEntry = m_pManifestFile->GetEntryPointToken(); + mdToken mdEntry = m_pPEAssembly->GetEntryPointToken(); if (IsNilToken(mdEntry)) RETURN NULL; Module *pModule = NULL; switch(TypeFromToken(mdEntry)) { case mdtFile: - pModule = m_pManifest->LoadModule(::GetAppDomain(), mdEntry)->GetModule(); + pModule = m_pModule->LoadModule(::GetAppDomain(), mdEntry)->GetModule(); mdEntry = pModule->GetEntryPointToken(); if ( (TypeFromToken(mdEntry) != mdtMethodDef) || @@ -1715,8 +1705,8 @@ MethodDesc* Assembly::GetEntryPoint() break; case mdtMethodDef: - if (m_pManifestFile->GetMDImport()->IsValidToken(mdEntry)) - pModule = m_pManifest; + if (m_pPEAssembly->GetMDImport()->IsValidToken(mdEntry)) + pModule = m_pModule; break; } @@ -1874,7 +1864,7 @@ BOOL Assembly::IsInstrumentedHelper() return false; // We must have a native image in order to perform IBC instrumentation - if (!GetManifestFile()->IsReadyToRun()) + if (!GetPEAssembly()->IsReadyToRun()) return false; // @Consider using the full name instead of the short form @@ -2001,7 +1991,7 @@ mdAssemblyRef Assembly::AddAssemblyRef(Assembly *refedAssembly, IMetaDataAssembl SafeComHolder emitHolder; AssemblySpec spec; - spec.InitializeSpec(refedAssembly->GetManifestFile()); + spec.InitializeSpec(refedAssembly->GetPEAssembly()); if (refedAssembly->IsCollectible()) { @@ -2059,7 +2049,7 @@ void Assembly::AddExportedType(mdExportedType cl) CONTRACTL_END AllocMemTracker amTracker; - m_pClassLoader->AddExportedTypeDontHaveLock(GetManifestModule(), + m_pClassLoader->AddExportedTypeDontHaveLock(GetModule(), cl, &amTracker); amTracker.SuppressRelease(); @@ -2238,13 +2228,13 @@ Assembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { m_pClassLoader->EnumMemoryRegions(flags); } - if (m_pManifest.IsValid()) + if (m_pModule.IsValid()) { - m_pManifest->EnumMemoryRegions(flags, true); + m_pModule->EnumMemoryRegions(flags, true); } - if (m_pManifestFile.IsValid()) + if (m_pPEAssembly.IsValid()) { - m_pManifestFile->EnumMemoryRegions(flags); + m_pPEAssembly->EnumMemoryRegions(flags); } } diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index f8de5c162e752..8c72128f3e4f6 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -56,16 +56,8 @@ struct CreateDynamicAssemblyArgs : CreateDynamicAssemblyArgsGC StackCrawlMark* stackMark; }; -// An assembly is the unit of deployment for managed code. Typically Assemblies are one to one with files -// (Modules), however this is not necessary, as an assembly can contain serveral files (typically you only -// do this so that you can resource-only modules that are national language specific) -// -// Conceptually Assemblies are loaded into code:AppDomain -// -// So in general an assemly is a list of code:Module, where a code:Module is 1-1 with a DLL or EXE file. -// -// One of the modules the code:Assembly.m_pManifest is special in that it knows about all the other -// modules in an assembly (often it is the only one). +// An assembly is the unit of deployment for managed code. +// Assemblies are one to one with files since coreclr does not support multimodule assemblies. // class Assembly { @@ -88,7 +80,7 @@ class Assembly static Assembly *Create(BaseDomain *pDomain, PEAssembly *pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator); static void Initialize(); - BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pManifestFile->IsSystem(); } + BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->IsSystem(); } static Assembly *CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, CreateDynamicAssemblyArgs *args); @@ -108,15 +100,7 @@ class Assembly void SetIsTenured() { WRAPPER_NO_CONTRACT; - m_pManifest->SetIsTenured(); - } - - // CAUTION: This should only be used as backout code if an assembly is unsuccessfully - // added to the shared domain assembly map. - void UnsetIsTenured() - { - WRAPPER_NO_CONTRACT; - m_pManifest->UnsetIsTenured(); + m_pModule->SetIsTenured(); } #endif // DACCESS_COMPILE @@ -130,72 +114,6 @@ class Assembly return m_pClassLoader; } - // ------------------------------------------------------------ - // Modules - // ------------------------------------------------------------ - - class ModuleIterator - { - Module* m_pManifest; - DWORD m_i; - - public: - // The preferred constructor. If you use this, you don't have to - // call Start() yourself - ModuleIterator(Assembly *pAssembly) - { - WRAPPER_NO_CONTRACT; - Start(pAssembly); - } - - // When you don't have the Assembly at contruction time, use this - // constructor, and explicitly call Start() to begin the iteration. - ModuleIterator() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - m_pManifest = NULL; - m_i = (DWORD) -1; - } - - void Start(Assembly * pAssembly) - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - m_pManifest = pAssembly->GetManifestModule(); - m_i = (DWORD) -1; - } - - BOOL Next() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - while (++m_i <= m_pManifest->GetFileMax()) - { - if (GetModule() != NULL) - return TRUE; - } - return FALSE; - } - - Module *GetModule() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - return m_pManifest->LookupFile(TokenFromRid(m_i, mdtFile)); - } - }; - - ModuleIterator IterateModules() - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - return ModuleIterator(this); - } - - //**************************************************************************************** // // Get the domain the assembly lives in. @@ -231,75 +149,75 @@ class Assembly LPCWSTR GetDebugName() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetDebugName(); + return GetPEAssembly()->GetDebugName(); } #endif LPCUTF8 GetSimpleName() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetSimpleName(); + return GetPEAssembly()->GetSimpleName(); } BOOL IsStrongNamed() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->IsStrongNamed(); + return GetPEAssembly()->IsStrongNamed(); } const void *GetPublicKey(DWORD *pcbPK) { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetPublicKey(pcbPK); + return GetPEAssembly()->GetPublicKey(pcbPK); } ULONG GetHashAlgId() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetHashAlgId(); + return GetPEAssembly()->GetHashAlgId(); } HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision) { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetVersion(pMajor, pMinor, pBuild, pRevision); + return GetPEAssembly()->GetVersion(pMajor, pMinor, pBuild, pRevision); } LPCUTF8 GetLocale() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetLocale(); + return GetPEAssembly()->GetLocale(); } DWORD GetFlags() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetFlags(); + return GetPEAssembly()->GetFlags(); } PTR_LoaderHeap GetLowFrequencyHeap(); PTR_LoaderHeap GetHighFrequencyHeap(); PTR_LoaderHeap GetStubHeap(); - PTR_Module GetManifestModule() + PTR_Module GetModule() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return m_pManifest; + return m_pModule; } - PTR_PEAssembly GetManifestFile() + PTR_PEAssembly GetPEAssembly() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return m_pManifestFile; + return m_pPEAssembly; } - IMDInternalImport* GetManifestImport() + IMDInternalImport* GetMDImport() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return m_pManifestFile->GetMDImport(); + return m_pPEAssembly->GetMDImport(); } HRESULT GetCustomAttribute(mdToken parentToken, @@ -309,7 +227,7 @@ class Assembly { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return GetManifestModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData); + return GetModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData); } mdAssembly GetManifestToken() @@ -324,7 +242,7 @@ class Assembly { WRAPPER_NO_CONTRACT; - return m_pManifestFile->GetDisplayName(result, flags); + return m_pPEAssembly->GetDisplayName(result, flags); } #endif // DACCESS_COMPILE @@ -332,7 +250,7 @@ class Assembly { WRAPPER_NO_CONTRACT; - return m_pManifestFile->GetCodeBase(result); + return m_pPEAssembly->GetCodeBase(result); } OBJECTREF GetExposedObject(); @@ -360,7 +278,7 @@ class Assembly ULONG HashIdentity() { - return GetManifestFile()->HashIdentity(); + return GetPEAssembly()->HashIdentity(); } //**************************************************************************************** @@ -408,8 +326,6 @@ class Assembly FORCEINLINE BOOL IsDynamic() { LIMITED_METHOD_CONTRACT; return m_isDynamic; } FORCEINLINE BOOL IsCollectible() { LIMITED_METHOD_DAC_CONTRACT; return m_isCollectible; } - DWORD GetNextModuleIndex() { LIMITED_METHOD_CONTRACT; return m_nextAvailableModuleIndex++; } - void AddType(Module* pModule, mdTypeDef cl); void AddExportedType(mdExportedType cl); @@ -520,9 +436,9 @@ class Assembly int mask = INTEROP_ATTRIBUTE_UNSET; - if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::ImportedFromTypeLib, NULL, 0) == S_OK) + if (GetModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::ImportedFromTypeLib, NULL, 0) == S_OK) mask |= INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB; - if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::PrimaryInteropAssembly, NULL, 0) == S_OK) + if (GetModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::PrimaryInteropAssembly, NULL, 0) == S_OK) mask |= INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY; if (!IsDynamic()) @@ -540,7 +456,6 @@ class Assembly //**************************************************************************************** void CacheManifestExportedTypes(AllocMemTracker *pamTracker); - void CacheManifestFiles(); void CacheFriendAssemblyInfo(); #ifndef DACCESS_COMPILE @@ -554,11 +469,9 @@ class Assembly PTR_BaseDomain m_pDomain; // Parent Domain PTR_ClassLoader m_pClassLoader; // Single Loader - - PTR_MethodDesc m_pEntryPoint; // Method containing the entry point - PTR_Module m_pManifest; - PTR_PEAssembly m_pManifestFile; + PTR_Module m_pModule; + PTR_PEAssembly m_pPEAssembly; FriendAssemblyDescriptor *m_pFriendAssemblyDescriptor; @@ -566,7 +479,6 @@ class Assembly #ifdef FEATURE_COLLECTIBLE_TYPES BOOL m_isCollectible; #endif // FEATURE_COLLECTIBLE_TYPES - DWORD m_nextAvailableModuleIndex; PTR_LoaderAllocator m_pLoaderAllocator; #ifdef FEATURE_COMINTEROP @@ -590,8 +502,6 @@ class Assembly }; -typedef Assembly::ModuleIterator ModuleIterator; - #ifndef DACCESS_COMPILE //--------------------------------------------------------------------------------------- @@ -673,7 +583,7 @@ class FriendAssemblyDescriptor static bool IsAssemblyOnList(Assembly *pAssembly, const ArrayList &alAssemblyNames) { - return IsAssemblyOnList(pAssembly->GetManifestFile(), alAssemblyNames); + return IsAssemblyOnList(pAssembly->GetPEAssembly(), alAssemblyNames); } static diff --git a/src/coreclr/vm/assemblyname.cpp b/src/coreclr/vm/assemblyname.cpp deleted file mode 100644 index bd6e41e52611b..0000000000000 --- a/src/coreclr/vm/assemblyname.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Header: AssemblyName.cpp -** -** Purpose: Implements AssemblyName (loader domain) architecture -** -** - - -** -===========================================================*/ - -#include "common.h" - -#include -#include - -#include "assemblyname.hpp" -#include "field.h" -#include "strongnameholders.h" -#include "strongnameinternal.h" -#include "eeconfig.h" - -FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE) -{ - FCALL_CONTRACT; - - struct _gc - { - ASSEMBLYNAMEREF result; - STRINGREF filename; - } gc; - - gc.result = NULL; - gc.filename = (STRINGREF) filenameUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - - if (gc.filename == NULL) - COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName")); - - if (gc.filename->GetStringLength() == 0) - COMPlusThrow(kArgumentException, W("Argument_EmptyFileName")); - - gc.result = (ASSEMBLYNAMEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__ASSEMBLY_NAME)); - - - /////////////////////////////////////////////// - SString sFileName(gc.filename->GetBuffer()); - PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache); - - // Ask for FLAT. We will only look at metadata and release the image shortly. - // Besides we may be getting the assembly name for images that contain native code for a - // non-native platform and would end up using flat anyways. - PEImageLayout* pLayout = pImage->GetOrCreateLayout(PEImageLayout::LAYOUT_FLAT); - - pImage->VerifyIsAssembly(); - - AssemblySpec spec; - spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL); - spec.AssemblyNameInit(&gc.result, pImage); - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(gc.result); -} -FCIMPLEND - -FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE) -{ - FCALL_CONTRACT; - - U1ARRAYREF orOutputArray = NULL; - OBJECTREF refThis = (OBJECTREF) refThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_1(refThis); - - if (refThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - - ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis; - U1ARRAYREF orPublicKey = orThis->GetPublicKey(); - - if (orPublicKey != NULL) { - DWORD cb = orPublicKey->GetNumComponents(); - StrongNameBufferHolder pbToken; - - if (cb) { - CQuickBytes qb; - BYTE *pbKey = (BYTE*) qb.AllocThrows(cb); - memcpy(pbKey, orPublicKey->GetDataPtr(), cb); - - { - GCX_PREEMP(); - IfFailThrow(StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb)); - } - } - - orOutputArray = (U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb); - memcpyNoGCRefs(orOutputArray->m_Array, pbToken, cb); - } - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(orOutputArray); -} -FCIMPLEND - - -FCIMPL1(void, AssemblyNameNative::Init, Object * refThisUNSAFE) -{ - FCALL_CONTRACT; - - ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE; - HRESULT hr = S_OK; - - HELPER_METHOD_FRAME_BEGIN_1(pThis); - - if (pThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - - ACQUIRE_STACKING_ALLOCATOR(pStackingAllocator); - - AssemblySpec spec; - hr = spec.InitializeSpec(pStackingAllocator, (ASSEMBLYNAMEREF *) &pThis, TRUE); - - if (SUCCEEDED(hr)) - { - spec.AssemblyNameInit(&pThis,NULL); - } - else - { - ThrowHR(hr); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - diff --git a/src/coreclr/vm/assemblyname.hpp b/src/coreclr/vm/assemblyname.hpp deleted file mode 100644 index 9e818fc1a9f7c..0000000000000 --- a/src/coreclr/vm/assemblyname.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Header: AssemblyName.hpp -** -** Purpose: Implements AssemblyName (loader domain) architecture -** -** - - -** -===========================================================*/ -#ifndef _AssemblyName_H -#define _AssemblyName_H - -class AssemblyNameNative -{ -public: - static FCDECL1(Object*, GetFileInformation, StringObject* filenameUNSAFE); - static FCDECL1(Object*, GetPublicKeyToken, Object* refThisUNSAFE); - static FCDECL1(void, Init, Object * refThisUNSAFE); -}; - -#endif // _AssemblyName_H - diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index a51280e21e4a3..dba5110590717 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -20,7 +20,6 @@ #include "assemblynative.hpp" #include "dllimport.h" #include "field.h" -#include "assemblyname.hpp" #include "eeconfig.h" #include "interoputil.h" #include "frames.h" @@ -86,9 +85,8 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(QCall::ObjectHandleOnStack } // Initialize spec - spec.InitializeSpec(pStackingAllocator, - &assemblyNameRef, - FALSE); + spec.InitializeSpec(pStackingAllocator, &assemblyNameRef); + GCPROTECT_END(); spec.SetCodeBase(NULL); @@ -107,7 +105,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(QCall::ObjectHandleOnStack { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEAssembly *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile(); + PEAssembly *pRefAssemblyManifestFile = pRefAssembly->GetPEAssembly(); spec.SetFallbackBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackBinder()); } @@ -271,7 +269,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl // we created above. We need pointer comparison instead of pe image equivalence // to avoid mixed binaries/PDB pairs of other images. // This applies to both Desktop CLR and CoreCLR, with or without fusion. - BOOL fIsSameAssembly = (pLoadedAssembly->GetManifestFile()->GetPEImage() == pILImage); + BOOL fIsSameAssembly = (pLoadedAssembly->GetPEAssembly()->GetPEImage() == pILImage); // Setting the PDB info is only applicable for our original assembly. // This applies to both Desktop CLR and CoreCLR, with or without fusion. @@ -282,7 +280,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl if (ptrSymbolArray != NULL) { PBYTE pSymbolArray = reinterpret_cast(ptrSymbolArray); - pLoadedAssembly->GetManifestModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); + pLoadedAssembly->GetModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); } #endif // DEBUGGING_SUPPORTED } @@ -404,7 +402,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedType(QCall::AssemblyHandle mdToken mdImpl; Assembly * pAsm = pAssembly->GetAssembly(); - Module *pManifestModule = pAsm->GetManifestModule(); + Module *pManifestModule = pAsm->GetModule(); IfFailThrow(pManifestModule->GetMDImport()->GetExportedTypeProps(mdtExternalType, &pszNameSpace, &pszClassName, &mdImpl, NULL, NULL)); if (TypeFromToken(mdImpl) == mdtAssemblyRef) { @@ -614,7 +612,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem HENUMInternalHolder phEnum(pAssembly->GetMDImport()); phEnum.EnumInit(mdtFile, mdTokenNil); - InlineSArray modules; + InlineSArray modules; modules.Append(pAssembly); @@ -623,7 +621,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem { if (fLoadIfNotFound) { - DomainFile* pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile); + DomainAssembly* pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile); modules.Append(pModule); } } @@ -640,7 +638,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem for(COUNT_T i = 0; i < modules.GetCount(); i++) { - DomainFile * pModule = modules[i]; + DomainAssembly * pModule = modules[i]; OBJECTREF o = pModule->GetExposedModuleObject(); orModules->SetAt(i, o); @@ -699,10 +697,10 @@ extern "C" void QCALLTYPE AssemblyNative_GetModule(QCall::AssemblyHandle pAssemb LPCUTF8 pModuleName = NULL; - if SUCCEEDED(pAssembly->GetDomainAssembly()->GetModule()->GetScopeName(&pModuleName)) + if SUCCEEDED(pAssembly->GetModule()->GetScopeName(&pModuleName)) { if (::SString::_stricmp(pModuleName, szModuleName) == 0) - pModule = pAssembly->GetDomainAssembly()->GetModule(); + pModule = pAssembly->GetModule(); } @@ -727,7 +725,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle Assembly * pAsm = pAssembly->GetAssembly(); - IMDInternalImport *pImport = pAsm->GetManifestImport(); + IMDInternalImport *pImport = pAsm->GetMDImport(); { HENUMTypeDefInternalHolder phTDEnum(pImport); @@ -755,7 +753,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle if (IsTdPublic(dwFlags)) { - TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetManifestModule(), mdTD, + TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetModule(), mdTD, ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef); types.Append(typeHnd); @@ -803,7 +801,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle IsTdPublic(dwFlags)) { NameHandle typeName(pszNameSpace, pszClassName); - typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); + typeName.SetTypeToken(pAsm->GetModule(), mdCT); TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); types.Append(typeHnd); @@ -847,7 +845,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedTypes(QCall::AssemblyHandle Assembly * pAsm = pAssembly->GetAssembly(); - IMDInternalImport *pImport = pAsm->GetManifestImport(); + IMDInternalImport *pImport = pAsm->GetMDImport(); // enumerate the ExportedTypes table { @@ -873,7 +871,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedTypes(QCall::AssemblyHandle if ((TypeFromToken(mdImpl) == mdtAssemblyRef) && (mdImpl != mdAssemblyRefNil)) { NameHandle typeName(pszNameSpace, pszClassName); - typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); + typeName.SetTypeToken(pAsm->GetModule(), mdCT); TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); types.Append(typeHnd); @@ -979,7 +977,7 @@ FCIMPL1(Object*, AssemblyNative::GetReferencedAssemblies, AssemblyBaseObject * p HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - IMDInternalImport *pImport = pAssembly->GetAssembly()->GetManifestImport(); + IMDInternalImport *pImport = pAssembly->GetAssembly()->GetMDImport(); MethodTable* pAsmNameClass = CoreLibBinder::GetClass(CLASS__ASSEMBLY_NAME); @@ -1106,7 +1104,7 @@ FCIMPL1(ReflectModuleBaseObject *, AssemblyNative::GetInMemoryAssemblyModule, As DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); - FC_RETURN_MODULE_OBJECT(pAssembly->GetCurrentModule(), refAssembly); + FC_RETURN_MODULE_OBJECT(pAssembly->GetModule(), refAssembly); } FCIMPLEND @@ -1358,7 +1356,7 @@ extern "C" void QCALLTYPE AssemblyNative_ApplyUpdate( { COMPlusThrow(kNotSupportedException, W("NotSupported_DebuggerAttached")); } - Module* pModule = assembly->GetDomainAssembly()->GetModule(); + Module* pModule = assembly->GetModule(); if (!pModule->IsEditAndContinueEnabled()) { COMPlusThrow(kInvalidOperationException, W("InvalidOperation_AssemblyNotEditable")); diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index dfbee7152df19..cce0b240105d3 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -250,8 +250,7 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) // This uses thread storage to allocate space. Please use Checkpoint and release it. -HRESULT AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName, - BOOL fParse /*=TRUE*/) +void AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName) { CONTRACTL { @@ -290,107 +289,86 @@ HRESULT AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* SetName(lpName); } - if (fParse) { - HRESULT hr = ParseName(); - // Sometimes Fusion flags invalid characters in the name, sometimes it doesn't - // depending on where the invalid characters are - // We want to Raise the assembly resolve event on all invalid characters - // but calling ParseName before checking for invalid characters gives Fusion a chance to - // parse the rest of the name (to get a public key token, etc.) - if ((hr == FUSION_E_INVALID_NAME) || (!IsValidAssemblyName())) { - // This is the only case where we do not throw on an error - // We don't want to throw so as to give the caller a chance to call RaiseAssemblyResolveEvent - // The only caller that cares is System.Reflection.Assembly.InternalLoad which calls us through - // AssemblyNameNative::Init - return FUSION_E_INVALID_NAME; - } - else - IfFailThrow(hr); + AssemblyMetaDataInternal asmInfo; + // Flags + DWORD dwFlags = (*pName)->GetFlags(); + + // Version + VERSIONREF version = (VERSIONREF) (*pName)->GetVersion(); + if(version == NULL) { + asmInfo.usMajorVersion = (USHORT)-1; + asmInfo.usMinorVersion = (USHORT)-1; + asmInfo.usBuildNumber = (USHORT)-1; + asmInfo.usRevisionNumber = (USHORT)-1; } else { - AssemblyMetaDataInternal asmInfo; - // Flags - DWORD dwFlags = (*pName)->GetFlags(); - - // Version - VERSIONREF version = (VERSIONREF) (*pName)->GetVersion(); - if(version == NULL) { - asmInfo.usMajorVersion = (USHORT)-1; - asmInfo.usMinorVersion = (USHORT)-1; - asmInfo.usBuildNumber = (USHORT)-1; - asmInfo.usRevisionNumber = (USHORT)-1; - } - else { - asmInfo.usMajorVersion = (USHORT)version->GetMajor(); - asmInfo.usMinorVersion = (USHORT)version->GetMinor(); - asmInfo.usBuildNumber = (USHORT)version->GetBuild(); - asmInfo.usRevisionNumber = (USHORT)version->GetRevision(); - } + asmInfo.usMajorVersion = (USHORT)version->GetMajor(); + asmInfo.usMinorVersion = (USHORT)version->GetMinor(); + asmInfo.usBuildNumber = (USHORT)version->GetBuild(); + asmInfo.usRevisionNumber = (USHORT)version->GetRevision(); + } - asmInfo.szLocale = 0; + asmInfo.szLocale = 0; - if ((*pName)->GetCultureInfo() != NULL) - { - struct _gc { - OBJECTREF cultureinfo; - STRINGREF pString; - } gc; - - gc.cultureinfo = (*pName)->GetCultureInfo(); - gc.pString = NULL; - - GCPROTECT_BEGIN(gc); - - MethodDescCallSite getName(METHOD__CULTURE_INFO__GET_NAME, &gc.cultureinfo); - - ARG_SLOT args[] = { - ObjToArgSlot(gc.cultureinfo) - }; - gc.pString = getName.Call_RetSTRINGREF(args); - if (gc.pString != NULL) { - WCHAR* pString; - int iString; - gc.pString->RefInterpretGetStringValuesDangerousForGC(&pString, &iString); - DWORD lgth = WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, NULL, 0, NULL, NULL); - S_UINT32 lengthWillNull = S_UINT32(lgth) + S_UINT32(1); - LPSTR lpLocale = (LPSTR) alloc->Alloc(lengthWillNull); - if (lengthWillNull.IsOverflow()) - { - COMPlusThrowHR(COR_E_OVERFLOW); - } - WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, - lpLocale, lengthWillNull.Value(), NULL, NULL); - lpLocale[lgth] = '\0'; - asmInfo.szLocale = lpLocale; - } - GCPROTECT_END(); - } + if ((*pName)->GetCultureInfo() != NULL) + { + struct _gc { + OBJECTREF cultureinfo; + STRINGREF pString; + } gc; - // Strong name - DWORD cbPublicKeyOrToken=0; - BYTE* pbPublicKeyOrToken=NULL; - // Note that we prefer to take a public key token if present, - // even if flags indicate a full public key - if ((*pName)->GetPublicKeyToken() != NULL) { - dwFlags &= ~afPublicKey; - PBYTE pArray = NULL; - pArray = (*pName)->GetPublicKeyToken()->GetDirectPointerToNonObjectElements(); - cbPublicKeyOrToken = (*pName)->GetPublicKeyToken()->GetNumComponents(); - pbPublicKeyOrToken = pArray; - } - else if ((*pName)->GetPublicKey() != NULL) { - dwFlags |= afPublicKey; - PBYTE pArray = NULL; - pArray = (*pName)->GetPublicKey()->GetDirectPointerToNonObjectElements(); - cbPublicKeyOrToken = (*pName)->GetPublicKey()->GetNumComponents(); - pbPublicKeyOrToken = pArray; + gc.cultureinfo = (*pName)->GetCultureInfo(); + gc.pString = NULL; + + GCPROTECT_BEGIN(gc); + + MethodDescCallSite getName(METHOD__CULTURE_INFO__GET_NAME, &gc.cultureinfo); + + ARG_SLOT args[] = { + ObjToArgSlot(gc.cultureinfo) + }; + gc.pString = getName.Call_RetSTRINGREF(args); + if (gc.pString != NULL) { + WCHAR* pString; + int iString; + gc.pString->RefInterpretGetStringValuesDangerousForGC(&pString, &iString); + DWORD lgth = WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, NULL, 0, NULL, NULL); + S_UINT32 lengthWillNull = S_UINT32(lgth) + S_UINT32(1); + LPSTR lpLocale = (LPSTR) alloc->Alloc(lengthWillNull); + if (lengthWillNull.IsOverflow()) + { + COMPlusThrowHR(COR_E_OVERFLOW); + } + WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, + lpLocale, lengthWillNull.Value(), NULL, NULL); + lpLocale[lgth] = '\0'; + asmInfo.szLocale = lpLocale; } - BaseAssemblySpec::Init(GetName(),&asmInfo,pbPublicKeyOrToken,cbPublicKeyOrToken,dwFlags); - } + GCPROTECT_END(); + } + + // Strong name + DWORD cbPublicKeyOrToken=0; + BYTE* pbPublicKeyOrToken=NULL; + // Note that we prefer to take a public key token if present, + // even if flags indicate a full public key + if ((*pName)->GetPublicKeyToken() != NULL) { + dwFlags &= ~afPublicKey; + PBYTE pArray = NULL; + pArray = (*pName)->GetPublicKeyToken()->GetDirectPointerToNonObjectElements(); + cbPublicKeyOrToken = (*pName)->GetPublicKeyToken()->GetNumComponents(); + pbPublicKeyOrToken = pArray; + } + else if ((*pName)->GetPublicKey() != NULL) { + dwFlags |= afPublicKey; + PBYTE pArray = NULL; + pArray = (*pName)->GetPublicKey()->GetDirectPointerToNonObjectElements(); + cbPublicKeyOrToken = (*pName)->GetPublicKey()->GetNumComponents(); + pbPublicKeyOrToken = pArray; + } + BaseAssemblySpec::Init(GetName(),&asmInfo,pbPublicKeyOrToken,cbPublicKeyOrToken,dwFlags); CloneFieldsToStackingAllocator(alloc); - - return S_OK; } void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName, PEImage* pImageInfo) @@ -756,7 +734,7 @@ DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, BinderTracing::AssemblyBindOperation bindOperation(this); bindOperation.SetResult(pAssembly->GetPEAssembly(), true /*cached*/); - pDomain->LoadDomainFile(pAssembly, targetLevel); + pDomain->LoadDomainAssembly(pAssembly, targetLevel); RETURN pAssembly; } diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 5d09b5b75a664..8d2bd8045593d 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -16,7 +16,7 @@ #define _ASSEMBLYSPEC_H #include "hash.h" #include "assemblyspecbase.h" -#include "domainfile.h" +#include "domainassembly.h" #include "holder.h" class AppDomain; @@ -103,9 +103,7 @@ class AssemblySpec : public BaseAssemblySpec void InitializeSpec(PEAssembly* pPEAssembly); - HRESULT InitializeSpec(StackingAllocator* alloc, - ASSEMBLYNAMEREF* pName, - BOOL fParse = TRUE); + void InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName); void AssemblyNameInit(ASSEMBLYNAMEREF* pName, PEImage* pImageInfo); //[in,out], [in] diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 72a2e1152210b..c25b7aa19cc9d 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -443,7 +443,6 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb // // szName is only used by dynamic modules, see ReflectionModule::Initialize // -// void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) { CONTRACTL @@ -464,14 +463,6 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) m_DictionaryCrst.Init(CrstDomainLocalBlock); AllocateMaps(); - - if (IsSystem() || - (strcmp(m_pSimpleName, "System") == 0) || - (strcmp(m_pSimpleName, "System.Core") == 0)) - { - FastInterlockOr(&m_dwPersistedFlags, LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME); - } - m_dwTransientFlags &= ~((DWORD)CLASSES_FREED); // Set flag indicating LookupMaps are now in a consistent and destructable state #ifdef FEATURE_COLLECTIBLE_TYPES @@ -1041,7 +1032,7 @@ BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEAssembly *pPEAssemb BOOL Module::IsManifest() { WRAPPER_NO_CONTRACT; - return dac_cast(GetAssembly()->GetManifestModule()) == + return dac_cast(GetAssembly()->GetModule()) == dac_cast(this); } @@ -1049,14 +1040,7 @@ DomainAssembly* Module::GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return dac_cast(m_ModuleID->GetDomainFile()); -} - -DomainFile *Module::GetDomainFile() -{ - LIMITED_METHOD_DAC_CONTRACT; - - return dac_cast(m_ModuleID->GetDomainFile()); + return dac_cast(m_ModuleID->GetDomainAssembly()); } #ifndef DACCESS_COMPILE @@ -1629,9 +1613,7 @@ BOOL Module::IsNoStringInterning() HRESULT hr; - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); _ASSERTE(mdImport); mdToken token; @@ -1736,9 +1718,7 @@ BOOL Module::IsRuntimeWrapExceptions() HRESULT hr; BOOL fRuntimeWrapExceptions = FALSE; - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); mdToken token; IfFailGo(mdImport->GetAssemblyFromScope(&token)); @@ -1775,6 +1755,42 @@ BOOL Module::IsRuntimeWrapExceptions() return !!(m_dwPersistedFlags & WRAP_EXCEPTIONS); } +BOOL Module::IsRuntimeMarshallingEnabled() +{ + CONTRACTL + { + THROWS; + if (IsRuntimeMarshallingEnabledCached()) GC_NOTRIGGER; else GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END + + if (IsRuntimeMarshallingEnabledCached()) + { + return !!(m_dwPersistedFlags & RUNTIME_MARSHALLING_ENABLED); + } + + HRESULT hr; + + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); + + mdToken token; + if (SUCCEEDED(hr = mdImport->GetAssemblyFromScope(&token))) + { + const BYTE *pVal; + ULONG cbVal; + + hr = mdImport->GetCustomAttributeByName(token, + g_DisableRuntimeMarshallingAttribute, + (const void**)&pVal, &cbVal); + } + + FastInterlockOr(&m_dwPersistedFlags, RUNTIME_MARSHALLING_ENABLED_IS_CACHED | + (hr == S_OK ? 0 : RUNTIME_MARSHALLING_ENABLED)); + + return hr != S_OK; +} + BOOL Module::IsPreV4Assembly() { CONTRACTL @@ -1786,7 +1802,7 @@ BOOL Module::IsPreV4Assembly() if (!(m_dwPersistedFlags & COMPUTED_IS_PRE_V4_ASSEMBLY)) { - IMDInternalImport *pImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *pImport = GetAssembly()->GetMDImport(); _ASSERTE(pImport); BOOL fIsPreV4Assembly = FALSE; @@ -1968,13 +1984,13 @@ void Module::AllocateStatics(AllocMemTracker *pamTracker) BuildStaticsOffsets(pamTracker); } -void Module::SetDomainFile(DomainFile *pDomainFile) +void Module::SetDomainAssembly(DomainAssembly *pDomainAssembly) { CONTRACTL { INSTANCE_CHECK; - PRECONDITION(CheckPointer(pDomainFile)); - PRECONDITION(IsManifest() == pDomainFile->IsAssembly()); + PRECONDITION(CheckPointer(pDomainAssembly)); + PRECONDITION(IsManifest()); THROWS; GC_TRIGGERS; MODE_ANY; @@ -1994,7 +2010,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) } else { - pLoaderAllocator = pDomainFile->GetAppDomain()->GetLoaderAllocator(); + pLoaderAllocator = pDomainAssembly->GetAppDomain()->GetLoaderAllocator(); } SIZE_T size = GetDomainLocalModuleSize(); @@ -2034,7 +2050,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) m_ModuleID = pModuleData; } - m_ModuleID->SetDomainFile(pDomainFile); + m_ModuleID->SetDomainAssembly(pDomainAssembly); // Allocate static handles now. // NOTE: Bootstrapping issue with CoreLib - we will manually allocate later @@ -2042,7 +2058,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) // as it is currently initialized through the DomainLocalModule::PopulateClass in MethodTable::CheckRunClassInitThrowing // (If we don't do this, it would allocate here unused regular static handles that will be overridden later) if (g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] != NULL && !GetAssembly()->IsCollectible()) - AllocateRegularStaticHandles(pDomainFile->GetAppDomain()); + AllocateRegularStaticHandles(pDomainAssembly->GetAppDomain()); } OBJECTREF Module::GetExposedObject() @@ -2057,7 +2073,7 @@ OBJECTREF Module::GetExposedObject() } CONTRACT_END; - RETURN GetDomainFile()->GetExposedModuleObject(); + RETURN GetDomainAssembly()->GetExposedModuleObject(); } // @@ -3284,7 +3300,7 @@ Module::GetAssemblyIfLoaded( } if (pDomainAssembly && pDomainAssembly->IsLoaded()) - pAssembly = pDomainAssembly->GetCurrentAssembly(); // Do not use GetAssembly - that may force the completion of a load + pAssembly = pDomainAssembly->GetAssembly(); // Only store in the rid map if working with the current AppDomain. if (fCanUseRidMap && pAssembly) @@ -3368,7 +3384,7 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) if (pAssembly != NULL) { pDomainAssembly = pAssembly->GetDomainAssembly(); - ::GetAppDomain()->LoadDomainFile(pDomainAssembly, FILE_LOADED); + ::GetAppDomain()->LoadDomainAssembly(pDomainAssembly, FILE_LOADED); RETURN pDomainAssembly; } @@ -3395,9 +3411,9 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases - if (pDomainAssembly->GetCurrentAssembly() != NULL) + if (pDomainAssembly->GetAssembly() != NULL) { - StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetCurrentAssembly()); + StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetAssembly()); } } @@ -3438,7 +3454,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) if (kFile == mdTokenNil) RETURN NULL; - RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile); + RETURN GetAssembly()->GetModule()->GetModuleIfLoaded(kFile); } Module *pModule = LookupFile(kFile); @@ -3447,7 +3463,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) if (IsManifest()) { if (kFile == mdFileNil) - pModule = GetAssembly()->GetManifestModule(); + pModule = GetAssembly()->GetModule(); } else { @@ -3461,7 +3477,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) { if (kMatch == mdFileNil) { - pModule = pAssembly->GetManifestModule(); + pModule = pAssembly->GetModule(); } else { @@ -3469,7 +3485,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) } } else - pModule = pAssembly->GetManifestModule()->LookupFile(kMatch); + pModule = pAssembly->GetModule()->LookupFile(kMatch); } #ifndef DACCESS_COMPILE @@ -3485,9 +3501,9 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) #ifndef DACCESS_COMPILE -DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile) +DomainAssembly *Module::LoadModule(AppDomain *pDomain, mdFile kFile) { - CONTRACT(DomainFile *) + CONTRACT(DomainAssembly *) { INSTANCE_CHECK; THROWS; @@ -3507,7 +3523,7 @@ DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile) else { // This is mdtFile - IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile, + IfFailThrow(GetAssembly()->GetMDImport()->GetFileProps(kFile, &psModuleName, NULL, NULL, @@ -3546,7 +3562,7 @@ PTR_Module Module::LookupModule(mdToken kFile) if (kFileLocal == mdTokenNil) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); - RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal); + RETURN GetAssembly()->GetModule()->LookupModule(kFileLocal); } PTR_Module pModule = LookupFile(kFile); @@ -3557,12 +3573,12 @@ PTR_Module Module::LookupModule(mdToken kFile) mdFile kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile); if (IsNilToken(kMatch)) { if (kMatch == mdFileNil) - pModule = pAssembly->GetManifestModule(); + pModule = pAssembly->GetModule(); else COMPlusThrowHR(COR_E_BADIMAGEFORMAT); } else - pModule = pAssembly->GetManifestModule()->LookupFile(kMatch); + pModule = pAssembly->GetModule()->LookupFile(kMatch); } RETURN pModule; } @@ -4031,7 +4047,7 @@ void Module::UpdateDynamicMetadataIfNeeded() #endif // DEBUGGING_SUPPORTED -BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int flags, BOOL attaching) +BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainAssembly * pDomainAssembly, int flags, BOOL attaching) { WRAPPER_NO_CONTRACT; @@ -4042,7 +4058,7 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in // Always capture metadata, even if no debugger is attached. If a debugger later attaches, it will use // this data. { - Module * pModule = pDomainFile->GetModule(); + Module * pModule = pDomainAssembly->GetModule(); pModule->UpdateDynamicMetadataIfNeeded(); } @@ -4063,7 +4079,7 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in m_pPEAssembly->GetPath().GetCount(), GetAssembly(), pDomain, - pDomainFile, + pDomainAssembly, attaching); result = TRUE; @@ -4559,7 +4575,7 @@ Module *Module::GetModuleFromIndex(DWORD ix) Assembly *pAssembly = this->LookupAssemblyRef(mdAssemblyRefToken); if (pAssembly) { - RETURN pAssembly->GetManifestModule(); + RETURN pAssembly->GetModule(); } else { @@ -6442,11 +6458,7 @@ void Module::WriteAllModuleProfileData(bool cleanup) while (assemblyIterator.Next(pDomainAssembly.This())) { - DomainModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (i.Next()) - { - /*hr=*/i.GetModule()->WriteMethodProfileDataLogFile(cleanup); - } + pDomainAssembly->GetModule()->WriteMethodProfileDataLogFile(cleanup); } } } @@ -7437,7 +7449,7 @@ VOID Module::EnsureActive() MODE_ANY; } CONTRACTL_END; - GetDomainFile()->EnsureActive(); + GetDomainAssembly()->EnsureActive(); } #endif // DACCESS_COMPILE @@ -7456,13 +7468,13 @@ VOID Module::EnsureAllocated() } CONTRACTL_END; - GetDomainFile()->EnsureAllocated(); + GetDomainAssembly()->EnsureAllocated(); } VOID Module::EnsureLibraryLoaded() { STANDARD_VM_CONTRACT; - GetDomainFile()->EnsureLibraryLoaded(); + GetDomainAssembly()->EnsureLibraryLoaded(); } #endif // !DACCESS_COMPILE @@ -7477,10 +7489,10 @@ CHECK Module::CheckActivated() CONTRACTL_END; #ifndef DACCESS_COMPILE - DomainFile *pDomainFile = GetDomainFile(); - CHECK(pDomainFile != NULL); - PREFIX_ASSUME(pDomainFile != NULL); - CHECK(pDomainFile->CheckActivated()); + DomainAssembly *pDomainAssembly = GetDomainAssembly(); + CHECK(pDomainAssembly != NULL); + PREFIX_ASSUME(pDomainAssembly != NULL); + CHECK(pDomainAssembly->CheckActivated()); #endif CHECK_OK; } diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index e7dd5629a2c84..d9cd6742cb6c0 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -832,8 +832,12 @@ class Module //If m_MethodDefToPropertyInfoMap has been generated COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP = 0x00002000, - // Low level system assembly. Used by preferred zap module computation. - LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME = 0x00004000, + // unused = 0x00004000, + + //If setting has been cached + RUNTIME_MARSHALLING_ENABLED_IS_CACHED = 0x00008000, + //If runtime marshalling is enabled for this assembly + RUNTIME_MARSHALLING_ENABLED = 0x00010000, }; Volatile m_dwTransientFlags; @@ -1127,13 +1131,9 @@ class Module MethodTable *GetGlobalMethodTable(); bool NeedsGlobalMethodTable(); - // This works for manifest modules too - DomainFile *GetDomainFile(); - - // Operates on assembly of module DomainAssembly *GetDomainAssembly(); - void SetDomainFile(DomainFile *pDomainFile); + void SetDomainAssembly(DomainAssembly *pDomainAssembly); OBJECTREF GetExposedObject(); @@ -1190,14 +1190,6 @@ class Module LIMITED_METHOD_CONTRACT; FastInterlockOr(&m_dwTransientFlags, MODULE_IS_TENURED); } - - // CAUTION: This should only be used as backout code if an assembly is unsuccessfully - // added to the shared domain assembly map. - VOID UnsetIsTenured() - { - LIMITED_METHOD_CONTRACT; - FastInterlockAnd(&m_dwTransientFlags, ~MODULE_IS_TENURED); - } #endif // !DACCESS_COMPILE @@ -1218,13 +1210,6 @@ class Module } #endif - BOOL IsLowLevelSystemAssemblyByName() - { - LIMITED_METHOD_CONTRACT; - // The flag is set during initialization, so we can skip the memory barrier - return m_dwPersistedFlags.LoadWithoutBarrier() & LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME; - } - #ifndef DACCESS_COMPILE VOID EnsureActive(); VOID EnsureAllocated(); @@ -1431,7 +1416,7 @@ class Module DomainAssembly * LoadAssembly(mdAssemblyRef kAssemblyRef); Module *GetModuleIfLoaded(mdFile kFile); - DomainFile *LoadModule(AppDomain *pDomain, mdFile kFile); + DomainAssembly *LoadModule(AppDomain *pDomain, mdFile kFile); PTR_Module LookupModule(mdToken kFile); //wrapper over GetModuleIfLoaded, takes modulerefs as well DWORD GetAssemblyRefFlags(mdAssemblyRef tkAssemblyRef); @@ -1714,7 +1699,7 @@ class Module public: // Debugger stuff - BOOL NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int level, BOOL attaching); + BOOL NotifyDebuggerLoad(AppDomain *pDomain, DomainAssembly * pDomainAssembly, int level, BOOL attaching); void NotifyDebuggerUnload(AppDomain *pDomain); void SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits); @@ -1985,18 +1970,6 @@ class Module return dac_cast(m_ModuleID); } - SIZE_T * GetAddrModuleID() - { - LIMITED_METHOD_CONTRACT; - return (SIZE_T*) &m_ModuleID; - } - - static SIZE_T GetOffsetOfModuleID() - { - LIMITED_METHOD_CONTRACT; - return offsetof(Module, m_ModuleID); - } - PTR_DomainLocalModule GetDomainLocalModule(); // LoaderHeap for storing IJW thunks @@ -2071,6 +2044,18 @@ class Module //----------------------------------------------------------------------------------------- BOOL IsRuntimeWrapExceptions(); + //----------------------------------------------------------------------------------------- + // If true, the built-in runtime-generated marshalling subsystem will be used for + // P/Invokes, function pointer invocations, and delegates defined in this module + //----------------------------------------------------------------------------------------- + BOOL IsRuntimeMarshallingEnabled(); + + BOOL IsRuntimeMarshallingEnabledCached() + { + LIMITED_METHOD_CONTRACT; + return (m_dwPersistedFlags & RUNTIME_MARSHALLING_ENABLED_IS_CACHED); + } + BOOL HasDefaultDllImportSearchPathsAttribute(); BOOL IsDefaultDllImportSearchPathsAttributeCached() diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl index ca770297a4bc9..fee8a8f4fcc33 100644 --- a/src/coreclr/vm/ceeload.inl +++ b/src/coreclr/vm/ceeload.inl @@ -297,25 +297,25 @@ inline Assembly *Module::LookupAssemblyRef(mdAssemblyRef token) inline void Module::ForceStoreAssemblyRef(mdAssemblyRef token, Assembly *value) { WRAPPER_NO_CONTRACT; // THROWS/GC_NOTRIGGER/INJECT_FAULT()/MODE_ANY - _ASSERTE(value->GetManifestModule()); + _ASSERTE(value->GetModule()); _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); - m_ManifestModuleReferencesMap.AddElement(this, RidFromToken(token), value->GetManifestModule()); + m_ManifestModuleReferencesMap.AddElement(this, RidFromToken(token), value->GetModule()); } inline void Module::StoreAssemblyRef(mdAssemblyRef token, Assembly *value) { WRAPPER_NO_CONTRACT; - _ASSERTE(value->GetManifestModule()); + _ASSERTE(value->GetModule()); _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); - m_ManifestModuleReferencesMap.TrySetElement(RidFromToken(token), value->GetManifestModule()); + m_ManifestModuleReferencesMap.TrySetElement(RidFromToken(token), value->GetModule()); } inline mdAssemblyRef Module::FindAssemblyRef(Assembly *targetAssembly) { WRAPPER_NO_CONTRACT; - return m_ManifestModuleReferencesMap.Find(targetAssembly->GetManifestModule()) | mdtAssemblyRef; + return m_ManifestModuleReferencesMap.Find(targetAssembly->GetModule()) | mdtAssemblyRef; } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 0ccacd36a9f91..9aa6c6994e726 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -363,19 +363,21 @@ class EEClassLayoutInfo private: enum { // TRUE if the GC layout of the class is bit-for-bit identical - // to its unmanaged counterpart (i.e. no internal reference fields, - // no ansi-unicode char conversions required, etc.) Used to - // optimize marshaling. - e_BLITTABLE = 0x01, - // Post V1.0 addition: Is this type also sequential in managed memory? - e_MANAGED_SEQUENTIAL = 0x02, + // to its unmanaged counterpart with the runtime marshalling system + // (i.e. no internal reference fields, no ansi-unicode char conversions required, etc.) + // Used to optimize marshaling. + e_BLITTABLE = 0x01, + // Is this type also sequential in managed memory? + e_MANAGED_SEQUENTIAL = 0x02, // When a sequential/explicit type has no fields, it is conceptually // zero-sized, but actually is 1 byte in length. This holds onto this // fact and allows us to revert the 1 byte of padding when another // explicit type inherits from this type. - e_ZERO_SIZED = 0x04, + e_ZERO_SIZED = 0x04, // The size of the struct is explicitly specified in the meta-data. - e_HAS_EXPLICIT_SIZE = 0x08 + e_HAS_EXPLICIT_SIZE = 0x08, + // The type recursively has a field that is LayoutKind.Auto and not an enum. + e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10 }; BYTE m_bFlags; @@ -419,6 +421,12 @@ class EEClassLayoutInfo return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE; } + BOOL HasAutoLayoutField() const + { + LIMITED_METHOD_CONTRACT; + return (m_bFlags & e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) == e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT; + } + BYTE GetPackingSize() const { LIMITED_METHOD_CONTRACT; @@ -453,6 +461,13 @@ class EEClassLayoutInfo m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE) : (m_bFlags & ~e_HAS_EXPLICIT_SIZE); } + + void SetHasAutoLayoutField(BOOL hasAutoLayoutField) + { + LIMITED_METHOD_CONTRACT; + m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) + : (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT); + } }; // @@ -1395,6 +1410,8 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! BOOL HasExplicitSize(); + BOOL IsAutoLayoutOrHasAutoLayoutField(); + static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar); /* @@ -2082,6 +2099,13 @@ inline BOOL EEClass::HasExplicitSize() return HasLayout() && GetLayoutInfo()->HasExplicitSize(); } +inline BOOL EEClass::IsAutoLayoutOrHasAutoLayoutField() +{ + LIMITED_METHOD_CONTRACT; + // If this type is not auto + return !HasLayout() || GetLayoutInfo()->HasAutoLayoutField(); +} + //========================================================================== // These routines manage the prestub (a bootstrapping stub that all // FunctionDesc's are initialized with.) diff --git a/src/coreclr/vm/classhash.cpp b/src/coreclr/vm/classhash.cpp index 28c636f7c9aad..7320f7bae72a7 100644 --- a/src/coreclr/vm/classhash.cpp +++ b/src/coreclr/vm/classhash.cpp @@ -267,7 +267,7 @@ VOID EEClassHashTable::ConstructKeyFromData(PTR_EEClassHashEntry pEntry, // IN mdToken mdtUncompressed = UncompressModuleAndClassDef(Data); if (TypeFromToken(mdtUncompressed) == mdtExportedType) { - IfFailThrow(GetModule()->GetClassLoader()->GetAssembly()->GetManifestImport()->GetExportedTypeProps( + IfFailThrow(GetModule()->GetClassLoader()->GetAssembly()->GetMDImport()->GetExportedTypeProps( mdtUncompressed, (LPCSTR *)&pszNameSpace, (LPCSTR *)&pszName, diff --git a/src/coreclr/vm/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp index 90315764cfbc5..b95c6d4108ed4 100644 --- a/src/coreclr/vm/classlayoutinfo.cpp +++ b/src/coreclr/vm/classlayoutinfo.cpp @@ -226,23 +226,18 @@ namespace *pLargestAlignmentRequirementOut = LargestAlignmentRequirement; } - //======================================================================= - // This function returns TRUE if the provided corElemType disqualifies - // the structure from being a managed-sequential structure. - // The fsig parameter is used when the corElemType doesn't contain enough information - // to successfully determine if this field disqualifies the type from being - // managed-sequential. - // This function also fills in the pManagedPlacementInfo structure for this field. - //======================================================================= - BOOL CheckIfDisqualifiedFromManagedSequential(CorElementType corElemType, MetaSig& fsig, RawFieldPlacementInfo* pManagedPlacementInfo) + RawFieldPlacementInfo GetFieldPlacementInfo(CorElementType corElemType, TypeHandle pNestedType) { - pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; - pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE; + RawFieldPlacementInfo placementInfo; + // Initialize offset to a dummy value as we set it to the correct value later. + placementInfo.m_offset = (UINT32)-1; + placementInfo.m_size = TARGET_POINTER_SIZE; + placementInfo.m_alignment = TARGET_POINTER_SIZE; // This type may qualify for ManagedSequential. Collect managed size and alignment info. if (CorTypeInfo::IsPrimitiveType(corElemType)) { // Safe cast - no primitive type is larger than 4gb! - pManagedPlacementInfo->m_size = ((UINT32)CorTypeInfo::Size(corElemType)); + placementInfo.m_size = ((UINT32)CorTypeInfo::Size(corElemType)); #if defined(TARGET_X86) && defined(UNIX_X86_ABI) switch (corElemType) { @@ -251,67 +246,87 @@ namespace case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R8: { - pManagedPlacementInfo->m_alignment = 4; + placementInfo.m_alignment = 4; break; } default: { - pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size; + placementInfo.m_alignment = placementInfo.m_size; break; } } #else // TARGET_X86 && UNIX_X86_ABI - pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size; + placementInfo.m_alignment = placementInfo.m_size; #endif - return FALSE; } else if (corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR) { - pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE; - pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; - - return FALSE; + placementInfo.m_size = TARGET_POINTER_SIZE; + placementInfo.m_alignment = TARGET_POINTER_SIZE; } else if (corElemType == ELEMENT_TYPE_VALUETYPE) { - TypeHandle pNestedType = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes, - CLASS_LOAD_APPROXPARENTS, - TRUE); + _ASSERTE(!pNestedType.IsNull()); - pManagedPlacementInfo->m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes()); + placementInfo.m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes()); #if !defined(TARGET_64BIT) && (DATA_ALIGNMENT > 4) - if (pManagedPlacementInfo->m_size >= DATA_ALIGNMENT) + if (placementInfo.m_size >= DATA_ALIGNMENT) { - pManagedPlacementInfo->m_alignment = DATA_ALIGNMENT; + placementInfo.m_alignment = DATA_ALIGNMENT; } else #elif defined(FEATURE_64BIT_ALIGNMENT) if (pNestedType.RequiresAlign8()) { - pManagedPlacementInfo->m_alignment = 8; + placementInfo.m_alignment = 8; } else #endif // FEATURE_64BIT_ALIGNMENT if (pNestedType.GetMethodTable()->ContainsPointers()) { // this field type has GC pointers in it, which need to be pointer-size aligned - // so do this if it has not been done already - pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; + placementInfo.m_alignment = TARGET_POINTER_SIZE; } else { - pManagedPlacementInfo->m_alignment = pNestedType.GetMethodTable()->GetFieldAlignmentRequirement(); + placementInfo.m_alignment = pNestedType.GetMethodTable()->GetFieldAlignmentRequirement(); } - // Types that have GC Pointer fields (objects or byrefs) are disqualified from ManagedSequential layout. - return pNestedType.GetMethodTable()->ContainsPointers() != FALSE; } // No other type permitted for ManagedSequential. + return placementInfo; + } + + BOOL TypeHasGCPointers(CorElementType corElemType, TypeHandle pNestedType) + { + if (CorTypeInfo::IsPrimitiveType(corElemType) || corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR) + { + return FALSE; + } + if (corElemType == ELEMENT_TYPE_VALUETYPE) + { + _ASSERTE(!pNestedType.IsNull()); + return pNestedType.GetMethodTable()->ContainsPointers() != FALSE; + } return TRUE; } + BOOL TypeHasAutoLayoutField(CorElementType corElemType, TypeHandle pNestedType) + { + if (CorTypeInfo::IsPrimitiveType(corElemType) || corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR) + { + return FALSE; + } + if (corElemType == ELEMENT_TYPE_VALUETYPE) + { + _ASSERTE(!pNestedType.IsNull()); + return pNestedType.IsEnum() || pNestedType.GetMethodTable()->IsAutoLayoutOrHasAutoLayoutField(); + } + return FALSE; + } + #ifdef UNIX_AMD64_ABI void SystemVAmd64CheckForPassNativeStructInRegister(MethodTable* pMT, EEClassNativeLayoutInfo* pNativeLayoutInfo) { @@ -437,6 +452,7 @@ namespace ParseNativeTypeFlags nativeTypeFlags, const SigTypeContext* pTypeContext, BOOL* fDisqualifyFromManagedSequential, + BOOL* fHasAutoLayoutField, LayoutRawFieldInfo* pFieldInfoArrayOut, BOOL* pIsBlittableOut, ULONG* cInstanceFields @@ -505,7 +521,16 @@ namespace #endif MetaSig fsig(pCOMSignature, cbCOMSignature, pModule, pTypeContext, MetaSig::sigField); CorElementType corElemType = fsig.NextArgNormalized(); - *fDisqualifyFromManagedSequential |= CheckIfDisqualifiedFromManagedSequential(corElemType, fsig, &pFieldInfoArrayOut->m_placement); + TypeHandle typeHandleMaybe; + if (corElemType == ELEMENT_TYPE_VALUETYPE) // Only look up the next element in the signature if it is a value type to avoid causing recursive type loads in valid scenarios. + { + typeHandleMaybe = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes, + CLASS_LOAD_APPROXPARENTS, + TRUE); + } + pFieldInfoArrayOut->m_placement = GetFieldPlacementInfo(corElemType, typeHandleMaybe); + *fDisqualifyFromManagedSequential |= TypeHasGCPointers(corElemType, typeHandleMaybe); + *fHasAutoLayoutField |= TypeHasAutoLayoutField(corElemType, typeHandleMaybe); if (!IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags)) *pIsBlittableOut = FALSE; @@ -598,6 +623,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( // Running tote - if anything in this type disqualifies it from being ManagedSequential, somebody will set this to TRUE by the the time // function exits. BOOL fDisqualifyFromManagedSequential; + BOOL hasAutoLayoutField = FALSE; // Check if this type might be ManagedSequential. Only valuetypes marked Sequential can be // ManagedSequential. Other issues checked below might also disqualify the type. @@ -612,6 +638,11 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( fDisqualifyFromManagedSequential = TRUE; } + if (pParentMT && !pParentMT->IsValueTypeClass() && pParentMT->IsAutoLayoutOrHasAutoLayoutField()) + { + hasAutoLayoutField = TRUE; + } + BOOL fHasNonTrivialParent = pParentMT && !pParentMT->IsObjectClass() && @@ -659,6 +690,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( nativeTypeFlags, pTypeContext, &fDisqualifyFromManagedSequential, + &hasAutoLayoutField, pInfoArrayOut, &isBlittable, &cInstanceFields @@ -671,6 +703,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( isBlittable = isBlittable && (fHasNonTrivialParent ? pParentMT->IsBlittable() : TRUE); pEEClassLayoutInfoOut->SetIsBlittable(isBlittable); + pEEClassLayoutInfoOut->SetHasAutoLayoutField(hasAutoLayoutField); + S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*)); if (cbSortArraySize.IsOverflow()) { diff --git a/src/coreclr/vm/classnames.h b/src/coreclr/vm/classnames.h index 94e9b1025c7a4..7d71ce2c7d891 100644 --- a/src/coreclr/vm/classnames.h +++ b/src/coreclr/vm/classnames.h @@ -113,4 +113,6 @@ #define g_CriticalFinalizerObjectName "CriticalFinalizerObject" +#define g_DisableRuntimeMarshallingAttribute "System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute" + #endif //!__CLASSNAMES_H__ diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index a2b0129e2dd71..c1a5ffb86ecd9 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -563,7 +563,7 @@ BOOL ClassLoader::IsNested(Module *pModule, mdToken token, mdToken *mdEncloser) (*mdEncloser != mdTypeRefNil)); case mdtExportedType: - IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetExportedTypeProps( + IfFailThrow(pModule->GetAssembly()->GetMDImport()->GetExportedTypeProps( token, NULL, // namespace NULL, // name @@ -643,17 +643,11 @@ void ClassLoader::GetClassValue(NameHandleTable nhTable, #endif PTR_Assembly assembly = GetAssembly(); - PREFIX_ASSUME(assembly != NULL); - ModuleIterator i = assembly->IterateModules(); + Module * pCurrentClsModule = assembly->GetModule(); + _ASSERTE(pCurrentClsModule != NULL); - while (i.Next()) + if (!pLookInThisModuleOnly || (pCurrentClsModule == pLookInThisModuleOnly)) { - Module * pCurrentClsModule = i.GetModule(); - PREFIX_ASSUME(pCurrentClsModule != NULL); - - if (pLookInThisModuleOnly && (pCurrentClsModule != pLookInThisModuleOnly)) - continue; - #ifdef FEATURE_READYTORUN if (nhTable == nhCaseSensitive && pCurrentClsModule->IsReadyToRun() && pCurrentClsModule->GetReadyToRunInfo()->HasHashtableOfTypes() && pCurrentClsModule->GetAvailableClassHash() == NULL) @@ -744,7 +738,7 @@ void ClassLoader::GetClassValue(NameHandleTable nhTable, (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL); break; case mdtExportedType: - while ((!CompareNestedEntryWithExportedType(pNameModule->GetAssembly()->GetManifestImport(), + while ((!CompareNestedEntryWithExportedType(pNameModule->GetAssembly()->GetMDImport(), mdEncloser, pCurrentClsModule->GetAvailableClassHash(), pBucket->GetEncloser())) && @@ -838,16 +832,11 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() _ASSERT(m_cUnhashedModules > 0); AllocMemTracker amTracker; - ModuleIterator i = GetAssembly()->IterateModules(); - // Create a case-sensitive hashtable for each module, and fill it with the module's typedef entries - while (i.Next()) + // Create a case-sensitive hashtable for the module, and fill it with the module's typedef entries + Module *pModule = GetAssembly()->GetModule(); + if (pModule->GetAvailableClassHash() == NULL) { - Module *pModule = i.GetModule(); - PREFIX_ASSUME(pModule != NULL); - if (pModule->GetAvailableClassHash() != NULL) - continue; - // Lazy construction of the case-sensitive hashtable of types is *only* a scenario for ReadyToRun images // (either images compiled with an old version of crossgen, or for case-insensitive type lookups in R2R modules) _ASSERT(pModule->IsReadyToRun()); @@ -858,14 +847,14 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() PopulateAvailableClassHashTable(pModule, &amTracker); } - // Add exported types of the manifest module to the hashtable - IMDInternalImport * pManifestImport = GetAssembly()->GetManifestImport(); + // Add exported types to the hashtable + IMDInternalImport * pManifestImport = GetAssembly()->GetMDImport(); HENUMInternalHolder phEnum(pManifestImport); phEnum.EnumInit(mdtExportedType, mdTokenNil); mdToken mdExportedType; while (pManifestImport->EnumNext(&phEnum, &mdExportedType)) - AddExportedTypeHaveLock(GetAssembly()->GetManifestModule(), mdExportedType, &amTracker); + AddExportedTypeHaveLock(GetAssembly()->GetModule(), mdExportedType, &amTracker); amTracker.SuppressRelease(); } @@ -882,7 +871,7 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() } CONTRACTL_END; - if (GetAssembly()->GetManifestModule()->GetAvailableClassHash() == NULL) + if (GetAssembly()->GetModule()->GetAvailableClassHash() == NULL) { // This is a R2R assembly, and a case insensitive type lookup was triggered. // Construct the case-sensitive table first, since the case-insensitive table @@ -893,28 +882,23 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() // Add any unhashed modules into our hash tables, and try again. AllocMemTracker amTracker; - ModuleIterator i = GetAssembly()->IterateModules(); - - while (i.Next()) + Module *pModule = GetAssembly()->GetModule(); + if (pModule->GetAvailableClassCaseInsHash() == NULL) { - Module *pModule = i.GetModule(); - if (pModule->GetAvailableClassCaseInsHash() == NULL) - { - EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker); + EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker); - LOG((LF_CLASSLOADER, LL_INFO10, "%s's classes being added to case insensitive hash table\n", - pModule->GetSimpleName())); + LOG((LF_CLASSLOADER, LL_INFO10, "%s's classes being added to case insensitive hash table\n", + pModule->GetSimpleName())); - { - CANNOTTHROWCOMPLUSEXCEPTION(); - FAULT_FORBID(); + { + CANNOTTHROWCOMPLUSEXCEPTION(); + FAULT_FORBID(); - amTracker.SuppressRelease(); - pModule->SetAvailableClassCaseInsHash(pNewClassCaseInsHash); - FastInterlockDecrement((LONG*)&m_cUnhashedModules); + amTracker.SuppressRelease(); + pModule->SetAvailableClassCaseInsHash(pNewClassCaseInsHash); + FastInterlockDecrement((LONG*)&m_cUnhashedModules); - _ASSERT(m_cUnhashedModules >= 0); - } + _ASSERT(m_cUnhashedModules >= 0); } } } @@ -1498,7 +1482,7 @@ ClassLoader::LoadTypeHandleThrowing( if (typeHnd.IsNull() || !CompareNameHandleWithTypeHandleNoThrow(pName, typeHnd)) { if (SUCCEEDED(pClsLdr->FindTypeDefByExportedType( - pClsLdr->GetAssembly()->GetManifestImport(), + pClsLdr->GetAssembly()->GetMDImport(), FoundExportedType, pFoundModule->GetMDImport(), &FoundCl))) @@ -1860,16 +1844,8 @@ void ClassLoader::FreeModules() CONTRACTL_END; Module *pManifest = NULL; - if (GetAssembly() && (NULL != (pManifest = GetAssembly()->GetManifestModule()))) { - // Unload the manifest last, since it contains the module list in its rid map - ModuleIterator i = GetAssembly()->IterateModules(); - while (i.Next()) { - // Have the module free its various tables and some of the EEClass links - if (i.GetModule() != pManifest) - i.GetModule()->Destruct(); - } - - // Now do the manifest module. + if (GetAssembly() && (NULL != (pManifest = GetAssembly()->GetModule()))) + { pManifest->Destruct(); } @@ -3267,15 +3243,6 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey, UINT32 typeLoad = ETW::TypeSystemLog::TypeLoadBegin(); #endif - // When using domain neutral assemblies (and not eagerly propagating dependency loads), - // it's possible to get here without having injected the module into the current app domain. - // GetDomainFile will accomplish that. - - if (!pTypeKey->IsConstructed()) - { - pTypeKey->GetModule()->GetDomainFile(); - } - ClassLoadLevel currentLevel = typeHnd.IsNull() ? CLASS_LOAD_BEGIN : typeHnd.GetLoadLevel(); ClassLoadLevel targetLevelUnderLock = targetLevel < CLASS_DEPENDENCIES_LOADED ? targetLevel : (ClassLoadLevel) (CLASS_DEPENDENCIES_LOADED-1); if (currentLevel < targetLevelUnderLock) @@ -5159,12 +5126,7 @@ ClassLoader::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) if (m_pAssembly.IsValid()) { - ModuleIterator modIter = GetAssembly()->IterateModules(); - - while (modIter.Next()) - { - modIter.GetModule()->EnumMemoryRegions(flags, true); - } + m_pAssembly->GetModule()->EnumMemoryRegions(flags, true); } } diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index 8fa82da46db6e..d59e13d45d45d 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -2036,18 +2036,15 @@ HRESULT CodeVersionManager::EnumerateDomainClosedMethodDescs( // these are the default flags which won't actually be used in shared mode other than // asserting they were specified with their default values AssemblyIterationFlags assemFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution); - ModuleIterationOption moduleFlags = (ModuleIterationOption)kModIterIncludeLoaded; if (pAppDomainToSearch != NULL) { assemFlags = (AssemblyIterationFlags)(kIncludeAvailableToProfilers | kIncludeExecution); - moduleFlags = (ModuleIterationOption)kModIterIncludeAvailableToProfilers; } LoadedMethodDescIterator it( pAppDomainToSearch, pModuleContainingMethodDef, methodDef, - assemFlags, - moduleFlags); + assemFlags); CollectibleAssemblyHolder pDomainAssembly; while (it.Next(pDomainAssembly.This())) { diff --git a/src/coreclr/vm/comdynamic.cpp b/src/coreclr/vm/comdynamic.cpp index 4996b53e2e48c..99a6c788b1e4f 100644 --- a/src/coreclr/vm/comdynamic.cpp +++ b/src/coreclr/vm/comdynamic.cpp @@ -900,12 +900,8 @@ void UpdateRuntimeStateForAssemblyCustomAttribute(Module* pModule, mdToken tkCus actualFlags = ((DWORD)pAssembly->GetDebuggerInfoBits() & mask) | flags; pAssembly->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); - ModuleIterator i = pAssembly->IterateModules(); - while (i.Next()) - { - actualFlags = ((DWORD)(i.GetModule()->GetDebuggerInfoBits()) & mask) | flags; - i.GetModule()->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); - } + actualFlags = ((DWORD)(pAssembly->GetModule()->GetDebuggerInfoBits()) & mask) | flags; + pAssembly->GetModule()->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); } // InternalsVisibleTo and IgnoresAccessChecksTo attribute processing diff --git a/src/coreclr/vm/commodule.cpp b/src/coreclr/vm/commodule.cpp index f19482c2a59f3..cd2b5ab843456 100644 --- a/src/coreclr/vm/commodule.cpp +++ b/src/coreclr/vm/commodule.cpp @@ -256,13 +256,13 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRef(QCall::ModuleHandle pModul } SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); CQuickBytes qbNewSig; ULONG cbNewSig; IfFailThrow( pRefedModule->GetMDImport()->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash value pvComSig, cbComSig, @@ -335,7 +335,7 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRefOfMethodInfo(QCall::ModuleH Assembly * pRefingAssembly = pModule->GetAssembly(); SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); CQuickBytes qbNewSig; ULONG cbNewSig; @@ -349,7 +349,7 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRefOfMethodInfo(QCall::ModuleH } IfFailThrow( pMeth->GetMDImport()->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash blob value pvComSig, cbComSig, @@ -421,14 +421,14 @@ extern "C" mdMemberRef QCALLTYPE ModuleBuilder_GetMemberRefOfFieldInfo(QCall::Mo COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible")); } SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); // Translate the field signature this scope CQuickBytes qbNewSig; ULONG cbNewSig; IfFailThrow( pRefedMDImport->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash value pvComSig, cbComSig, @@ -499,14 +499,20 @@ extern "C" void QCALLTYPE ModuleBuilder_SetFieldRVAContent(QCall::ModuleHandle p if (pReflectionModule->m_sdataSection == 0) IfFailThrow( pGen->GetSectionCreate (".sdata", sdReadWrite, &pReflectionModule->m_sdataSection) ); + // Define the alignment that the rva will be set to. Since the CoreCLR runtime only has hard alignment requirements + // up to 8 bytes, the highest alignment we may need is 8 byte alignment. This hard alignment requirement is only needed + // by Runtime.Helpers.CreateSpan. Since the previous alignment was 4 bytes before CreateSpan was implemented, if the + // data isn't itself of size divisible by 8, just align to 4 to the memory cost of excess alignment. + DWORD alignment = (length % 8 == 0) ? 8 : 4; + // Get the size of current .sdata section. This will be the RVA for this field within the section DWORD dwRVA = 0; IfFailThrow( pGen->GetSectionDataLen(pReflectionModule->m_sdataSection, &dwRVA) ); - dwRVA = (dwRVA + sizeof(DWORD)-1) & ~(sizeof(DWORD)-1); + dwRVA = (dwRVA + alignment-1) & ~(alignment-1); // allocate the space in .sdata section void * pvBlob; - IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, sizeof(DWORD), (void**) &pvBlob) ); + IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, alignment, (void**) &pvBlob) ); // copy over the initialized data if specified if (pContent != NULL) diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index bcd9af84555c6..c2fff3f9c9a96 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -120,8 +120,6 @@ typedef DPTR(class ComPlusCallMethodDesc) PTR_ComPlusCallMethodDesc; typedef VPTR(class DebugInterface) PTR_DebugInterface; typedef DPTR(class Dictionary) PTR_Dictionary; typedef VPTR(class DomainAssembly) PTR_DomainAssembly; -typedef VPTR(class DomainFile) PTR_DomainFile; -typedef VPTR(class DomainModule) PTR_DomainModule; typedef DPTR(struct FailedAssembly) PTR_FailedAssembly; typedef VPTR(class EditAndContinueModule) PTR_EditAndContinueModule; typedef DPTR(class EEClass) PTR_EEClass; @@ -429,7 +427,6 @@ extern DummyGlobalContract ___contract; #include "typehandle.inl" #include "object.inl" #include "clsload.inl" -#include "domainfile.inl" #include "method.inl" #include "syncblk.inl" #include "threads.inl" diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index eaaddafdbe9c6..2da6e14750d71 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -15,7 +15,7 @@ #include "appdomain.inl" #include #include "peimagelayout.inl" -#include "domainfile.h" +#include "domainassembly.h" #include "holder.h" #include "bundle.h" #include "strongnameinternal.h" diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp index 707cd24274148..54bb5177cae53 100644 --- a/src/coreclr/vm/corelib.cpp +++ b/src/coreclr/vm/corelib.cpp @@ -32,7 +32,6 @@ #include "comdatetime.h" #include "compatibilityswitch.h" #include "debugdebugger.h" -#include "assemblyname.hpp" #include "assemblynative.hpp" #include "comthreadpool.h" #include "comwaithandle.h" diff --git a/src/coreclr/vm/dacenumerablehash.inl b/src/coreclr/vm/dacenumerablehash.inl index e4e5de3b11f3f..049329bbfbc67 100644 --- a/src/coreclr/vm/dacenumerablehash.inl +++ b/src/coreclr/vm/dacenumerablehash.inl @@ -400,8 +400,8 @@ namespace HashTableDetail { // Use the C++ detection idiom (https://isocpp.org/blog/2017/09/detection-idiom-a-stopgap-for-concepts-simon-brand) to call the // derived table's EnumMemoryRegionsForEntry method if it defines one. - template - using void_t = void; + template struct make_void { using type = void; }; + template using void_t = typename make_void::type; template struct negation : std::integral_constant { }; diff --git a/src/coreclr/vm/dbginterface.h b/src/coreclr/vm/dbginterface.h index 51b2c3bf36358..c9bc65c33fd28 100644 --- a/src/coreclr/vm/dbginterface.h +++ b/src/coreclr/vm/dbginterface.h @@ -68,7 +68,7 @@ class DebugInterface DWORD dwModuleName, // number of characters in file name excludign null Assembly * pAssembly, // the assembly the module belongs to AppDomain * pAppDomain, // the AppDomain the module is being loaded into - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching) = 0; // true if this notification is due to a debugger // being attached to the process @@ -242,7 +242,7 @@ class DebugInterface // send a custom notification from the target to the RS. This will become an ICorDebugThread and // ICorDebugAppDomain on the RS. - virtual void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomainFile, mdTypeDef classToken) = 0; + virtual void SendCustomDebuggerNotification(Thread * pThread, DomainAssembly * pDomainAssembly, mdTypeDef classToken) = 0; // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side. virtual void SendMDANotification( diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index 2ade537044abb..566bb74d6d3eb 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -827,11 +827,11 @@ FCIMPL1(void, DebugDebugger::CustomNotification, Object * dataUNSAFE) StrongHandleHolder objHandle = pAppDomain->CreateStrongHandle(pData); MethodTable * pMT = pData->GetGCSafeMethodTable(); Module * pModule = pMT->GetModule(); - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); mdTypeDef classToken = pMT->GetCl(); pThread->SetThreadCurrNotification(objHandle); - g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainFile, classToken); + g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainAssembly, classToken); pThread->ClearThreadCurrNotification(); if (pThread->IsAbortRequested()) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 6c4ce7608660e..3a35a8e108fa4 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -107,6 +107,7 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD) m_tkMethodDef = pMD->GetMemberDef(); SigTypeContext::InitTypeContext(pMD, &m_typeContext); + m_pMetadataModule = pMD->GetModule(); m_pLoaderModule = pMD->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation. INDEBUG(InitDebugNames()); @@ -133,11 +134,13 @@ StubSigDesc::StubSigDesc(MethodDesc* pMD, const Signature& sig, Module* pModule) { m_tkMethodDef = pMD->GetMemberDef(); SigTypeContext::InitTypeContext(pMD, &m_typeContext); + m_pMetadataModule = pMD->GetModule(); m_pLoaderModule = pMD->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation. } else { m_tkMethodDef = mdMethodDefNil; + m_pMetadataModule = m_pModule; m_pLoaderModule = m_pModule; } @@ -166,7 +169,8 @@ StubSigDesc::StubSigDesc(MethodTable* pMT, const Signature& sig, Module* pModule if (pMT != NULL) { SigTypeContext::InitTypeContext(pMT, &m_typeContext); - m_pLoaderModule = pMT->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation. + m_pMetadataModule = pMT->GetModule(); + m_pLoaderModule = pMT->GetLoaderModule(); } else { @@ -193,6 +197,7 @@ StubSigDesc::StubSigDesc(const Signature& sig, Module* pModule) m_sig = sig; m_pModule = pModule; m_tkMethodDef = mdMethodDefNil; + m_pMetadataModule = m_pModule; m_pLoaderModule = m_pModule; INDEBUG(InitDebugNames()); @@ -959,7 +964,7 @@ class ILStubState : public StubState if (pTargetMD) { pTargetMD->GetMethodInfoWithNewSig(strNamespaceOrClassName, strMethodName, strMethodSignature); - uModuleId = (UINT64)pTargetMD->GetModule()->GetAddrModuleID(); + uModuleId = (UINT64)(TADDR)pTargetMD->GetModule_NoLogging(); } // @@ -3287,6 +3292,15 @@ BOOL NDirect::MarshalingRequired( } CollateParamTokens(pMDImport, methodToken, numArgs - 1, pParamTokenArray); + // We enable the runtime marshalling system whenever it is enabled on the module as a whole + // or when the call is a COM interop call. COM interop calls are already using a significant portion of the runtime + // marshalling system just to function at all, so we aren't going to disable the parameter marshalling; + // we'd rather have developers use the feature flag to diable the whole COM interop subsystem at once. + bool runtimeMarshallingEnabled = pModule->IsRuntimeMarshallingEnabled(); +#ifdef FEATURE_COMINTEROP + runtimeMarshallingEnabled |= pMD && pMD->IsComPlusCall(); +#endif + for (ULONG i = 0; i < numArgs; i++) { SigPointer arg = ptr; @@ -3300,7 +3314,7 @@ BOOL NDirect::MarshalingRequired( IfFailThrow(arg.GetElemType(NULL)); // skip ELEMENT_TYPE_PTR IfFailThrow(arg.PeekElemType(&type)); - if (type == ELEMENT_TYPE_VALUETYPE) + if (runtimeMarshallingEnabled && type == ELEMENT_TYPE_VALUETYPE) { if ((arg.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", @@ -3331,11 +3345,21 @@ BOOL NDirect::MarshalingRequired( { TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext); - // JIT can handle internal blittable value types - if (!hndArgType.IsBlittable() && !hndArgType.IsEnum()) + // When the runtime runtime marshalling system is disabled, we don't support + // any types that contain gc pointers, but all "unmanaged" types are treated as blittable + // as long as they aren't auto-layout and don't have any auto-layout fields. + if (!runtimeMarshallingEnabled && + (hndArgType.GetMethodTable()->ContainsPointers() + || hndArgType.GetMethodTable()->IsAutoLayoutOrHasAutoLayoutField())) { return TRUE; } + else if (runtimeMarshallingEnabled && !hndArgType.IsBlittable() && !hndArgType.IsEnum()) + { + // When the runtime runtime marshalling system is enabled, we do special handling + // for any types that aren't blittable or enums. + return TRUE; + } if (i > 0) { @@ -3348,10 +3372,15 @@ BOOL NDirect::MarshalingRequired( case ELEMENT_TYPE_BOOLEAN: case ELEMENT_TYPE_CHAR: { + // When runtime marshalling is enabled: // Bool requires marshaling // Char may require marshaling (MARSHAL_TYPE_ANSICHAR) - return TRUE; + if (runtimeMarshallingEnabled) + { + return TRUE; + } } + FALLTHROUGH; default: { @@ -3376,7 +3405,10 @@ BOOL NDirect::MarshalingRequired( // check for explicit MarshalAs NativeTypeParamInfo paramInfo; - if (pParamTokenArray[i] != mdParamDefNil) + // We only check the MarshalAs info when the runtime marshalling system is enabled. + // We ignore MarshalAs when the system is disabled, so no reason to disqualify from inlining + // when it is present. + if (runtimeMarshallingEnabled && pParamTokenArray[i] != mdParamDefNil) { if (!ParseNativeTypeInfo(pParamTokenArray[i], pMDImport, ¶mInfo) || paramInfo.m_NativeType != NATIVE_TYPE_DEFAULT) @@ -3594,6 +3626,7 @@ static void CreateNDirectStubWorker(StubState* pss, CONSISTENCY_CHECK_MSGF(false, ("BreakOnInteropStubSetup: '%s' ", pSigDesc->m_pDebugName)); #endif // _DEBUG + bool runtimeMarshallingEnabled = SF_IsCOMStub(dwStubFlags) || pSigDesc->m_pMetadataModule->IsRuntimeMarshallingEnabled(); if (SF_IsCOMStub(dwStubFlags)) { _ASSERTE(0 == nlType); @@ -3615,26 +3648,48 @@ static void CreateNDirectStubWorker(StubState* pss, &pSigDesc->m_typeContext); if (SF_IsVarArgStub(dwStubFlags)) + { + if (!runtimeMarshallingEnabled) + { + COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS); + } msig.SetTreatAsVarArg(); + } bool fThisCall = (unmgdCallConv == CorInfoCallConvExtension::Thiscall); - pss->SetLastError(nlFlags & nlfLastError); + if (nlFlags & nlfLastError) + { + if (!runtimeMarshallingEnabled) + { + COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR); + } + pss->SetLastError(TRUE); + } // This has been in the product since forward P/Invoke via delegates was // introduced. It's wrong, but please keep it for backward compatibility. - if (SF_IsDelegateStub(dwStubFlags)) + if (runtimeMarshallingEnabled && SF_IsDelegateStub(dwStubFlags)) pss->SetLastError(TRUE); pss->BeginEmit(dwStubFlags); if (-1 != iLCIDArg) { - // The code to handle the LCID will call MarshalLCID before calling MarshalArgument + if (!runtimeMarshallingEnabled) + { + COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID); + } + // The code to handle the LCID will call MarshalLCID before calling MarshalArgument // on the argument the LCID should go after. So we just bump up the index here. iLCIDArg++; } + if (!runtimeMarshallingEnabled && SF_IsHRESULTSwapping(dwStubFlags)) + { + COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG); + } + int numArgs = msig.NumFixedArgs(); // thiscall must have at least one parameter (the "this") diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index f731823ff4a0b..8b472e3a0aafb 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -23,7 +23,15 @@ struct StubSigDesc MethodDesc *m_pMD; MethodTable *m_pMT; Signature m_sig; + // Module to use for signature reading. Module *m_pModule; + // Module that owns any metadata that influences interop behavior. + // This is usually the same as m_pModule, but can differ with vararg + // P/Invokes, where the calling assembly's module is assigned to m_pModule + // since the specific caller signature is defined in that assembly, not the + // assembly that defined the P/Invoke. + Module *m_pMetadataModule; + // Used for ILStubCache selection and MethodTable creation. Module *m_pLoaderModule; mdMethodDef m_tkMethodDef; SigTypeContext m_typeContext; diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp index 455d33813eec0..65d2afd7d0512 100644 --- a/src/coreclr/vm/dllimportcallback.cpp +++ b/src/coreclr/vm/dllimportcallback.cpp @@ -195,37 +195,6 @@ extern "C" VOID STDCALL ReversePInvokeBadTransition() ); } -// Disable from a place that is calling into managed code via a UMEntryThunk. -extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThunk *pUMEntryThunk) -{ - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_TRIGGERS; - - // Do not add a CONTRACT here. We haven't set up SEH. - - // WARNING!!!! - // when we start executing here, we are actually in cooperative mode. But we - // haven't synchronized with the barrier to reentry yet. So we are in a highly - // dangerous mode. If we call managed code, we will potentially be active in - // the GC heap, even as GC's are occuring! - - // We must do the following in this order, because otherwise we would be constructing - // the exception for the abort without synchronizing with the GC. Also, we have no - // CLR SEH set up, despite the fact that we may throw a ThreadAbortException. - pThread->RareDisablePreemptiveGC(); - pThread->HandleThreadAbort(); - -#ifdef DEBUGGING_SUPPORTED - // If the debugger is attached, we use this opportunity to see if - // we're disabling preemptive GC on the way into the runtime from - // unmanaged code. We end up here because - // Increment/DecrementTraceCallCount() will bump - // g_TrapReturningThreads for us. - if (CORDebuggerTraceCall()) - g_pDebugInterface->TraceCall((const BYTE *)pUMEntryThunk->GetManagedTarget()); -#endif // DEBUGGING_SUPPORTED -} - PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk) { STATIC_CONTRACT_THROWS; @@ -234,39 +203,13 @@ PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk) Thread * pThread = GetThreadNULLOk(); if (pThread == NULL) - pThread = CreateThreadBlockThrow(); - - GCX_COOP_THREAD_EXISTS(pThread); - - if (pThread->IsAbortRequested()) - pThread->HandleThreadAbort(); - - UMEntryThunk::DoRunTimeInit(pUMEntryThunk); - - return (PCODE)pUMEntryThunk->GetCode(); -} - -void RunTimeInit_Wrapper(LPVOID /* UMThunkMarshInfo * */ ptr) -{ - WRAPPER_NO_CONTRACT; - - UMEntryThunk::DoRunTimeInit((UMEntryThunk*)ptr); -} - - -// asm entrypoint -void STDCALL UMEntryThunk::DoRunTimeInit(UMEntryThunk* pUMEntryThunk) -{ - - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - ENTRY_POINT; - PRECONDITION(CheckPointer(pUMEntryThunk)); + CREATETHREAD_IF_NULL_FAILFAST(pThread, W("Failed to setup new thread during reverse P/Invoke")); } - CONTRACTL_END; + + // Verify the current thread isn't in COOP mode. + if (pThread->PreemptiveGCDisabled()) + ReversePInvokeBadTransition(); INSTALL_MANAGED_EXCEPTION_DISPATCHER; // this method is called by stubs which are called by managed code, @@ -274,15 +217,13 @@ void STDCALL UMEntryThunk::DoRunTimeInit(UMEntryThunk* pUMEntryThunk) // exceptions don't leak out into managed code. INSTALL_UNWIND_AND_CONTINUE_HANDLER; - { - GCX_PREEMP(); - - ExecutableWriterHolder uMEntryThunkWriterHolder(pUMEntryThunk, sizeof(UMEntryThunk)); - uMEntryThunkWriterHolder.GetRW()->RunTimeInit(pUMEntryThunk); - } + ExecutableWriterHolder uMEntryThunkWriterHolder(pUMEntryThunk, sizeof(UMEntryThunk)); + uMEntryThunkWriterHolder.GetRW()->RunTimeInit(pUMEntryThunk); UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; + + return (PCODE)pUMEntryThunk->GetCode(); } UMEntryThunk* UMEntryThunk::CreateUMEntryThunk() diff --git a/src/coreclr/vm/dllimportcallback.h b/src/coreclr/vm/dllimportcallback.h index 14b7db5704824..fb2214a8c18d5 100644 --- a/src/coreclr/vm/dllimportcallback.h +++ b/src/coreclr/vm/dllimportcallback.h @@ -16,6 +16,12 @@ #include "class.h" #include "dllimport.h" +class UMThunkMarshInfo; +typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo; + +class UMEntryThunk; +typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk; + //---------------------------------------------------------------------- // This structure collects all information needed to marshal an // unmanaged->managed thunk. The only information missing is the @@ -189,9 +195,6 @@ class UMEntryThunk #endif // _DEBUG } - // asm entrypoint - static VOID STDCALL DoRunTimeInit(UMEntryThunk* pThis); - PCODE GetManagedTarget() const { CONTRACT (PCODE) @@ -396,14 +399,7 @@ class UMEntryThunkCache }; #if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) -//------------------------------------------------------------------------- -// One-time creation of special prestub to initialize UMEntryThunks. -//------------------------------------------------------------------------- -Stub *GenerateUMThunkPrestub(); - EXCEPTION_HANDLER_DECL(FastNExportExceptHandler); -EXCEPTION_HANDLER_DECL(UMThunkPrestubHandler); - #endif // TARGET_X86 && !FEATURE_STUBS_AS_IL extern "C" void TheUMEntryPrestub(void); diff --git a/src/coreclr/vm/domainfile.cpp b/src/coreclr/vm/domainassembly.cpp similarity index 80% rename from src/coreclr/vm/domainfile.cpp rename to src/coreclr/vm/domainassembly.cpp index 22796801543b3..458f988280b02 100644 --- a/src/coreclr/vm/domainfile.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- -// DomainFile.cpp +// DomainAssembly.cpp // // -------------------------------------------------------------------------------- @@ -30,33 +30,42 @@ #endif // FEATURE_PERFMAP #ifndef DACCESS_COMPILE -DomainFile::DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly) - : m_pDomain(pDomain), +DomainAssembly::DomainAssembly(AppDomain* pDomain, PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator) : + m_pAssembly(NULL), + m_pDomain(pDomain), m_pPEAssembly(pPEAssembly), m_pModule(NULL), + m_fCollectible(pLoaderAllocator->IsCollectible()), + m_NextDomainAssemblyInSameALC(NULL), + m_pLoaderAllocator(pLoaderAllocator), m_level(FILE_LOAD_CREATE), - m_pError(NULL), - m_notifyflags(NOT_NOTIFIED), m_loading(TRUE), + m_hExposedModuleObject(NULL), + m_hExposedAssemblyObject(NULL), + m_pError(NULL), + m_bDisableActivationCheck(FALSE), + m_fHostAssemblyPublished(FALSE), m_pDynamicMethodTable(NULL), - m_pUMThunkHash(NULL), - m_bDisableActivationCheck(FALSE) + m_debuggerFlags(DACF_NONE), + m_notifyflags(NOT_NOTIFIED), + m_fDebuggerUnloadStarted(FALSE) { CONTRACTL { CONSTRUCTOR_CHECK; - THROWS; // From CreateHandle - GC_NOTRIGGER; + THROWS; // ValidateForExecution + GC_TRIGGERS; // ValidateForExecution MODE_ANY; - FORBID_FAULT; } CONTRACTL_END; - m_hExposedModuleObject = NULL; pPEAssembly->AddRef(); + pPEAssembly->ValidateForExecution(); + + SetupDebuggingConfig(); } -DomainFile::~DomainFile() +DomainAssembly::~DomainAssembly() { CONTRACTL { @@ -70,36 +79,24 @@ DomainFile::~DomainFile() m_pPEAssembly->Release(); if (m_pDynamicMethodTable) m_pDynamicMethodTable->Destroy(); - delete m_pError; -} -#endif //!DACCESS_COMPILE + delete m_pError; -LoaderAllocator * DomainFile::GetLoaderAllocator() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - Assembly *pAssembly = GetDomainAssembly()->GetAssembly(); - if ((pAssembly != NULL) && (pAssembly->IsCollectible())) + if (m_fHostAssemblyPublished) { - return pAssembly->GetLoaderAllocator(); + // Remove association first. + UnregisterFromHostAssembly(); } - else + + if (m_pAssembly != NULL) { - return this->GetAppDomain()->GetLoaderAllocator(); + delete m_pAssembly; } } -#ifndef DACCESS_COMPILE - // Optimization intended for EnsureLoadLevel only #include -void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) +void DomainAssembly::EnsureLoadLevel(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -112,7 +109,7 @@ void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) TRIGGERSGC (); if (IsLoading()) { - this->GetAppDomain()->LoadDomainFile(this, targetLevel); + this->GetAppDomain()->LoadDomainAssembly(this, targetLevel); // Enforce the loading requirement. Note that we may have a deadlock in which case we // may be off by one which is OK. (At this point if we are short of targetLevel we know @@ -127,26 +124,7 @@ void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) } #include -void DomainFile::AttemptLoadLevel(FileLoadLevel targetLevel) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - } - CONTRACT_END; - - if (IsLoading()) - this->GetAppDomain()->LoadDomainFile(this, targetLevel); - else - ThrowIfError(targetLevel); - - RETURN; -} - - -CHECK DomainFile::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) +CHECK DomainAssembly::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) { CONTRACTL { @@ -176,7 +154,7 @@ CHECK DomainFile::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) -void DomainFile::RequireLoadLevel(FileLoadLevel targetLevel) +void DomainAssembly::RequireLoadLevel(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -196,7 +174,7 @@ void DomainFile::RequireLoadLevel(FileLoadLevel targetLevel) } -void DomainFile::SetError(Exception *ex) +void DomainAssembly::SetError(Exception *ex) { CONTRACT_VOID { @@ -211,26 +189,26 @@ void DomainFile::SetError(Exception *ex) m_pError = new ExInfo(ex->DomainBoundClone()); - GetCurrentModule()->NotifyEtwLoadFinished(ex->GetHR()); - - if (!IsProfilerNotified()) + if (m_pModule) { - SetProfilerNotified(); + m_pModule->NotifyEtwLoadFinished(ex->GetHR()); -#ifdef PROFILING_SUPPORTED - if (GetCurrentModule() != NULL) + if (!IsProfilerNotified()) { + SetProfilerNotified(); + +#ifdef PROFILING_SUPPORTED // Only send errors for non-shared assemblies; other assemblies might be successfully completed // in another app domain later. - GetCurrentModule()->NotifyProfilerLoadFinished(ex->GetHR()); - } + m_pModule->NotifyProfilerLoadFinished(ex->GetHR()); #endif + } } RETURN; } -void DomainFile::ThrowIfError(FileLoadLevel targetLevel) +void DomainAssembly::ThrowIfError(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -250,7 +228,7 @@ void DomainFile::ThrowIfError(FileLoadLevel targetLevel) RETURN; } -CHECK DomainFile::CheckNoError(FileLoadLevel targetLevel) +CHECK DomainAssembly::CheckNoError(FileLoadLevel targetLevel) { LIMITED_METHOD_CONTRACT; CHECK(m_level >= targetLevel @@ -259,7 +237,7 @@ CHECK DomainFile::CheckNoError(FileLoadLevel targetLevel) CHECK_OK; } -CHECK DomainFile::CheckLoaded() +CHECK DomainAssembly::CheckLoaded() { CONTRACTL { @@ -270,7 +248,7 @@ CHECK DomainFile::CheckLoaded() } CONTRACTL_END; - CHECK_MSG(CheckNoError(FILE_LOADED), "DomainFile load resulted in an error"); + CHECK_MSG(CheckNoError(FILE_LOADED), "DomainAssembly load resulted in an error"); if (IsLoaded()) CHECK_OK; @@ -287,7 +265,7 @@ CHECK DomainFile::CheckLoaded() CHECK_OK; } -CHECK DomainFile::CheckActivated() +CHECK DomainAssembly::CheckActivated() { CONTRACTL { @@ -298,7 +276,7 @@ CHECK DomainFile::CheckActivated() } CONTRACTL_END; - CHECK_MSG(CheckNoError(FILE_ACTIVE), "DomainFile load resulted in an error"); + CHECK_MSG(CheckNoError(FILE_ACTIVE), "DomainAssembly load resulted in an error"); if (IsActive()) CHECK_OK; @@ -311,7 +289,7 @@ CHECK DomainFile::CheckActivated() CHECK_OK; CHECK_MSG(GetPEAssembly()->IsLoaded(), "PEAssembly has not been loaded"); - CHECK_MSG(IsLoaded(), "DomainFile has not been fully loaded"); + CHECK_MSG(IsLoaded(), "DomainAssembly has not been fully loaded"); CHECK_MSG(m_bDisableActivationCheck || CheckLoadLevel(FILE_ACTIVE), "File has not had execution verified"); CHECK_OK; @@ -319,20 +297,6 @@ CHECK DomainFile::CheckActivated() #endif //!DACCESS_COMPILE -DomainAssembly *DomainFile::GetDomainAssembly() -{ - CONTRACTL - { - SUPPORTS_DAC; - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - _ASSERTE(IsAssembly()); - return (DomainAssembly *) this; -} - // Return true iff the debugger should get notifications about this assembly. // // Notes: @@ -358,7 +322,7 @@ BOOL DomainAssembly::IsVisibleToDebugger() // Returns managed representation of the module (Module or ModuleBuilder). // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). // -OBJECTREF DomainFile::GetExposedModuleObject() +OBJECTREF DomainAssembly::GetExposedModuleObject() { CONTRACTL { @@ -423,9 +387,9 @@ OBJECTREF DomainFile::GetExposedModuleObject() } return pLoaderAllocator->GetHandleValue(m_hExposedModuleObject); -} // DomainFile::GetExposedModuleObject +} -BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) +BOOL DomainAssembly::DoIncrementalLoad(FileLoadLevel level) { STANDARD_VM_CONTRACT; @@ -491,7 +455,7 @@ BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) #ifdef FEATURE_MULTICOREJIT { - Module * pModule = GetModule(); + Module * pModule = m_pModule; if (pModule != NULL) // Should not triggle assert when module is NULL { @@ -503,7 +467,7 @@ BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) return TRUE; } -void DomainFile::PreLoadLibrary() +void DomainAssembly::PreLoadLibrary() { CONTRACTL { @@ -512,11 +476,9 @@ void DomainFile::PreLoadLibrary() } CONTRACTL_END; -} // DomainFile::PreLoadLibrary +} // DomainAssembly::PreLoadLibrary -// Note that this is the sole loading function which must be called OUTSIDE THE LOCK, since -// it will potentially involve the OS loader lock. -void DomainFile::LoadLibrary() +void DomainAssembly::LoadLibrary() { CONTRACTL { @@ -527,7 +489,7 @@ void DomainFile::LoadLibrary() } -void DomainFile::PostLoadLibrary() +void DomainAssembly::PostLoadLibrary() { CONTRACTL { @@ -557,46 +519,46 @@ void DomainFile::PostLoadLibrary() if (!IsProfilerNotified()) { SetProfilerNotified(); - GetCurrentModule()->NotifyProfilerLoadFinished(S_OK); + GetModule()->NotifyProfilerLoadFinished(S_OK); } #endif } -void DomainFile::AddDependencies() +void DomainAssembly::AddDependencies() { STANDARD_VM_CONTRACT; } -void DomainFile::EagerFixups() +void DomainAssembly::EagerFixups() { WRAPPER_NO_CONTRACT; #ifdef FEATURE_READYTORUN - if (GetCurrentModule()->IsReadyToRun()) + if (GetModule()->IsReadyToRun()) { - GetCurrentModule()->RunEagerFixups(); + GetModule()->RunEagerFixups(); - PEImageLayout * pLayout = GetCurrentModule()->GetReadyToRunInfo()->GetImage(); + PEImageLayout * pLayout = GetModule()->GetReadyToRunInfo()->GetImage(); TADDR base = dac_cast(pLayout->GetBase()); ExecutionManager::AddCodeRange(base, base + (TADDR)pLayout->GetVirtualSize(), ExecutionManager::GetReadyToRunJitManager(), RangeSection::RANGE_SECTION_READYTORUN, - GetCurrentModule() /* (void *)pLayout */); + GetModule() /* (void *)pLayout */); } #endif // FEATURE_READYTORUN } -void DomainFile::VtableFixups() +void DomainAssembly::VtableFixups() { WRAPPER_NO_CONTRACT; - GetCurrentModule()->FixupVTables(); + GetModule()->FixupVTables(); } -void DomainFile::FinishLoad() +void DomainAssembly::FinishLoad() { CONTRACTL { @@ -621,7 +583,7 @@ void DomainFile::FinishLoad() #endif } -void DomainFile::Activate() +void DomainAssembly::Activate() { CONTRACT_VOID { @@ -631,24 +593,11 @@ void DomainFile::Activate() } CONTRACT_END; - // If we are a module, ensure we've activated the assembly first. - - if (!IsAssembly()) - { - GetDomainAssembly()->EnsureActive(); - } - else - { - // We cannot execute any code in this assembly until we know what exception plan it is on. - // At the point of an exception's stack-crawl it is too late because we cannot tolerate a GC. - // See PossiblyUnwrapThrowable and its callers. - _ASSERTE(GetLoadedModule() == GetDomainAssembly()->GetLoadedAssembly()->GetManifestModule()); - GetLoadedModule()->IsRuntimeWrapExceptions(); - } - - // Now activate any dependencies. - // This will typically cause reentrancy of course. - + // We cannot execute any code in this assembly until we know what exception plan it is on. + // At the point of an exception's stack-crawl it is too late because we cannot tolerate a GC. + // See PossiblyUnwrapThrowable and its callers. + _ASSERTE(GetModule() == GetAssembly()->GetModule()); + GetModule()->IsRuntimeWrapExceptions(); // // Now call the module constructor. Note that this might cause reentrancy; @@ -669,84 +618,18 @@ void DomainFile::Activate() } #endif //_DEBUG - RETURN; } -//-------------------------------------------------------------------------------- -// DomainAssembly -//-------------------------------------------------------------------------------- - -DomainAssembly::DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator) - : DomainFile(pDomain, pPEAssembly), - m_pAssembly(NULL), - m_debuggerFlags(DACF_NONE), - m_fDebuggerUnloadStarted(FALSE), - m_fCollectible(pLoaderAllocator->IsCollectible()), - m_fHostAssemblyPublished(false), - m_pLoaderAllocator(pLoaderAllocator), - m_NextDomainAssemblyInSameALC(NULL) -{ - CONTRACTL - { - CONSTRUCTOR_CHECK; - STANDARD_VM_CHECK; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - pPEAssembly->ValidateForExecution(); - - // !!! backout - - m_hExposedAssemblyObject = NULL; - - SetupDebuggingConfig(); - - // Add a Module iterator entry for this assembly. - IfFailThrow(m_Modules.Append(this)); -} - -DomainAssembly::~DomainAssembly() -{ - CONTRACTL - { - DESTRUCTOR_CHECK; - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - if (m_fHostAssemblyPublished) - { - // Remove association first. - UnregisterFromHostAssembly(); - } - - ModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) - { - if (i.GetDomainFile() != this) - delete i.GetDomainFile(); - } - - if (m_pAssembly != NULL) - { - delete m_pAssembly; - } -} - void DomainAssembly::SetAssembly(Assembly* pAssembly) { STANDARD_VM_CONTRACT; - _ASSERTE(pAssembly->GetManifestModule()->GetPEAssembly()==m_pPEAssembly); + _ASSERTE(pAssembly->GetModule()->GetPEAssembly()==m_pPEAssembly); _ASSERTE(m_pAssembly == NULL); m_pAssembly = pAssembly; - m_pModule = pAssembly->GetManifestModule(); + m_pModule = pAssembly->GetModule(); pAssembly->SetDomainAssembly(this); } @@ -841,7 +724,7 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject() } return pLoaderAllocator->GetHandleValue(m_hExposedAssemblyObject); -} // DomainAssembly::GetExposedAssemblyObject +} void DomainAssembly::Begin() { @@ -917,8 +800,7 @@ void DomainAssembly::Allocate() } SetAssembly(pAssembly); - -} // DomainAssembly::Allocate +} void DomainAssembly::DeliverAsyncEvents() { @@ -933,10 +815,8 @@ void DomainAssembly::DeliverAsyncEvents() OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE); m_pDomain->RaiseLoadingAssemblyEvent(this); - } - void DomainAssembly::DeliverSyncEvents() { CONTRACTL @@ -946,17 +826,8 @@ void DomainAssembly::DeliverSyncEvents() } CONTRACTL_END; - GetCurrentModule()->NotifyEtwLoadFinished(S_OK); + GetModule()->NotifyEtwLoadFinished(S_OK); - // We may be notified from inside the loader lock if we are delivering IJW events, so keep track. -#ifdef PROFILING_SUPPORTED - if (!IsProfilerNotified()) - { - SetProfilerNotified(); - GetCurrentModule()->NotifyProfilerLoadFinished(S_OK); - } - -#endif #ifdef DEBUGGING_SUPPORTED GCX_COOP(); if (!IsDebuggerNotified()) @@ -968,7 +839,7 @@ void DomainAssembly::DeliverSyncEvents() } #endif // DEBUGGING_SUPPORTED -} // DomainAssembly::DeliverSyncEvents +} /* // The enum for dwLocation from managed code: @@ -1152,7 +1023,6 @@ BOOL DomainAssembly::NotifyDebuggerLoad(int flags, BOOL attaching) } // There is still work we need to do even when no debugger is attached. - if (flags & ATTACH_ASSEMBLY_LOAD) { if (ShouldNotifyDebugger()) @@ -1162,24 +1032,18 @@ BOOL DomainAssembly::NotifyDebuggerLoad(int flags, BOOL attaching) result = TRUE; } - DomainModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) + if(this->ShouldNotifyDebugger()) { - DomainFile * pDomainFile = i.GetDomainFile(); - if(pDomainFile->ShouldNotifyDebugger()) - { - result = result || - pDomainFile->GetModule()->NotifyDebuggerLoad(this->GetAppDomain(), pDomainFile, flags, attaching); - } + result = result || + this->GetModule()->NotifyDebuggerLoad(this->GetAppDomain(), this, flags, attaching); } + if( ShouldNotifyDebugger()) { result|=m_pModule->NotifyDebuggerLoad(m_pDomain, this, ATTACH_MODULE_LOAD, attaching); SetDebuggerNotified(); } - - return result; } @@ -1195,29 +1059,22 @@ void DomainAssembly::NotifyDebuggerUnload() m_fDebuggerUnloadStarted = TRUE; - // Dispatch module unloads for all modules. Debugger is resilient in case we haven't dispatched + // Dispatch module unload for the module. Debugger is resilient in case we haven't dispatched // a previous load event (such as if debugger attached after the modules was loaded). - DomainModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) - { - i.GetDomainFile()->GetModule()->NotifyDebuggerUnload(this->GetAppDomain()); - } + this->GetModule()->NotifyDebuggerUnload(this->GetAppDomain()); g_pDebugInterface->UnloadAssembly(this); - } #endif // #ifndef DACCESS_COMPILE #ifdef DACCESS_COMPILE -void -DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) +void DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { SUPPORTS_DAC; - //sizeof(DomainFile) == 0x60 - DAC_ENUM_VTHIS(); + DAC_ENUM_DTHIS(); // Modules are needed for all minidumps, but they are enumerated elsewhere // so we don't need to duplicate effort; thus we do noting with m_pModule. @@ -1233,19 +1090,6 @@ DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { m_pDomain->EnumMemoryRegions(flags, true); } -} - -void -DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) -{ - SUPPORTS_DAC; - - //sizeof(DomainAssembly) == 0xe0 - DAC_ENUM_VTHIS(); - DomainFile::EnumMemoryRegions(flags); - - // For minidumps without full memory, we need to always be able to iterate over m_Modules. - m_Modules.EnumMemoryRegions(flags); if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE) { diff --git a/src/coreclr/vm/domainfile.h b/src/coreclr/vm/domainassembly.h similarity index 59% rename from src/coreclr/vm/domainfile.h rename to src/coreclr/vm/domainassembly.h index 917af193ceade..268c49654253c 100644 --- a/src/coreclr/vm/domainfile.h +++ b/src/coreclr/vm/domainassembly.h @@ -1,14 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- -// DomainFile.h +// DomainAssembly.h // // -------------------------------------------------------------------------------- -#ifndef _DOMAINFILE_H_ -#define _DOMAINFILE_H_ +#ifndef _DOMAINASSEMBLY_H_ +#define _DOMAINASSEMBLY_H_ // -------------------------------------------------------------------------------- // Required headers @@ -59,27 +59,23 @@ enum NotificationStatus }; // -------------------------------------------------------------------------------- -// DomainFile represents a file loaded (or being loaded) into an app domain. It +// DomainAssembly represents an assembly loaded (or being loaded) into an app domain. It // is guranteed to be unique per file per app domain. // -------------------------------------------------------------------------------- -class DomainFile +class DomainAssembly final { - VPTR_BASE_VTABLE_CLASS(DomainFile); - - public: +public: // ------------------------------------------------------------ // Public API // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - virtual ~DomainFile(); - DomainFile() {LIMITED_METHOD_CONTRACT;}; + ~DomainAssembly(); + DomainAssembly() {LIMITED_METHOD_CONTRACT;}; #endif - virtual LoaderAllocator *GetLoaderAllocator(); - PTR_AppDomain GetAppDomain() { LIMITED_METHOD_CONTRACT; @@ -93,12 +89,41 @@ class DomainFile return PTR_PEAssembly(m_pPEAssembly); } + Assembly* GetAssembly() + { + LIMITED_METHOD_DAC_CONTRACT; + CONSISTENCY_CHECK(CheckLoaded()); + + return m_pAssembly; + } + + Module* GetModule() + { + LIMITED_METHOD_CONTRACT; + CONSISTENCY_CHECK(CheckLoaded()); + + return m_pModule; + } + IMDInternalImport *GetMDImport() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetMDImport(); } + OBJECTREF GetExposedAssemblyObjectIfExists() + { + LIMITED_METHOD_CONTRACT; + + OBJECTREF objRet = NULL; + GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedAssemblyObject, &objRet); + return objRet; + } + + // Returns managed representation of the assembly (Assembly or AssemblyBuilder). + // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). + OBJECTREF GetExposedAssemblyObject(); + OBJECTREF GetExposedModuleObjectIfExists() { LIMITED_METHOD_CONTRACT; @@ -130,9 +155,17 @@ class DomainFile } #endif - virtual BOOL IsAssembly() = 0; + BOOL IsCollectible() + { + LIMITED_METHOD_CONTRACT; + return m_fCollectible; + } - DomainAssembly *GetDomainAssembly(); + ULONG HashIdentity() + { + WRAPPER_NO_CONTRACT; + return GetPEAssembly()->HashIdentity(); + } // ------------------------------------------------------------ // Loading state checks @@ -202,7 +235,6 @@ class DomainFile return EnsureLoadLevel(FILE_LOAD_ALLOCATE); } - void EnsureLibraryLoaded() { WRAPPER_NO_CONTRACT; @@ -214,10 +246,6 @@ class DomainFile // is required for an operation. Note that deadlocks are tolerated so the level may be one void EnsureLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); - // AttemptLoadLevel is a generic routine used to try to further load the file to a given level. - // No guarantee is made about the load level resulting however. - void AttemptLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); - // CheckLoadLevel is an assert predicate used to verify the load level of an assembly. // deadlockOK indicates that the level is allowed to be one short if we are restricted // by loader reentrancy. @@ -245,16 +273,12 @@ class DomainFile // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - BOOL Equals(DomainFile *pFile) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pFile->GetPEAssembly()); } + BOOL Equals(DomainAssembly *pAssembly) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pAssembly->GetPEAssembly()); } BOOL Equals(PEAssembly *pPEAssembly) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pPEAssembly); } #endif // DACCESS_COMPILE - Module* GetCurrentModule(); - Module* GetLoadedModule(); - Module* GetModule(); - #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif #ifndef DACCESS_COMPILE @@ -262,7 +286,33 @@ class DomainFile DynamicMethodTable* GetDynamicMethodTable(); #endif - protected: + DomainAssembly* GetNextDomainAssemblyInSameALC() + { + return m_NextDomainAssemblyInSameALC; + } + + void SetNextDomainAssemblyInSameALC(DomainAssembly* domainAssembly) + { + _ASSERTE(m_NextDomainAssemblyInSameALC == NULL); + m_NextDomainAssemblyInSameALC = domainAssembly; + } + + LoaderAllocator* GetLoaderAllocator() + { + LIMITED_METHOD_CONTRACT; + return m_pLoaderAllocator; + } + +// ------------------------------------------------------------ +// Resource access +// ------------------------------------------------------------ + + BOOL GetResource(LPCSTR szName, DWORD* cbResource, + PBYTE* pbInMemoryResource, DomainAssembly** pAssemblyRef, + LPCSTR* szFileName, DWORD* dwLocation, + BOOL fSkipRaiseResolveEvent); + + private: // ------------------------------------------------------------ // Loader API // ------------------------------------------------------------ @@ -272,59 +322,53 @@ class DomainFile friend class Module; friend class FileLoadLock; - DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly); + DomainAssembly(AppDomain* pDomain, PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator); BOOL DoIncrementalLoad(FileLoadLevel targetLevel); void ClearLoading() { LIMITED_METHOD_CONTRACT; m_loading = FALSE; } void SetLoadLevel(FileLoadLevel level) { LIMITED_METHOD_CONTRACT; m_level = level; } #ifndef DACCESS_COMPILE - virtual void Begin() = 0; - virtual void Allocate() = 0; + void Begin(); + void Allocate(); void AddDependencies(); void PreLoadLibrary(); void LoadLibrary(); - void PostLoadLibrary(); + void PostLoadLibrary(); void EagerFixups(); void VtableFixups(); - virtual void DeliverSyncEvents() = 0; - virtual void DeliverAsyncEvents() = 0; + void DeliverSyncEvents(); + void DeliverAsyncEvents(); void FinishLoad(); void Activate(); + + void RegisterWithHostAssembly(); + void UnregisterFromHostAssembly(); #endif // This should be used to permanently set the load to fail. Do not use with transient conditions void SetError(Exception *ex); + void SetAssembly(Assembly* pAssembly); void SetProfilerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|= PROFILER_NOTIFIED; } void SetDebuggerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NOTIFIED; } void SetShouldNotifyDebugger() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NEEDNOTIFICATION; } - // ------------------------------------------------------------ - // Instance data - // ------------------------------------------------------------ - - PTR_AppDomain m_pDomain; - PTR_PEAssembly m_pPEAssembly; - PTR_Module m_pModule; - FileLoadLevel m_level; - LOADERHANDLE m_hExposedModuleObject; - class ExInfo { enum { - ExType_ClrEx, - ExType_HR + ExType_ClrEx, + ExType_HR } m_type; union { - Exception *m_pEx; - HRESULT m_hr; + Exception* m_pEx; + HRESULT m_hr; }; - public: + public: void Throw() { CONTRACTL @@ -334,209 +378,35 @@ class DomainFile MODE_ANY; } CONTRACTL_END; - if (m_type==ExType_ClrEx) + if (m_type == ExType_ClrEx) { - PAL_CPP_THROW(Exception *, m_pEx->DomainBoundClone()); + PAL_CPP_THROW(Exception*, m_pEx->DomainBoundClone()); } - if (m_type==ExType_HR) + if (m_type == ExType_HR) ThrowHR(m_hr); _ASSERTE(!"Bad exception type"); ThrowHR(E_UNEXPECTED); }; + ExInfo(Exception* pEx) { LIMITED_METHOD_CONTRACT; - m_type=ExType_ClrEx; - m_pEx=pEx; + m_type = ExType_ClrEx; + m_pEx = pEx; }; - void ConvertToHResult() - { - LIMITED_METHOD_CONTRACT; - if(m_type==ExType_HR) - return; - _ASSERTE(m_type==ExType_ClrEx); - HRESULT hr=m_pEx->GetHR(); - delete m_pEx; - m_hr=hr; - m_type=ExType_HR; - }; ~ExInfo() { LIMITED_METHOD_CONTRACT; - if (m_type==ExType_ClrEx) + if (m_type == ExType_ClrEx) delete m_pEx; } - }* m_pError; - - void ReleaseManagedData() - { - if (m_pError) - m_pError->ConvertToHResult(); }; - DWORD m_notifyflags; - BOOL m_loading; - // m_pDynamicMethodTable is used by the light code generation to allow method - // generation on the fly. They are lazily created when/if a dynamic method is requested - // for this specific module - DynamicMethodTable *m_pDynamicMethodTable; - class UMThunkHash *m_pUMThunkHash; - BOOL m_bDisableActivationCheck; -}; - -//--------------------------------------------------------------------------------------- -// One of these values is specified when requesting a module iterator to customize which -// modules should appear in the enumeration -enum ModuleIterationOption -{ - // include only modules that are already loaded (m_level >= FILE_LOAD_DELIVER_EVENTS) - kModIterIncludeLoaded = 1, - - // include all modules, even those that are still in the process of loading (all m_level values) - kModIterIncludeLoading = 2, - - // include only modules loaded just enough that profilers are notified of them. - // (m_level >= FILE_LOAD_LOADLIBRARY). See comment at code:DomainFile::IsAvailableToProfilers - kModIterIncludeAvailableToProfilers = 3, -}; - -// -------------------------------------------------------------------------------- -// DomainAssembly is a subclass of DomainFile which specifically represents a assembly. -// -------------------------------------------------------------------------------- - -class DomainAssembly : public DomainFile -{ - VPTR_VTABLE_CLASS(DomainAssembly, DomainFile); - public: - // ------------------------------------------------------------ - // Public API - // ------------------------------------------------------------ - - LoaderAllocator *GetLoaderAllocator() - { - LIMITED_METHOD_CONTRACT; - return m_pLoaderAllocator; - } - - void SetAssembly(Assembly* pAssembly); - - BOOL IsAssembly() - { - LIMITED_METHOD_DAC_CONTRACT; - return TRUE; - } - - OBJECTREF GetExposedAssemblyObjectIfExists() - { - LIMITED_METHOD_CONTRACT; - - OBJECTREF objRet = NULL; - GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedAssemblyObject, &objRet); - return objRet; - } - - // Returns managed representation of the assembly (Assembly or AssemblyBuilder). - // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). - OBJECTREF GetExposedAssemblyObject(); - - Assembly* GetCurrentAssembly(); - Assembly* GetLoadedAssembly(); - Assembly* GetAssembly(); - -#ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); -#endif - - // ------------------------------------------------------------ - // Modules - // ------------------------------------------------------------ - class ModuleIterator - { - ArrayList::Iterator m_i; - ModuleIterationOption m_moduleIterationOption; - - public: - BOOL Next() - { - WRAPPER_NO_CONTRACT; - while (m_i.Next()) - { - if (m_i.GetElement() == NULL) - { - continue; - } - if (GetDomainFile()->IsError()) - { - continue; - } - if (m_moduleIterationOption == kModIterIncludeLoading) - return TRUE; - if ((m_moduleIterationOption == kModIterIncludeLoaded) && - GetDomainFile()->IsLoaded()) - return TRUE; - if ((m_moduleIterationOption == kModIterIncludeAvailableToProfilers) && - GetDomainFile()->IsAvailableToProfilers()) - return TRUE; - } - return FALSE; - } - Module *GetModule() - { - WRAPPER_NO_CONTRACT; - return GetDomainFile()->GetModule(); - } - Module *GetLoadedModule() - { - WRAPPER_NO_CONTRACT; - return GetDomainFile()->GetLoadedModule(); - } - DomainFile *GetDomainFile() - { - WRAPPER_NO_CONTRACT; - return dac_cast(m_i.GetElement()); - } - SIZE_T GetIndex() - { - WRAPPER_NO_CONTRACT; - return m_i.GetIndex(); - } - - private: - friend class DomainAssembly; - // Cannot have constructor so this iterator can be used inside a union - static ModuleIterator Create(DomainAssembly * pDomainAssembly, ModuleIterationOption moduleIterationOption) - { - WRAPPER_NO_CONTRACT; - ModuleIterator i; - - i.m_i = pDomainAssembly->m_Modules.Iterate(); - i.m_moduleIterationOption = moduleIterationOption; - - return i; - } - }; - friend class ModuleIterator; - - ModuleIterator IterateModules(ModuleIterationOption moduleIterationOption) - { - WRAPPER_NO_CONTRACT; - return ModuleIterator::Create(this, moduleIterationOption); - } - - // ------------------------------------------------------------ - // Resource access - // ------------------------------------------------------------ - - BOOL GetResource(LPCSTR szName, DWORD *cbResource, - PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef, - LPCSTR *szFileName, DWORD *dwLocation, - BOOL fSkipRaiseResolveEvent); - - // ------------------------------------------------------------ - // Debugger control API - // ------------------------------------------------------------ +// ------------------------------------------------------------ +// Debugger control API +// ------------------------------------------------------------ DebuggerAssemblyControlFlags GetDebuggerInfoBits(void) { @@ -553,75 +423,46 @@ class DomainAssembly : public DomainFile void SetupDebuggingConfig(void); DWORD ComputeDebuggingConfig(void); - HRESULT GetDebuggingCustomAttributes(DWORD *pdwFlags); + HRESULT GetDebuggingCustomAttributes(DWORD* pdwFlags); BOOL IsVisibleToDebugger(); BOOL NotifyDebuggerLoad(int flags, BOOL attaching); void NotifyDebuggerUnload(); - inline BOOL IsCollectible(); - - - private: - +private: // ------------------------------------------------------------ - // Loader API + // Instance data // ------------------------------------------------------------ - friend class AppDomain; - friend class Assembly; + PTR_Assembly m_pAssembly; + PTR_AppDomain m_pDomain; + PTR_PEAssembly m_pPEAssembly; + PTR_Module m_pModule; -#ifndef DACCESS_COMPILE -public: - ~DomainAssembly(); -private: - DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator); -#endif + BOOL m_fCollectible; + DomainAssembly* m_NextDomainAssemblyInSameALC; + PTR_LoaderAllocator m_pLoaderAllocator; - // ------------------------------------------------------------ - // Internal routines - // ------------------------------------------------------------ + FileLoadLevel m_level; + BOOL m_loading; -#ifndef DACCESS_COMPILE - void Begin(); - void Allocate(); - void DeliverSyncEvents(); - void DeliverAsyncEvents(); - void RegisterWithHostAssembly(); - void UnregisterFromHostAssembly(); -#endif + LOADERHANDLE m_hExposedModuleObject; + LOADERHANDLE m_hExposedAssemblyObject; - public: - ULONG HashIdentity(); + ExInfo* m_pError; - // ------------------------------------------------------------ - // Instance data - // ------------------------------------------------------------ + BOOL m_bDisableActivationCheck; + BOOL m_fHostAssemblyPublished; + + // m_pDynamicMethodTable is used by the light code generation to allow method + // generation on the fly. They are lazily created when/if a dynamic method is requested + // for this specific module + DynamicMethodTable* m_pDynamicMethodTable; - private: - LOADERHANDLE m_hExposedAssemblyObject; - PTR_Assembly m_pAssembly; - DebuggerAssemblyControlFlags m_debuggerFlags; - ArrayList m_Modules; - BOOL m_fDebuggerUnloadStarted; - BOOL m_fCollectible; - Volatile m_fHostAssemblyPublished; - PTR_LoaderAllocator m_pLoaderAllocator; - DomainAssembly* m_NextDomainAssemblyInSameALC; - - public: - DomainAssembly* GetNextDomainAssemblyInSameALC() - { - return m_NextDomainAssemblyInSameALC; - } - - void SetNextDomainAssemblyInSameALC(DomainAssembly* domainAssembly) - { - _ASSERTE(m_NextDomainAssemblyInSameALC == NULL); - m_NextDomainAssemblyInSameALC = domainAssembly; - } -}; -typedef DomainAssembly::ModuleIterator DomainModuleIterator; + DebuggerAssemblyControlFlags m_debuggerFlags; + DWORD m_notifyflags; + BOOL m_fDebuggerUnloadStarted; +}; -#endif // _DOMAINFILE_H_ +#endif // _DOMAINASSEMBLY_H_ diff --git a/src/coreclr/vm/domainfile.inl b/src/coreclr/vm/domainfile.inl deleted file mode 100644 index a87d9aaef1309..0000000000000 --- a/src/coreclr/vm/domainfile.inl +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// - -inline Module* DomainFile::GetCurrentModule() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return m_pModule; -} - -inline Module* DomainFile::GetLoadedModule() -{ - LIMITED_METHOD_CONTRACT; - CONSISTENCY_CHECK(CheckLoaded()); - - return m_pModule; -} - -inline Module* DomainFile::GetModule() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - { - // While executing the consistency check, we will take a lock. - // But since this is debug-only, we'll allow the lock violation so that - // CANNOT_TAKE_LOCK callers aren't penalized - CONTRACT_VIOLATION(TakesLockViolation); - CONSISTENCY_CHECK(CheckLoadLevel(FILE_LOAD_ALLOCATE)); - } - - return m_pModule; -} - -inline Assembly* DomainAssembly::GetCurrentAssembly() -{ - LIMITED_METHOD_CONTRACT; - - return m_pAssembly; -} - -inline Assembly* DomainAssembly::GetLoadedAssembly() -{ - LIMITED_METHOD_DAC_CONTRACT; - CONSISTENCY_CHECK(CheckLoaded()); - - return m_pAssembly; -} - -inline Assembly* DomainAssembly::GetAssembly() -{ - LIMITED_METHOD_CONTRACT; - - CONSISTENCY_CHECK(CheckLoadLevel(FILE_LOAD_ALLOCATE)); - return m_pAssembly; -} - -inline ULONG DomainAssembly::HashIdentity() -{ - WRAPPER_NO_CONTRACT; - return GetPEAssembly()->HashIdentity(); -} - -inline BOOL DomainAssembly::IsCollectible() -{ - LIMITED_METHOD_CONTRACT; - return m_fCollectible; -} - diff --git a/src/coreclr/vm/dwbucketmanager.hpp b/src/coreclr/vm/dwbucketmanager.hpp index 2524f706c7ef3..6eb0e9438b5f3 100644 --- a/src/coreclr/vm/dwbucketmanager.hpp +++ b/src/coreclr/vm/dwbucketmanager.hpp @@ -650,7 +650,7 @@ void BaseBucketParamsManager::GetModuleVersion(_Out_writes_(maxLength) WCHAR* ta // if we failed to get a version and this isn't the manifest module then try that if (!gotFileVersion && !pModule->IsManifest()) { - pModule = pModule->GetAssembly()->GetManifestModule(); + pModule = pModule->GetAssembly()->GetModule(); if (pModule) gotFileVersion = GetFileVersionInfoForModule(pModule, major, minor, build, revision); } @@ -701,7 +701,7 @@ void BaseBucketParamsManager::GetModuleTimeStamp(_Out_writes_(maxLength) WCHAR* { // We only store the IL timestamp in the native image for the // manifest module. We should consider fixing this for Orcas. - PTR_PEAssembly pFile = pModule->GetAssembly()->GetManifestModule()->GetPEAssembly(); + PTR_PEAssembly pFile = pModule->GetAssembly()->GetModule()->GetPEAssembly(); // for dynamic modules use 0 as the time stamp ULONG ulTimeStamp = 0; diff --git a/src/coreclr/vm/dwreport.cpp b/src/coreclr/vm/dwreport.cpp index 1032725eb854b..47defdeedb5d0 100644 --- a/src/coreclr/vm/dwreport.cpp +++ b/src/coreclr/vm/dwreport.cpp @@ -17,6 +17,7 @@ #include "field.h" #include #include +#include #include "dbginterface.h" #include #include "dlwrap.h" @@ -57,14 +58,6 @@ class SimpleModuleHolder operator HMODULE() { return hModule; } }; -#ifndef FEATURE_CORESYSTEM -#define WER_MODULE_NAME_W WINDOWS_KERNEL32_DLLNAME_W -typedef SimpleModuleHolder WerModuleHolder; -#else -#define WER_MODULE_NAME_W W("api-ms-win-core-windowserrorreporting-l1-1-0.dll") -typedef SimpleModuleHolder WerModuleHolder; -#endif - //------------------------------------------------------------------------------ // Description // Indicate if Watson is enabled @@ -107,47 +100,17 @@ BOOL RegisterOutOfProcessWatsonCallbacks() CONTRACTL_END; WCHAR wszDACName[] = MAIN_DAC_MODULE_NAME_W W(".dll"); - WerModuleHolder hWerModule(WER_MODULE_NAME_W); - -#ifdef FEATURE_CORESYSTEM - if ((hWerModule == NULL) && !RunningOnWin8()) - { - // If we are built for CoreSystemServer, but are running on Windows 7, we need to look elsewhere - hWerModule = WerModuleHolder(W("Kernel32.dll")); - } -#endif - - if (hWerModule == NULL) - { - _ASSERTE(!"failed to get WER module handle"); - return FALSE; - } - - typedef HRESULT (WINAPI * WerRegisterRuntimeExceptionModuleFnPtr)(PCWSTR, PDWORD); - WerRegisterRuntimeExceptionModuleFnPtr pFnWerRegisterRuntimeExceptionModule; - - pFnWerRegisterRuntimeExceptionModule = (WerRegisterRuntimeExceptionModuleFnPtr) - GetProcAddress(hWerModule, "WerRegisterRuntimeExceptionModule"); - - _ASSERTE(pFnWerRegisterRuntimeExceptionModule != NULL); - if (pFnWerRegisterRuntimeExceptionModule == NULL) - { - return FALSE; - } HRESULT hr = S_OK; EX_TRY { PathString wszDACPath; - if (SUCCEEDED(::GetClrModuleDirectory(wszDACPath))) + hr = ::GetClrModuleDirectory(wszDACPath); + if (SUCCEEDED(hr)) { wszDACPath.Append(wszDACName); - hr = (*pFnWerRegisterRuntimeExceptionModule)(wszDACPath, (PDWORD)GetClrModuleBase()); - } - else { - hr = E_FAIL; + hr = WerRegisterRuntimeExceptionModule(wszDACPath, (PDWORD)GetClrModuleBase()); } - } EX_CATCH_HRESULT(hr); @@ -156,16 +119,7 @@ BOOL RegisterOutOfProcessWatsonCallbacks() STRESS_LOG0(LF_STARTUP, LL_ERROR, "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); - -#ifdef FEATURE_CORESYSTEM - // For CoreSys we *could* be running on a platform that doesn't have Watson proper - // (the APIs might exist but they just fail). - // WerRegisterRuntimeExceptionModule may return E_NOIMPL. return TRUE; -#else // FEATURE_CORESYSTEM - _ASSERTE(! "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); - return FALSE; -#endif // FEATURE_CORESYSTEM } STRESS_LOG0(LF_STARTUP, diff --git a/src/coreclr/vm/dynamicmethod.cpp b/src/coreclr/vm/dynamicmethod.cpp index 35137855229e5..a5a9ee44ba8eb 100644 --- a/src/coreclr/vm/dynamicmethod.cpp +++ b/src/coreclr/vm/dynamicmethod.cpp @@ -20,7 +20,7 @@ #ifndef DACCESS_COMPILE // get the method table for dynamic methods -DynamicMethodTable* DomainFile::GetDynamicMethodTable() +DynamicMethodTable* DomainAssembly::GetDynamicMethodTable() { CONTRACT (DynamicMethodTable*) { diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index be7a6826854f0..08ab8e71c868a 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -291,12 +291,6 @@ FCFuncStart(gAssemblyLoadContextFuncs) FCFuncElement("IsTracingEnabled", AssemblyNative::IsTracingEnabled) FCFuncEnd() -FCFuncStart(gAssemblyNameFuncs) - FCFuncElement("nInit", AssemblyNameNative::Init) - FCFuncElement("ComputePublicKeyToken", AssemblyNameNative::GetPublicKeyToken) - FCFuncElement("nGetFileInformation", AssemblyNameNative::GetFileInformation) -FCFuncEnd() - FCFuncStart(gAssemblyBuilderFuncs) FCFuncElement("GetInMemoryAssemblyModule", AssemblyNative::GetInMemoryAssemblyModule) FCFuncEnd() @@ -322,8 +316,6 @@ FCFuncStart(gDelegateFuncs) FCFuncEnd() FCFuncStart(gMathFuncs) - FCFuncElementSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::Abs) - FCFuncElementSig("Abs", &gsig_SM_Flt_RetFlt, COMSingle::Abs) FCFuncElement("Acos", COMDouble::Acos) FCFuncElement("Acosh", COMDouble::Acosh) FCFuncElement("Asin", COMDouble::Asin) @@ -772,7 +764,6 @@ FCClassElement("ArgIterator", "System", gVarArgFuncs) FCClassElement("Array", "System", gArrayFuncs) FCClassElement("AssemblyBuilder", "System.Reflection.Emit", gAssemblyBuilderFuncs) FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadContextFuncs) -FCClassElement("AssemblyName", "System.Reflection", gAssemblyNameFuncs) FCClassElement("Buffer", "System", gBufferFuncs) FCClassElement("CastHelpers", "System.Runtime.CompilerServices", gCastHelpers) FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilitySwitchFuncs) diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index e5473b1104177..3c5d8ded8c574 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -1380,7 +1380,7 @@ void BulkComLogger::AddCcwHandle(Object **handle) -#include "domainfile.h" +#include "domainassembly.h" BulkStaticsLogger::BulkStaticsLogger(BulkTypeEventLogger *typeLogger) : m_buffer(0), m_used(0), m_count(0), m_domain(0), m_typeLogger(typeLogger) @@ -1524,69 +1524,64 @@ void BulkStaticsLogger::LogAllStatics() continue; CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); - DomainModuleIterator modIter = pDomainAssembly->IterateModules(kModIterIncludeLoaded); + // Get the domain module from the module/appdomain pair. + Module *module = pDomainAssembly->GetModule(); + if (module == NULL) + continue; - while (modIter.Next()) - { - // Get the domain module from the module/appdomain pair. - Module *module = modIter.GetModule(); - if (module == NULL) - continue; + DomainAssembly *domainAssembly = module->GetDomainAssembly(); + if (domainAssembly == NULL) + continue; - DomainFile *domainFile = module->GetDomainFile(); - if (domainFile == NULL) - continue; + // Ensure the module has fully loaded. + if (!domainAssembly->IsActive()) + continue; - // Ensure the module has fully loaded. - if (!domainFile->IsActive()) + DomainLocalModule *domainModule = module->GetDomainLocalModule(); + if (domainModule == NULL) + continue; + + // Now iterate all types with + LookupMap::Iterator mtIter = module->EnumerateTypeDefs(); + while (mtIter.Next()) + { + // I don't think mt can be null here, but the dac does a null check... + // IsFullyLoaded should be equivalent to 'GetLoadLevel() == CLASS_LOADED' + MethodTable *mt = mtIter.GetElement(); + if (mt == NULL || !mt->IsFullyLoaded()) continue; - DomainLocalModule *domainModule = module->GetDomainLocalModule(); - if (domainModule == NULL) + EEClass *cls = mt->GetClass(); + _ASSERTE(cls != NULL); + + if (cls->GetNumStaticFields() <= 0) continue; - // Now iterate all types with - LookupMap::Iterator mtIter = module->EnumerateTypeDefs(); - while (mtIter.Next()) + ApproxFieldDescIterator fieldIter(mt, ApproxFieldDescIterator::STATIC_FIELDS); + for (FieldDesc *field = fieldIter.Next(); field != NULL; field = fieldIter.Next()) { - // I don't think mt can be null here, but the dac does a null check... - // IsFullyLoaded should be equivalent to 'GetLoadLevel() == CLASS_LOADED' - MethodTable *mt = mtIter.GetElement(); - if (mt == NULL || !mt->IsFullyLoaded()) + // Don't want thread local + _ASSERTE(field->IsStatic()); + if (field->IsSpecialStatic() || field->IsEnCNew()) continue; - EEClass *cls = mt->GetClass(); - _ASSERTE(cls != NULL); + // Static valuetype values are boxed. + CorElementType fieldType = field->GetFieldType(); + if (fieldType != ELEMENT_TYPE_CLASS && fieldType != ELEMENT_TYPE_VALUETYPE) + continue; - if (cls->GetNumStaticFields() <= 0) + BYTE *base = field->GetBaseInDomainLocalModule(domainModule); + if (base == NULL) continue; - ApproxFieldDescIterator fieldIter(mt, ApproxFieldDescIterator::STATIC_FIELDS); - for (FieldDesc *field = fieldIter.Next(); field != NULL; field = fieldIter.Next()) - { - // Don't want thread local - _ASSERTE(field->IsStatic()); - if (field->IsSpecialStatic() || field->IsEnCNew()) - continue; - - // Static valuetype values are boxed. - CorElementType fieldType = field->GetFieldType(); - if (fieldType != ELEMENT_TYPE_CLASS && fieldType != ELEMENT_TYPE_VALUETYPE) - continue; - - BYTE *base = field->GetBaseInDomainLocalModule(domainModule); - if (base == NULL) - continue; - - Object **address = (Object**)field->GetStaticAddressHandle(base); - Object *obj = NULL; - if (address == NULL || ((obj = *address) == NULL)) - continue; - - WriteEntry(domain, address, *address, field); - } // foreach static field - } - } // foreach domain module + Object **address = (Object**)field->GetStaticAddressHandle(base); + Object *obj = NULL; + if (address == NULL || ((obj = *address) == NULL)) + continue; + + WriteEntry(domain, address, *address, field); + } // foreach static field + } } // foreach domain assembly } // foreach AppDomain } // BulkStaticsLogger::LogAllStatics @@ -6047,7 +6042,7 @@ VOID ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions PCWSTR szDtraceOutput1=W(""); BOOL bIsDynamicAssembly = pAssembly->IsDynamic(); BOOL bIsCollectibleAssembly = pAssembly->IsCollectible(); - BOOL bIsReadyToRun = pAssembly->GetManifestFile()->IsReadyToRun(); + BOOL bIsReadyToRun = pAssembly->GetPEAssembly()->IsReadyToRun(); ULONGLONG ullAssemblyId = (ULONGLONG)pAssembly; ULONGLONG ullDomainId = (ULONGLONG)pAssembly->GetDomain(); @@ -6338,7 +6333,7 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL if(!bIsDynamicAssembly) { - ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetPEImage()->GetPath().GetUnicode(); + ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetPEAssembly()->GetPEImage()->GetPath().GetUnicode(); ModuleNativePath = (PWCHAR)pEmptyString; } @@ -7246,18 +7241,14 @@ VOID ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp CollectibleAssemblyHolder pDomainAssembly; while (assemblyIterator.Next(pDomainAssembly.This())) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + Module * pModule = pDomainAssembly->GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) @@ -7313,12 +7304,8 @@ VOID ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca { Assembly *pAssembly = domainAssemblyIt->GetAssembly(); // TODO: handle iterator - DomainModuleIterator domainModuleIterator = domainAssemblyIt->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module *pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + Module* pModule = domainAssemblyIt->GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { @@ -7362,11 +7349,8 @@ VOID ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumeration { if(pAssembly->GetDomain()->IsAppDomain()) { - DomainModuleIterator dmIterator = pAssembly->GetDomainAssembly()->IterateModules(kModIterIncludeLoaded); - while (dmIterator.Next()) - { - ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); - } + Module* pModule = pAssembly->GetDomainAssembly()->GetModule(); + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions, TRUE); } } diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index fa2b8ffc7dfe3..dd80bf37ec679 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -500,7 +500,7 @@ OBJECTREF PossiblyUnwrapThrowable(OBJECTREF throwable, Assembly *pAssembly) // Check if we are required to compute the RuntimeWrapExceptions status. BOOL fIsRuntimeWrappedException = ((throwable != NULL) && (throwable->GetMethodTable() == pMT_RuntimeWrappedException)); BOOL fRequiresComputingRuntimeWrapExceptionsStatus = (fIsRuntimeWrappedException && - (!(pAssembly->GetManifestModule()->IsRuntimeWrapExceptionsStatusComputed()))); + (!(pAssembly->GetModule()->IsRuntimeWrapExceptionsStatusComputed()))); CONTRACTL { @@ -513,7 +513,7 @@ OBJECTREF PossiblyUnwrapThrowable(OBJECTREF throwable, Assembly *pAssembly) } CONTRACTL_END; - if (fIsRuntimeWrappedException && (!pAssembly->GetManifestModule()->IsRuntimeWrapExceptions())) + if (fIsRuntimeWrappedException && (!pAssembly->GetModule()->IsRuntimeWrapExceptions())) { // We already created the instance, fetched the field. We know it is // not marshal by ref, or any of the other cases that might trigger GC. @@ -12136,8 +12136,8 @@ VOID CheckAndThrowSameTypeAndAssemblyInvalidCastException(TypeHandle thCastFrom, _ASSERTE(pAssemblyTypeFrom != NULL); _ASSERTE(pAssemblyTypeTo != NULL); - PEAssembly *pPEAssemblyTypeFrom = pAssemblyTypeFrom->GetManifestFile(); - PEAssembly *pPEAssemblyTypeTo = pAssemblyTypeTo->GetManifestFile(); + PEAssembly *pPEAssemblyTypeFrom = pAssemblyTypeFrom->GetPEAssembly(); + PEAssembly *pPEAssemblyTypeTo = pAssemblyTypeTo->GetPEAssembly(); _ASSERTE(pPEAssemblyTypeFrom != NULL); _ASSERTE(pPEAssemblyTypeTo != NULL); diff --git a/src/coreclr/vm/field.cpp b/src/coreclr/vm/field.cpp index a0e1260976dee..31d858814d020 100644 --- a/src/coreclr/vm/field.cpp +++ b/src/coreclr/vm/field.cpp @@ -61,6 +61,8 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr FieldType == ELEMENT_TYPE_R8 || FieldType == ELEMENT_TYPE_CLASS || FieldType == ELEMENT_TYPE_VALUETYPE || + FieldType == ELEMENT_TYPE_BYREF || + FieldType == ELEMENT_TYPE_TYPEDBYREF || FieldType == ELEMENT_TYPE_PTR || FieldType == ELEMENT_TYPE_FNPTR ); @@ -70,7 +72,8 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr m_requiresFullMbValue = 0; SetMemberDef(mb); - m_type = FieldType; + // A TypedByRef should be treated like a regular value type. + m_type = FieldType != ELEMENT_TYPE_TYPEDBYREF ? FieldType : ELEMENT_TYPE_VALUETYPE; m_prot = fdFieldAccessMask & dwMemberAttrs; m_isStatic = fIsStatic != 0; m_isRVA = fIsRVA != 0; @@ -81,7 +84,7 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr #endif _ASSERTE(GetMemberDef() == mb); // no truncation - _ASSERTE(GetFieldType() == FieldType); + _ASSERTE(GetFieldType() == FieldType || (FieldType == ELEMENT_TYPE_TYPEDBYREF && m_type == ELEMENT_TYPE_VALUETYPE)); _ASSERTE(GetFieldProtection() == (fdFieldAccessMask & dwMemberAttrs)); _ASSERTE((BOOL) IsStatic() == (fIsStatic != 0)); } @@ -94,6 +97,14 @@ BOOL FieldDesc::IsObjRef() return CorTypeInfo::IsObjRef_NoThrow(GetFieldType()); } +// Return whether the field is a GC ref type +BOOL FieldDesc::IsByRef() +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return CorTypeInfo::IsByRef_NoThrow(GetFieldType()); +} + BOOL FieldDesc::MightHaveName(ULONG nameHashValue) { LIMITED_METHOD_CONTRACT; @@ -152,6 +163,7 @@ TypeHandle FieldDesc::LookupFieldTypeHandle(ClassLoadLevel level, BOOL dropGener _ASSERTE(type == ELEMENT_TYPE_CLASS || type == ELEMENT_TYPE_VALUETYPE || type == ELEMENT_TYPE_STRING || + type == ELEMENT_TYPE_TYPEDBYREF || type == ELEMENT_TYPE_SZARRAY || type == ELEMENT_TYPE_VAR ); diff --git a/src/coreclr/vm/field.h b/src/coreclr/vm/field.h index 25e9e19fb7306..72378df259060 100644 --- a/src/coreclr/vm/field.h +++ b/src/coreclr/vm/field.h @@ -353,6 +353,8 @@ class FieldDesc BOOL IsObjRef(); + BOOL IsByRef(); + UINT LoadSize(); // Return -1 if the type isn't loaded yet (i.e. if LookupFieldTypeHandle() would return null) diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index 2f7a4d91c9ec4..9377b4ec028b7 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -63,21 +63,12 @@ void Frame::Log() { MethodDesc* method = GetFunction(); -#ifdef TARGET_X86 - if (GetVTablePtr() == UMThkCallFrame::GetMethodFrameVPtr()) - method = ((UMThkCallFrame*) this)->GetUMEntryThunk()->GetMethod(); -#endif - STRESS_LOG3(LF_STUBS, LL_INFO1000000, "STUBS: In Stub with Frame %p assoc Method %pM FrameType = %pV\n", this, method, *((void**) this)); char buff[64]; const char* frameType; if (GetVTablePtr() == PrestubMethodFrame::GetMethodFrameVPtr()) frameType = "PreStub"; -#ifdef TARGET_X86 - else if (GetVTablePtr() == UMThkCallFrame::GetMethodFrameVPtr()) - frameType = "UMThkCallFrame"; -#endif else if (GetVTablePtr() == PInvokeCalliFrame::GetMethodFrameVPtr()) { sprintf_s(buff, ARRAY_SIZE(buff), "PInvoke CALLI target" FMT_ADDR, @@ -1603,32 +1594,6 @@ void ComMethodFrame::DoSecondPassHandlerCleanup(Frame * pCurFrame) #endif // FEATURE_COMINTEROP - -#ifdef TARGET_X86 - -PTR_UMEntryThunk UMThkCallFrame::GetUMEntryThunk() -{ - LIMITED_METHOD_DAC_CONTRACT; - return dac_cast(GetDatum()); -} - -#ifdef DACCESS_COMPILE -void UMThkCallFrame::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) -{ - WRAPPER_NO_CONTRACT; - UnmanagedToManagedFrame::EnumMemoryRegions(flags); - - // Pieces of the UMEntryThunk need to be saved. - UMEntryThunk *pThunk = GetUMEntryThunk(); - DacEnumMemoryRegion(dac_cast(pThunk), sizeof(UMEntryThunk)); - - UMThunkMarshInfo *pMarshInfo = pThunk->GetUMThunkMarshInfo(); - DacEnumMemoryRegion(dac_cast(pMarshInfo), sizeof(UMThunkMarshInfo)); -} -#endif - -#endif // TARGET_X86 - #ifndef DACCESS_COMPILE #if defined(_MSC_VER) && defined(TARGET_X86) @@ -1952,16 +1917,18 @@ VOID InlinedCallFrame::Init() } - +#ifdef FEATURE_COMINTEROP void UnmanagedToManagedFrame::ExceptionUnwind() { WRAPPER_NO_CONTRACT; AppDomain::ExceptionUnwind(this); } +#endif // FEATURE_COMINTEROP #endif // !DACCESS_COMPILE +#ifdef FEATURE_COMINTEROP PCODE UnmanagedToManagedFrame::GetReturnAddress() { WRAPPER_NO_CONTRACT; @@ -1980,6 +1947,7 @@ PCODE UnmanagedToManagedFrame::GetReturnAddress() return pRetAddr; } } +#endif // FEATURE_COMINTEROP #ifndef DACCESS_COMPILE //================================================================================= diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index c2946ced0b2f6..82e57cbbb0401 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -90,23 +90,18 @@ // | | // | +-TPMethodFrame - for calls on transparent proxy // | +#ifdef FEATURE_COMINTEROP // +-UnmanagedToManagedFrame - this frame represents a transition from // | | unmanaged code back to managed code. It's // | | main functions are to stop COM+ exception // | | propagation and to expose unmanaged parameters. // | | -#ifdef FEATURE_COMINTEROP -// | | // | +-ComMethodFrame - this frame represents a transition from // | | com to com+ // | | // | +-ComPrestubMethodFrame - prestub frame for calls from COM to CLR // | #endif //FEATURE_COMINTEROP -#ifdef TARGET_X86 -// | +-UMThkCallFrame - this frame represents an unmanaged->managed -// | transition through N/Direct -#endif #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) // +-TailCallFrame - padding for tailcalls // | @@ -172,16 +167,9 @@ Delegate over a native function pointer: Reverse P/Invoke (used for C++ exports & fixups as well as delegates obtained from function pointers): Normal stub: - x86: The stub is generated by UMEntryThunk::CompileUMThunkWorker - (in DllImportCallback.cpp) and it is frameless. It calls directly - the managed target or to IL stub if marshaling is required. - non-x86: The stub exists statically as UMThunkStub and calls to IL stub. + The stub exists statically as UMThunkStub and calls to IL stub. Prestub: - The prestub is generated by GenerateUMThunkPrestub (x86) or exists statically - as TheUMEntryPrestub (64-bit), and it erects an UMThkCallFrame frame. - -Reverse P/Invoke AppDomain selector stub: - The asm helper is IJWNOADThunkJumpTarget (in asmhelpers.asm) and it is frameless. + The prestub exists statically as TheUMEntryPrestub. //------------------------------------------------------------------------ #endif // 0 @@ -212,8 +200,8 @@ FRAME_TYPE_NAME(HelperMethodFrame_3OBJ) FRAME_TYPE_NAME(HelperMethodFrame_PROTECTOBJ) FRAME_ABSTRACT_TYPE_NAME(FramedMethodFrame) FRAME_TYPE_NAME(MulticastFrame) -FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame) #ifdef FEATURE_COMINTEROP +FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame) FRAME_TYPE_NAME(ComMethodFrame) FRAME_TYPE_NAME(ComPlusMethodFrame) FRAME_TYPE_NAME(ComPrestubMethodFrame) @@ -238,9 +226,6 @@ FRAME_TYPE_NAME(DebuggerClassInitMarkFrame) FRAME_TYPE_NAME(DebuggerSecurityCodeMarkFrame) FRAME_TYPE_NAME(DebuggerExitFrame) FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame) -#ifdef TARGET_X86 -FRAME_TYPE_NAME(UMThkCallFrame) -#endif FRAME_TYPE_NAME(InlinedCallFrame) #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) FRAME_TYPE_NAME(TailCallFrame) @@ -281,9 +266,6 @@ class Frame; class FramedMethodFrame; typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame; struct HijackArgs; -class UMEntryThunk; -class UMThunkMarshInfo; -class Marshaler; struct ResolveCacheElem; #if defined(DACCESS_COMPILE) class DacDbiInterfaceImpl; @@ -1814,6 +1796,8 @@ class MulticastFrame : public TransitionFrame }; +#ifdef FEATURE_COMINTEROP + //----------------------------------------------------------------------- // Transition frame from unmanaged to managed //----------------------------------------------------------------------- @@ -1922,8 +1906,6 @@ class UnmanagedToManagedFrame : public Frame #endif }; -#ifdef FEATURE_COMINTEROP - //------------------------------------------------------------------------ // This frame represents a transition from COM to COM+ //------------------------------------------------------------------------ @@ -2774,43 +2756,6 @@ class DebuggerU2MCatchHandlerFrame : public Frame DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerU2MCatchHandlerFrame) }; - -class UMThunkMarshInfo; -typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo; - -class UMEntryThunk; -typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk; - -#if defined(TARGET_X86) -//------------------------------------------------------------------------ -// This frame guards an unmanaged->managed transition thru a UMThk -//------------------------------------------------------------------------ - -class UMThkCallFrame : public UnmanagedToManagedFrame -{ - VPTR_VTABLE_CLASS(UMThkCallFrame, UnmanagedToManagedFrame) - -public: - -#ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); -#endif - - PTR_UMEntryThunk GetUMEntryThunk(); - - static int GetOffsetOfUMEntryThunk() - { - WRAPPER_NO_CONTRACT; - return GetOffsetOfDatum(); - } - -protected: - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(UMThkCallFrame) -}; -#endif // TARGET_X86 && !TARGET_UNIX - // Frame for the Reverse PInvoke (i.e. UnmanagedCallersOnlyAttribute). struct ReversePInvokeFrame { @@ -2821,29 +2766,6 @@ struct ReversePInvokeFrame #endif }; -#if defined(TARGET_X86) && defined(FEATURE_COMINTEROP) -//------------------------------------------------------------------------- -// Exception handler for COM to managed frame -// and the layout of the exception registration record structure in the stack -// the layout is similar to the NT's EXCEPTIONREGISTRATION record -// followed by the UnmanagedToManagedFrame specific info - -struct ComToManagedExRecord -{ - EXCEPTION_REGISTRATION_RECORD m_ExReg; - ArgumentRegisters m_argRegs; - GSCookie m_gsCookie; - UMThkCallFrame m_frame; - - UnmanagedToManagedFrame * GetCurrFrame() - { - LIMITED_METHOD_CONTRACT; - return &m_frame; - } -}; -#endif // TARGET_X86 && FEATURE_COMINTEROP - - //------------------------------------------------------------------------ // This frame is pushed by any JIT'ted method that contains one or more // inlined N/Direct calls. Note that the JIT'ted method keeps it pushed diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index d3eb78da47256..896c249822c55 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -43,7 +43,6 @@ EXTERN _COMPlusFrameHandlerRevCom:PROC endif ; FEATURE_COMINTEROP EXTERN __alloca_probe:PROC EXTERN _NDirectImportWorker@4:PROC -EXTERN _UMThunkStubRareDisableWorker@8:PROC EXTERN _VarargPInvokeStubWorker@12:PROC EXTERN _GenericPInvokeCalliStubWorker@12:PROC @@ -53,6 +52,7 @@ EXTERN _CopyCtorCallStubWorker@4:PROC endif EXTERN _PreStubWorker@8:PROC +EXTERN _TheUMEntryPrestubWorker@4:PROC ifdef FEATURE_COMINTEROP EXTERN _CLRToCOMWorker@8:PROC @@ -255,9 +255,6 @@ COMPlusNestedExceptionHandler proto c FastNExportExceptHandler proto c .safeseh FastNExportExceptHandler -UMThunkPrestubHandler proto c -.safeseh UMThunkPrestubHandler - ifdef FEATURE_COMINTEROP COMPlusFrameHandlerRevCom proto c .safeseh COMPlusFrameHandlerRevCom @@ -872,23 +869,6 @@ getFPReturn4: retn 8 _getFPReturn@8 endp -; VOID __cdecl UMThunkStubRareDisable() -; -; @todo: this is very similar to StubRareDisable -; -_UMThunkStubRareDisable proc public - push eax - push ecx - - push eax ; Push the UMEntryThunk - push ecx ; Push thread - call _UMThunkStubRareDisableWorker@8 - - pop ecx - pop eax - retn -_UMThunkStubRareDisable endp - ; void __stdcall JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle) _JIT_ProfilerEnterLeaveTailcallStub@4 proc public @@ -1432,6 +1412,22 @@ public _ThePreStubPatchLabel@0 ret _ThePreStubPatch@0 endp +_TheUMEntryPrestub@0 proc public + ; push argument registers + push ecx + push edx + + push eax ; UMEntryThunk* + call _TheUMEntryPrestubWorker@4 + + ; pop argument registers + pop edx + pop ecx + + ; eax = PCODE + jmp eax ; Tail Jmp +_TheUMEntryPrestub@0 endp + ifdef FEATURE_COMINTEROP ;========================================================================== ; CLR -> COM generic or late-bound call diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index f0a81d6daeea1..d2d5d1676e95c 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -931,58 +931,6 @@ WORD GetUnpatchedCodeData(LPCBYTE pAddr) #ifndef DACCESS_COMPILE -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) -//------------------------------------------------------------------------- -// One-time creation of special prestub to initialize UMEntryThunks. -//------------------------------------------------------------------------- -Stub *GenerateUMThunkPrestub() -{ - CONTRACT(Stub*) - { - STANDARD_VM_CHECK; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - CPUSTUBLINKER sl; - CPUSTUBLINKER *psl = &sl; - - CodeLabel* rgRareLabels[] = { psl->NewCodeLabel(), - psl->NewCodeLabel(), - psl->NewCodeLabel() - }; - - - CodeLabel* rgRejoinLabels[] = { psl->NewCodeLabel(), - psl->NewCodeLabel(), - psl->NewCodeLabel() - }; - - // emit the initial prolog - psl->EmitComMethodStubProlog(UMThkCallFrame::GetMethodFrameVPtr(), rgRareLabels, rgRejoinLabels, FALSE /*Don't profile*/); - - // mov ecx, [esi+UMThkCallFrame.pUMEntryThunk] - psl->X86EmitIndexRegLoad(kECX, kESI, UMThkCallFrame::GetOffsetOfUMEntryThunk()); - - // The call conv is a __stdcall - psl->X86EmitPushReg(kECX); - - // call UMEntryThunk::DoRunTimeInit - psl->X86EmitCall(psl->NewExternalCodeLabel((LPVOID)UMEntryThunk::DoRunTimeInit), 4); - - // mov ecx, [esi+UMThkCallFrame.pUMEntryThunk] - psl->X86EmitIndexRegLoad(kEAX, kESI, UMThkCallFrame::GetOffsetOfUMEntryThunk()); - - // lea eax, [eax + UMEntryThunk.m_code] // point to fixedup UMEntryThunk - psl->X86EmitOp(0x8d, kEAX, kEAX, - UMEntryThunk::GetCodeOffset() + UMEntryThunkCode::GetEntryPointOffset()); - - psl->EmitComMethodStubEpilog(UMThkCallFrame::GetMethodFrameVPtr(), rgRareLabels, rgRejoinLabels, FALSE /*Don't profile*/); - - RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()); -} -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL - Stub *GenerateInitPInvokeFrameHelper() { CONTRACT(Stub*) diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp index 3d2e0e4dddeca..15dd0667dd6c4 100644 --- a/src/coreclr/vm/i386/excepx86.cpp +++ b/src/coreclr/vm/i386/excepx86.cpp @@ -113,17 +113,6 @@ static void RtlUnwindCallback() _ASSERTE(!"Should never get here"); } -BOOL NExportSEH(EXCEPTION_REGISTRATION_RECORD* pEHR) -{ - LIMITED_METHOD_CONTRACT; - - if ((LPVOID)pEHR->Handler == (LPVOID)UMThunkPrestubHandler) - { - return TRUE; - } - return FALSE; -} - BOOL FastNExportSEH(EXCEPTION_REGISTRATION_RECORD* pEHR) { LIMITED_METHOD_CONTRACT; @@ -156,9 +145,8 @@ BOOL IsUnmanagedToManagedSEHHandler(EXCEPTION_REGISTRATION_RECORD *pEstablisherF // // ComPlusFrameSEH() is for COMPlusFrameHandler & COMPlusNestedExceptionHandler. // FastNExportSEH() is for FastNExportExceptHandler. - // NExportSEH() is for UMThunkPrestubHandler. // - return (ComPlusFrameSEH(pEstablisherFrame) || FastNExportSEH(pEstablisherFrame) || NExportSEH(pEstablisherFrame) || ReverseCOMSEH(pEstablisherFrame)); + return (ComPlusFrameSEH(pEstablisherFrame) || FastNExportSEH(pEstablisherFrame) || ReverseCOMSEH(pEstablisherFrame)); } Frame *GetCurrFrame(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame) @@ -166,10 +154,7 @@ Frame *GetCurrFrame(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame) Frame *pFrame; WRAPPER_NO_CONTRACT; _ASSERTE(IsUnmanagedToManagedSEHHandler(pEstablisherFrame)); - if (NExportSEH(pEstablisherFrame)) - pFrame = ((ComToManagedExRecord *)pEstablisherFrame)->GetCurrFrame(); - else - pFrame = ((FrameHandlerExRecord *)pEstablisherFrame)->GetCurrFrame(); + pFrame = ((FrameHandlerExRecord *)pEstablisherFrame)->GetCurrFrame(); // Assert that the exception frame is on the thread or that the exception frame is the top frame. _ASSERTE(GetThreadNULLOk() == NULL || GetThread()->GetFrame() == (Frame*)-1 || GetThread()->GetFrame() <= pFrame); @@ -3384,52 +3369,6 @@ EXCEPTION_HANDLER_IMPL(FastNExportExceptHandler) return retval; } - -// Just like a regular NExport handler -- except it pops an extra frame on unwind. A handler -// like this is needed by the COMMethodStubProlog code. It first pushes a frame -- and then -// pushes a handler. When we unwind, we need to pop the extra frame to avoid corrupting the -// frame chain in the event of an unmanaged catcher. -// -EXCEPTION_HANDLER_IMPL(UMThunkPrestubHandler) -{ - // @todo: we'd like to have a dynamic contract here, but there's a problem. (Bug 129180) Enter on the CRST used - // in HandleManagedFault leaves the no-trigger count incremented. The destructor of this contract will restore - // it to zero, then when we leave the CRST in LinkFrameAndThrow, we assert because we're trying to decrement the - // gc-trigger count down past zero. The solution is to fix what we're doing with this CRST. - STATIC_CONTRACT_THROWS; // COMPlusFrameHandler throws - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_MODE_ANY; - - EXCEPTION_DISPOSITION retval = ExceptionContinueSearch; - - // We must forward to the COMPlusFrameHandler. This will unwind the Frame Chain up to here, and also leave the - // preemptive GC mode set correctly. - retval = EXCEPTION_HANDLER_FWD(COMPlusFrameHandler); - -#ifdef _DEBUG - // If the exception is escaping the last CLR personality routine on the stack, - // then state a flag on the thread to indicate so. - if (retval == ExceptionContinueSearch) - { - SetReversePInvokeEscapingUnhandledExceptionStatus(IS_UNWINDING(pExceptionRecord->ExceptionFlags), pEstablisherFrame); - } -#endif // _DEBUG - - if (IS_UNWINDING(pExceptionRecord->ExceptionFlags)) - { - // Pops an extra frame on unwind. - - GCX_COOP(); // Must be cooperative to modify frame chain. - - Thread *pThread = GetThread(); - Frame *pFrame = pThread->GetFrame(); - pFrame->ExceptionUnwind(); - pFrame->Pop(pThread); - } - - return retval; -} - #ifdef FEATURE_COMINTEROP // The reverse COM interop path needs to be sure to pop the ComMethodFrame that is pushed, but we do not want // to have an additional FS:0 handler between the COM callsite and the call into managed. So we push this diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 3f4a7ed531273..74d55fd4544db 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -2445,44 +2445,21 @@ VOID StubLinkerCPU::X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedR #endif // TARGET_UNIX } -#if defined(TARGET_X86) +#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) -#if defined(PROFILING_SUPPORTED) && !defined(FEATURE_STUBS_AS_IL) +#if defined(PROFILING_SUPPORTED) VOID StubLinkerCPU::EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame) { STANDARD_VM_CONTRACT; - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // Load the methoddesc into ECX (UMThkCallFrame->m_pvDatum->m_pMD) - X86EmitIndexRegLoad(kECX, regFrame, UMThkCallFrame::GetOffsetOfDatum()); - X86EmitIndexRegLoad(kECX, kECX, UMEntryThunk::GetOffsetOfMethodDesc()); - - // Push arguments and notify profiler - X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason - X86EmitPushReg(kECX); // MethodDesc* - X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*)); - } - -#ifdef FEATURE_COMINTEROP - else if (pFrameVptr == ComMethodFrame::GetMethodFrameVPtr()) - { - // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD) - X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum()); - X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc()); - - // Push arguments and notify profiler - X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason - X86EmitPushReg(kECX); // MethodDesc* - X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*)); - } -#endif // FEATURE_COMINTEROP + // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD) + X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum()); + X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc()); - // Unrecognized frame vtbl - else - { - _ASSERTE(!"Unrecognized vtble passed to EmitComMethodStubProlog with profiling turned on."); - } + // Push arguments and notify profiler + X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason + X86EmitPushReg(kECX); // MethodDesc* + X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*)); } @@ -2491,50 +2468,21 @@ VOID StubLinkerCPU::EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame) CONTRACTL { STANDARD_VM_CHECK; -#ifdef FEATURE_COMINTEROP - PRECONDITION(pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr() || pFrameVptr == ComMethodFrame::GetMethodFrameVPtr()); -#else - PRECONDITION(pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()); -#endif // FEATURE_COMINTEROP + PRECONDITION(pFrameVptr == ComMethodFrame::GetMethodFrameVPtr()); } CONTRACTL_END; - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // Load the methoddesc into ECX (UMThkCallFrame->m_pvDatum->m_pMD) - X86EmitIndexRegLoad(kECX, regFrame, UMThkCallFrame::GetOffsetOfDatum()); - X86EmitIndexRegLoad(kECX, kECX, UMEntryThunk::GetOffsetOfMethodDesc()); - - // Push arguments and notify profiler - X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason - X86EmitPushReg(kECX); // MethodDesc* - X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*)); - } - -#ifdef FEATURE_COMINTEROP - else if (pFrameVptr == ComMethodFrame::GetMethodFrameVPtr()) - { - // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD) - X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum()); - X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc()); - - // Push arguments and notify profiler - X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason - X86EmitPushReg(kECX); // MethodDesc* - X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*)); - } -#endif // FEATURE_COMINTEROP + // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD) + X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum()); + X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc()); - // Unrecognized frame vtbl - else - { - _ASSERTE(!"Unrecognized vtble passed to EmitComMethodStubEpilog with profiling turned on."); - } + // Push arguments and notify profiler + X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason + X86EmitPushReg(kECX); // MethodDesc* + X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*)); } -#endif // PROFILING_SUPPORTED && !FEATURE_STUBS_AS_IL - +#endif // PROFILING_SUPPORTED -#ifndef FEATURE_STUBS_AS_IL //======================================================================== // Prolog for entering managed code from COM // pushes the appropriate frame ptr @@ -2584,13 +2532,6 @@ void StubLinkerCPU::EmitComMethodStubProlog(TADDR pFrameVptr, // lea esi, [esp+4] ;; set ESI -> new frame X86EmitEspOffset(0x8d, kESI, 4); // lea ESI, [ESP+4] - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // Preserve argument registers for thiscall/fastcall - X86EmitPushReg(kECX); - X86EmitPushReg(kEDX); - } - // Emit Setup thread EmitSetup(rgRareLabels[0]); // rareLabel for rare setup EmitLabel(rgRejoinLabels[0]); // rejoin label for rare setup @@ -2639,23 +2580,6 @@ void StubLinkerCPU::EmitComMethodStubProlog(TADDR pFrameVptr, // mov [ebx + Thread.GetFrame()], esi X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kESI); - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // push UnmanagedToManagedExceptHandler - X86EmitPushImmPtr((LPVOID)UMThunkPrestubHandler); - - // mov eax, fs:[0] - static const BYTE codeSEH1[] = { 0x64, 0xA1, 0x0, 0x0, 0x0, 0x0}; - EmitBytes(codeSEH1, sizeof(codeSEH1)); - - // push eax - X86EmitPushReg(kEAX); - - // mov dword ptr fs:[0], esp - static const BYTE codeSEH2[] = { 0x64, 0x89, 0x25, 0x0, 0x0, 0x0, 0x0}; - EmitBytes(codeSEH2, sizeof(codeSEH2)); - } - #if _DEBUG if (Frame::ShouldLogTransitions()) { @@ -2692,19 +2616,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, EmitCheckGSCookie(kESI, UnmanagedToManagedFrame::GetOffsetOfGSCookie()); - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // if we are using exceptions, unlink the SEH - // mov ecx,[esp] ;;pointer to the next exception record - X86EmitEspOffset(0x8b, kECX, 0); - - // mov dword ptr fs:[0], ecx - static const BYTE codeSEH[] = { 0x64, 0x89, 0x0D, 0x0, 0x0, 0x0, 0x0 }; - EmitBytes(codeSEH, sizeof(codeSEH)); - - X86EmitAddEsp(sizeof(EXCEPTION_REGISTRATION_RECORD)); - } - // mov [ebx + Thread.GetFrame()], edi ;; restore previous frame X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kEDI); @@ -2714,13 +2625,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, EmitEnable(rgRareLabels[2]); // rare gc EmitLabel(rgRejoinLabels[2]); // rejoin for rare gc - if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr()) - { - // Restore argument registers for thiscall/fastcall - X86EmitPopReg(kEDX); - X86EmitPopReg(kECX); - } - // add esp, popstack X86EmitAddEsp(sizeof(GSCookie) + UnmanagedToManagedFrame::GetOffsetOfCalleeSavedRegisters()); @@ -2761,7 +2665,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, EmitLabel(rgRareLabels[0]); // label for rare setup thread EmitRareSetup(rgRejoinLabels[0], /*fThrow*/ TRUE); // emit rare setup thread } -#endif // !FEATURE_STUBS_AS_IL //--------------------------------------------------------------- // Emit code to store the setup current Thread structure in eax. @@ -2792,16 +2695,12 @@ VOID StubLinkerCPU::EmitRareSetup(CodeLabel *pRejoinPoint, BOOL fThrow) { STANDARD_VM_CONTRACT; -#ifndef FEATURE_COMINTEROP - _ASSERTE(fThrow); -#else // !FEATURE_COMINTEROP if (!fThrow) { X86EmitPushReg(kESI); X86EmitCall(NewExternalCodeLabel((LPVOID) CreateThreadBlockReturnHr), sizeof(void*)); } else -#endif // !FEATURE_COMINTEROP { X86EmitCall(NewExternalCodeLabel((LPVOID) CreateThreadBlockThrow), 0); } @@ -2811,10 +2710,6 @@ VOID StubLinkerCPU::EmitRareSetup(CodeLabel *pRejoinPoint, BOOL fThrow) X86EmitNearJump(pRejoinPoint); } -//======================================================================== -#endif // TARGET_X86 -//======================================================================== -#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) //======================================================================== // Epilog for stubs that enter managed code from COM // @@ -2920,9 +2815,9 @@ void StubLinkerCPU::EmitSharedComMethodStubEpilog(TADDR pFrameVptr, EmitRareSetup(rgRejoinLabels[0],/*fThrow*/ FALSE); // emit rare setup thread } -//======================================================================== #endif // defined(FEATURE_COMINTEROP) && defined(TARGET_X86) + #if !defined(FEATURE_STUBS_AS_IL) && defined(TARGET_X86) /*============================================================================== Pushes a TransitionFrame on the stack @@ -3437,7 +3332,7 @@ VOID StubLinkerCPU::EmitUnwindInfoCheckSubfunction() #endif // defined(_DEBUG) && defined(STUBLINKER_GENERATES_UNWIND_INFO) -#ifdef TARGET_X86 +#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) //----------------------------------------------------------------------- // Generates the inline portion of the code to enable preemptive GC. Hopefully, @@ -3579,7 +3474,6 @@ VOID StubLinkerCPU::EmitRareDisable(CodeLabel *pRejoinPoint) X86EmitNearJump(pRejoinPoint); } -#ifdef FEATURE_COMINTEROP //----------------------------------------------------------------------- // Generates the out-of-line portion of the code to disable preemptive GC. // After the work is done, the code normally jumps back to the "pRejoinPoint" @@ -3611,10 +3505,8 @@ VOID StubLinkerCPU::EmitRareDisableHRESULT(CodeLabel *pRejoinPoint, CodeLabel *p X86EmitNearJump(pExitPoint); } -#endif // FEATURE_COMINTEROP - -#endif // TARGET_X86 +#endif // defined(FEATURE_COMINTEROP) && defined(TARGET_X86) VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray) diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 02ab6e9d253ea..c719057e97ea3 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -250,17 +250,6 @@ class StubLinkerCPU : public StubLinker ); VOID X86EmitPushEBPframe(); -#if defined(TARGET_X86) -#if defined(PROFILING_SUPPORTED) && !defined(FEATURE_STUBS_AS_IL) - // These are used to emit calls to notify the profiler of transitions in and out of - // managed code through COM->COM+ interop or N/Direct - VOID EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame); - VOID EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame); -#endif // PROFILING_SUPPORTED && !FEATURE_STUBS_AS_IL -#endif // TARGET_X86 - - - // Emits the most efficient form of the operation: // // opcode altreg, [basereg + scaledreg*scale + ofs] @@ -340,6 +329,7 @@ class StubLinkerCPU : public StubLinker #endif } +#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) VOID EmitEnable(CodeLabel *pForwardRef); VOID EmitRareEnable(CodeLabel *pRejoinPoint); @@ -349,20 +339,13 @@ class StubLinkerCPU : public StubLinker VOID EmitSetup(CodeLabel *pForwardRef); VOID EmitRareSetup(CodeLabel* pRejoinPoint, BOOL fThrow); +#endif // FEATURE_COMINTEROP && TARGET_X86 #ifndef FEATURE_STUBS_AS_IL VOID EmitMethodStubProlog(TADDR pFrameVptr, int transitionBlockOffset); VOID EmitMethodStubEpilog(WORD numArgBytes, int transitionBlockOffset); VOID EmitCheckGSCookie(X86Reg frameReg, int gsCookieOffset); - -#ifdef TARGET_X86 - void EmitComMethodStubProlog(TADDR pFrameVptr, CodeLabel** rgRareLabels, - CodeLabel** rgRejoinLabels, BOOL bShouldProfile); - - void EmitComMethodStubEpilog(TADDR pFrameVptr, CodeLabel** rgRareLabels, - CodeLabel** rgRejoinLabels, BOOL bShouldProfile); -#endif // TARGET_X86 #endif // !FEATURE_STUBS_AS_IL #ifdef TARGET_X86 @@ -379,6 +362,20 @@ class StubLinkerCPU : public StubLinker VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg); #if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) + +#if defined(PROFILING_SUPPORTED) + // These are used to emit calls to notify the profiler of transitions in and out of + // managed code through COM->COM+ interop or N/Direct + VOID EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame); + VOID EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame); +#endif // PROFILING_SUPPORTED + + void EmitComMethodStubProlog(TADDR pFrameVptr, CodeLabel** rgRareLabels, + CodeLabel** rgRejoinLabels, BOOL bShouldProfile); + + void EmitComMethodStubEpilog(TADDR pFrameVptr, CodeLabel** rgRareLabels, + CodeLabel** rgRejoinLabels, BOOL bShouldProfile); + //======================================================================== // shared Epilog for stubs that enter managed code from COM // uses a return thunk within the method desc diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 3bf1abcfcfbee..b509a5c221ed1 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -1063,7 +1063,7 @@ CorClassIfaceAttr ReadClassInterfaceTypeCustomAttribute(TypeHandle type) { // Check the class interface attribute at the assembly level. Assembly *pAssembly = type.GetAssembly(); - hr = TryParseClassInterfaceAttribute(pAssembly->GetManifestModule(), pAssembly->GetManifestToken(), &attrValueMaybe); + hr = TryParseClassInterfaceAttribute(pAssembly->GetModule(), pAssembly->GetManifestToken(), &attrValueMaybe); if (FAILED(hr)) ThrowHR(hr, BFA_BAD_CLASS_INT_CA_FORMAT); } @@ -2501,8 +2501,8 @@ HRESULT GetTypeLibGuidForAssembly(Assembly *pAssembly, GUID *pGuid) CQuickArray rName; // String for guid. ULONG cbData; // Size of the string in bytes. - // Get GUID from Assembly, else from Manifest Module, else Generate from name. - hr = pAssembly->GetManifestImport()->GetItemGuid(TokenFromRid(1, mdtAssembly), pGuid); + // Get GUID from Assembly, else Generate from name. + hr = pAssembly->GetMDImport()->GetItemGuid(TokenFromRid(1, mdtAssembly), pGuid); if (*pGuid == GUID_NULL) { @@ -2548,7 +2548,7 @@ HRESULT GetTypeLibVersionForAssembly( ULONG cbData = 0; // Check to see if the TypeLibVersionAttribute is set. - IfFailRet(pAssembly->GetManifestImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_TYPELIBVERSION_TYPE, (const void**)&pbData, &cbData)); + IfFailRet(pAssembly->GetMDImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_TYPELIBVERSION_TYPE, (const void**)&pbData, &cbData)); // For attribute contents, see https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.typelibversionattribute if (cbData >= (2 + 2 * sizeof(UINT32))) diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 109f98ceecfe1..27d2452491e2a 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -529,16 +529,8 @@ ftype BankersRound(ftype value) if ((value -(integerPart +0.5)) == 0.0) { // round to even -#if defined(TARGET_ARM) && defined(FEATURE_CORESYSTEM) - // @ARMTODO: On ARM when building on CoreSystem (where we link against the system CRT) an attempt to - // use fmod(float, float) fails to link (apparently this is converted to a reference to fmodf, which - // is not included in the system CRT). Use the double version instead. - if (fmod(double(integerPart), double(2.0)) == 0.0) - return integerPart; -#else if (fmod(ftype(integerPart), ftype(2.0)) == 0.0) return integerPart; -#endif // Else return the nearest even integer return (ftype)_copysign(ceil(fabs(value+0.5)), @@ -1442,7 +1434,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass_Helper, DomainLocalModul HELPER_METHOD_FRAME_BEGIN_RET_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1464,7 +1456,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass, DomainLocalModule *pLoc if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1486,7 +1478,7 @@ HCIMPL2(void, JIT_ClassInitDynamicClass_Helper, DomainLocalModule *pLocalModule, HELPER_METHOD_FRAME_BEGIN_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1525,7 +1517,7 @@ HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass_Helper, DomainLocalModule * HELPER_METHOD_FRAME_BEGIN_RET_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1547,7 +1539,7 @@ HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass, DomainLocalModule *pLocalM if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1861,7 +1853,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, DomainLocalModule if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_NONGCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_NONGCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); return retval; @@ -1872,7 +1864,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, DomainLocalModule // then we have to go through the slow path // Obtain the Module - Module * pModule = pDomainLocalModule->GetDomainFile()->GetModule(); + Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule(); // Obtain the MethodTable MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID); @@ -1909,7 +1901,7 @@ HCIMPL2(void*, JIT_GetSharedGCThreadStaticBaseDynamicClass, DomainLocalModule *p if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1921,7 +1913,7 @@ HCIMPL2(void*, JIT_GetSharedGCThreadStaticBaseDynamicClass, DomainLocalModule *p // then we have to go through the slow path // Obtain the Module - Module * pModule = pDomainLocalModule->GetDomainFile()->GetModule(); + Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule(); // Obtain the MethodTable MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e28434acabe56..7c298b847400e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -953,7 +953,7 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken ThrowBadTokenException(pResolvedToken); { - DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK); + DomainAssembly *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK); if (pTargetModule == NULL) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); th = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable()); @@ -2029,54 +2029,54 @@ bool CEEInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, return result; } +static unsigned MarkGCField(BYTE* gcPtrs, CorInfoGCType type) +{ + STANDARD_VM_CONTRACT; + + // Ensure that if we have multiple fields with the same offset, + // that we don't double count the data in the gc layout. + if (*gcPtrs == TYPE_GC_NONE) + { + *gcPtrs = type; + return 1; + } + else if (*gcPtrs != type) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + + return 0; +} + /*********************************************************************/ static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs) { STANDARD_VM_CONTRACT; - unsigned result = 0; - _ASSERTE(pMT->IsValueType()); if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) - { - if (gcPtrs[0] == TYPE_GC_NONE) - { - gcPtrs[0] = TYPE_GC_BYREF; - result++; - } - else if (gcPtrs[0] != TYPE_GC_BYREF) - { - COMPlusThrowHR(COR_E_BADIMAGEFORMAT); - } - return result; - } + return MarkGCField(gcPtrs, TYPE_GC_BYREF); + unsigned result = 0; ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) { int fieldStartIndex = pFD->GetOffset() / TARGET_POINTER_SIZE; - if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE) - { - if (pFD->IsObjRef()) - { - if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE) - { - gcPtrs[fieldStartIndex] = TYPE_GC_REF; - result++; - } - else if (gcPtrs[fieldStartIndex] != TYPE_GC_REF) - { - COMPlusThrowHR(COR_E_BADIMAGEFORMAT); - } - } - } - else + if (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE) { MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); result += ComputeGCLayout(pFieldMT, gcPtrs + fieldStartIndex); } + else if (pFD->IsObjRef()) + { + result += MarkGCField(gcPtrs + fieldStartIndex, TYPE_GC_REF); + } + else if (pFD->IsByRef()) + { + result += MarkGCField(gcPtrs + fieldStartIndex, TYPE_GC_BYREF); + } } return result; } @@ -9002,9 +9002,6 @@ CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, FieldDesc* field = (FieldDesc*) fieldHnd; CorElementType type = field->GetFieldType(); - // TODO should not burn the time to do this for anything but Value Classes - _ASSERTE(type != ELEMENT_TYPE_BYREF); - if (type == ELEMENT_TYPE_I) { PTR_MethodTable enclosingMethodTable = field->GetApproxEnclosingMethodTable(); @@ -12736,7 +12733,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, LARGE_INTEGER methodJitTimeStop; QueryPerformanceCounter(&methodJitTimeStop); SString codeBase; - ftn->GetModule()->GetDomainFile()->GetPEAssembly()->GetPathOrCodeBase(codeBase); + ftn->GetModule()->GetDomainAssembly()->GetPEAssembly()->GetPathOrCodeBase(codeBase); codeBase.AppendPrintf(W(",0x%x,%d,%d\n"), //(const WCHAR *)codeBase, //module name ftn->GetMemberDef(), //method token @@ -12818,13 +12815,11 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, "Jitted Entry at" FMT_ADDR "method %s::%s %s\n", DBG_ADDR(nativeEntry), ftn->m_pszDebugClassName, ftn->m_pszDebugMethodName, ftn->m_pszDebugMethodSignature)); -#if defined(FEATURE_CORESYSTEM) - #ifdef _DEBUG LPCUTF8 pszDebugClassName = ftn->m_pszDebugClassName; LPCUTF8 pszDebugMethodName = ftn->m_pszDebugMethodName; LPCUTF8 pszDebugMethodSignature = ftn->m_pszDebugMethodSignature; -#else +#elif 0 LPCUTF8 pszNamespace; LPCUTF8 pszDebugClassName = ftn->GetMethodTable()->GetFullyQualifiedNameInfo(&pszNamespace); LPCUTF8 pszDebugMethodName = ftn->GetName(); @@ -12833,7 +12828,6 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry), // pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode); -#endif ClrFlushInstructionCache(nativeEntry, sizeOfCode); ret = (PCODE)nativeEntry; diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 5b5c9d142c89d..657ff7b2b40ce 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -360,7 +360,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (iData.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -393,7 +393,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (i.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -420,7 +420,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (i.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -672,7 +672,7 @@ BOOL LoaderAllocator::Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator) DomainAssembly* pDomainAssembly = (DomainAssembly*)(pID->GetDomainAssemblyIterator()); if (pDomainAssembly != NULL) { - Assembly *pAssembly = pDomainAssembly->GetCurrentAssembly(); + Assembly *pAssembly = pDomainAssembly->GetAssembly(); pLoaderAllocator->m_pFirstDomainAssemblyFromSameALCToDelete = pAssembly->GetDomainAssembly(); } diff --git a/src/coreclr/vm/memberload.cpp b/src/coreclr/vm/memberload.cpp index 78fdb518a1618..4c8e7dc7e2a92 100644 --- a/src/coreclr/vm/memberload.cpp +++ b/src/coreclr/vm/memberload.cpp @@ -277,7 +277,7 @@ void MemberLoader::GetDescFromMemberRef(Module * pModule, { case mdtModuleRef: { - DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), parent); + DomainAssembly *pTargetModule = pModule->LoadModule(GetAppDomain(), parent); if (pTargetModule == NULL) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); typeHnd = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable()); diff --git a/src/coreclr/vm/methoditer.cpp b/src/coreclr/vm/methoditer.cpp index 841b3214d2e2d..da24a53d064a1 100644 --- a/src/coreclr/vm/methoditer.cpp +++ b/src/coreclr/vm/methoditer.cpp @@ -77,11 +77,7 @@ BOOL LoadedMethodDescIterator::Next( dbg_m_pDomainAssembly = *pDomainAssemblyHolder; #endif //_DEBUG - m_moduleIterator = (*pDomainAssemblyHolder)->IterateModules(m_moduleIterationFlags); - -ADVANCE_MODULE: - if (!m_moduleIterator.Next()) - goto ADVANCE_ASSEMBLY; + m_currentModule = (*pDomainAssemblyHolder)->GetModule(); if (m_mainMD->HasClassInstantiation()) { @@ -96,7 +92,7 @@ BOOL LoadedMethodDescIterator::Next( if (m_mainMD->HasClassInstantiation()) { if (!GetCurrentModule()->GetAvailableParamTypes()->FindNext(&m_typeIterator, &m_typeIteratorEntry)) - goto ADVANCE_MODULE; + goto ADVANCE_ASSEMBLY; if (CORCOMPILE_IS_POINTER_TAGGED(m_typeIteratorEntry->GetTypeHandle().AsTAddr())) goto ADVANCE_TYPE; @@ -130,7 +126,7 @@ BOOL LoadedMethodDescIterator::Next( } else if (m_startedNonGenericType) { - goto ADVANCE_MODULE; + goto ADVANCE_ASSEMBLY; } else { @@ -188,7 +184,7 @@ Module * LoadedMethodDescIterator::GetCurrentModule() } CONTRACTL_END - return m_moduleIterator.GetLoadedModule(); + return m_currentModule; } MethodDesc *LoadedMethodDescIterator::Current() @@ -228,8 +224,7 @@ LoadedMethodDescIterator::Start( AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemblyIterationFlags, - ModuleIterationOption moduleIterationFlags) + AssemblyIterationFlags assemblyIterationFlags) { CONTRACTL { @@ -241,7 +236,6 @@ LoadedMethodDescIterator::Start( CONTRACTL_END; m_assemIterationFlags = assemblyIterationFlags; - m_moduleIterationFlags = moduleIterationFlags; m_mainMD = NULL; m_module = pModule; m_md = md; diff --git a/src/coreclr/vm/methoditer.h b/src/coreclr/vm/methoditer.h index 71192be2e0c01..fdc49e2ce5971 100644 --- a/src/coreclr/vm/methoditer.h +++ b/src/coreclr/vm/methoditer.h @@ -9,7 +9,7 @@ #include "instmethhash.h" #include "method.hpp" #include "appdomain.hpp" -#include "domainfile.h" +#include "domainassembly.h" #include "typehash.h" @@ -44,9 +44,8 @@ class LoadedMethodDescIterator // These are used when iterating over an AppDomain AppDomain::AssemblyIterator m_assemIterator; - DomainModuleIterator m_moduleIterator; + Module* m_currentModule; AssemblyIterationFlags m_assemIterationFlags; - ModuleIterationOption m_moduleIterationFlags; EETypeHashTable::Iterator m_typeIterator; EETypeHashEntry * m_typeIteratorEntry; @@ -69,19 +68,17 @@ class LoadedMethodDescIterator void Start(AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution), - ModuleIterationOption moduleIterationFlags = kModIterIncludeLoaded); + AssemblyIterationFlags assemIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); void Start(AppDomain * pAppDomain, Module *pModule, mdMethodDef md, MethodDesc *pDesc); LoadedMethodDescIterator( AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemblyIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution), - ModuleIterationOption moduleIterationFlags = kModIterIncludeLoaded) + AssemblyIterationFlags assemblyIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)) { LIMITED_METHOD_CONTRACT; - Start(pAppDomain, pModule, md, assemblyIterationFlags, moduleIterationFlags); + Start(pAppDomain, pModule, md, assemblyIterationFlags); } LoadedMethodDescIterator(void); diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 86a033a0593a2..76c552a304284 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1517,6 +1517,8 @@ class MethodTable inline BOOL HasExplicitSize(); + inline BOOL IsAutoLayoutOrHasAutoLayoutField(); + UINT32 GetNativeSize(); DWORD GetBaseSize() diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index d14a73532b6e1..72b628dae9545 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -947,6 +947,13 @@ inline BOOL MethodTable::HasExplicitSize() return GetClass()->HasExplicitSize(); } +//========================================================================================== +inline BOOL MethodTable::IsAutoLayoutOrHasAutoLayoutField() +{ + LIMITED_METHOD_CONTRACT; + return GetClass()->IsAutoLayoutOrHasAutoLayoutField(); +} + //========================================================================================== inline DWORD MethodTable::GetPerInstInfoSize() { diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 694e03cca35f2..82499f314e4f3 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -3935,6 +3935,27 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, break; } + case ELEMENT_TYPE_BYREF: + { + dwLog2FieldSize = LOG2_PTRSIZE; + if (fIsStatic) + { + // Byref-like types cannot be used for static fields + BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_STATICFIELD); + } + if (!bmtFP->fIsByRefLikeType) + { + // Non-byref-like types cannot contain byref-like instance fields + BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_INSTANCEFIELD); + } + break; + } + + case ELEMENT_TYPE_TYPEDBYREF: + { + goto IS_VALUETYPE; + } + // Class type variable (method type variables aren't allowed in fields) // These only occur in open types used for verification/reflection. case ELEMENT_TYPE_VAR: @@ -3970,7 +3991,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, { Module * pTokenModule; dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule); - fIsByValue = TRUE; // By-value class BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0); @@ -4042,6 +4062,11 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, pByValueClass = (MethodTable *)-1; } } // If 'this' is a value class + } + // TypedReference shares the rest of the code here +IS_VALUETYPE: + { + fIsByValue = TRUE; // It's not self-referential so try to load it if (pByValueClass == NULL) @@ -8648,6 +8673,14 @@ MethodTableBuilder::HandleExplicitLayout( BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL); } } + + if (!numInstanceFieldBytes.IsOverflow() && numInstanceFieldBytes.Value() == 0) + { + // If we calculate a 0-byte size here, we should have also calculated a 0-byte size + // in the initial layout algorithm. + _ASSERTE(GetLayoutInfo()->IsZeroSized()); + numInstanceFieldBytes = S_UINT32(1); + } } // The GC requires that all valuetypes containing orefs be sized to a multiple of TARGET_POINTER_SIZE. diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index c573184012284..5a071c2b9f8f9 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -1056,6 +1056,78 @@ OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo() } #endif // FEATURE_COMINTEROP +namespace +{ + MarshalInfo::MarshalType GetDisabledMarshallerType( + Module* pModule, + SigPointer sig, + const SigTypeContext * pTypeContext, + MethodTable** pMTOut, + UINT* errorResIDOut) + { + switch (sig.PeekElemTypeNormalized(pModule, pTypeContext)) + { + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_U1: + return MarshalInfo::MARSHAL_TYPE_GENERIC_U1; + case ELEMENT_TYPE_I1: + return MarshalInfo::MARSHAL_TYPE_GENERIC_1; + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_U2: + return MarshalInfo::MARSHAL_TYPE_GENERIC_U2; + case ELEMENT_TYPE_I2: + return MarshalInfo::MARSHAL_TYPE_GENERIC_2; + case ELEMENT_TYPE_U4: + return MarshalInfo::MARSHAL_TYPE_GENERIC_U4; + case ELEMENT_TYPE_I4: + return MarshalInfo::MARSHAL_TYPE_GENERIC_4; + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_I8: + return MarshalInfo::MARSHAL_TYPE_GENERIC_8; +#ifdef TARGET_64BIT + case ELEMENT_TYPE_U: + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_FNPTR: + case ELEMENT_TYPE_I: + return MarshalInfo::MARSHAL_TYPE_GENERIC_8; +#else + case ELEMENT_TYPE_U: + return MarshalInfo::MARSHAL_TYPE_GENERIC_U4; + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_FNPTR: + case ELEMENT_TYPE_I: + return MarshalInfo::MARSHAL_TYPE_GENERIC_4; +#endif + case ELEMENT_TYPE_R4: + return MarshalInfo::MARSHAL_TYPE_FLOAT; + case ELEMENT_TYPE_R8: + return MarshalInfo::MARSHAL_TYPE_DOUBLE; + case ELEMENT_TYPE_VAR: + case ELEMENT_TYPE_VALUETYPE: + { + TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext); + MethodTable* pMT = sigTH.GetMethodTable(); + + if (!pMT->IsValueType() || pMT->ContainsPointers()) + { + *errorResIDOut = IDS_EE_BADMARSHAL_MARSHAL_DISABLED; + return MarshalInfo::MARSHAL_TYPE_UNKNOWN; + } + if (pMT->IsAutoLayoutOrHasAutoLayoutField()) + { + *errorResIDOut = IDS_EE_BADMARSHAL_AUTOLAYOUT; + return MarshalInfo::MARSHAL_TYPE_UNKNOWN; + } + *pMTOut = pMT; + return MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS; + } + default: + *errorResIDOut = IDS_EE_BADMARSHAL_MARSHAL_DISABLED; + return MarshalInfo::MARSHAL_TYPE_UNKNOWN; + } + } +} + //========================================================================== // Constructs MarshalInfo. //========================================================================== @@ -1163,7 +1235,30 @@ MarshalInfo::MarshalInfo(Module* pModule, m_byref = TRUE; #endif + // For COM IL-stub scenarios, we do not support disabling the runtime marshalling support. + // The runtime-integrated COM support uses a significant portion of the marshalling infrastructure as well as + // quite a bit of its own custom marshalling infrastructure to function in basically any aspect. + // As a result, disabling marshalling in COM scenarios isn't useful. Instead, we recommend that people set the + // feature switch to false to disable the runtime COM support if they want it disabled. + // For field marshalling scenarios, we also don't disable runtime marshalling. If we're already in a field + // marshalling scenario, we've already decided that the context for the owning type is using runtime marshalling, + // so the fields of the struct should also use runtime marshalling. + const bool useRuntimeMarshalling = ms != MARSHAL_SCENARIO_NDIRECT || pModule->IsRuntimeMarshallingEnabled(); + if (!useRuntimeMarshalling) + { + m_in = TRUE; + m_out = FALSE; + m_byref = FALSE; + m_type = GetDisabledMarshallerType( + pModule, + sig, + pTypeContext, + &m_pMT, + &m_resID); + m_args.m_pMT = m_pMT; + return; + } // Retrieve the native type for the current parameter. if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo)) @@ -1322,6 +1417,7 @@ MarshalInfo::MarshalInfo(Module* pModule, switch (mtype) { case ELEMENT_TYPE_BOOLEAN: + switch (nativeType) { case NATIVE_TYPE_BOOLEAN: @@ -1482,10 +1578,6 @@ MarshalInfo::MarshalInfo(Module* pModule, break; case ELEMENT_TYPE_I: - // Technically the "native int" and "native uint" types aren't supported in the WinRT scenario, - // but we need to not block ourselves from using them to enable accurate managed->native marshalling of - // projected types such as NotifyCollectionChangedEventArgs and NotifyPropertyChangedEventArgs. - if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT)) { m_resID = IDS_EE_BADMARSHAL_I; @@ -1499,7 +1591,6 @@ MarshalInfo::MarshalInfo(Module* pModule, break; case ELEMENT_TYPE_U: - if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT)) { m_resID = IDS_EE_BADMARSHAL_I; @@ -1564,6 +1655,21 @@ MarshalInfo::MarshalInfo(Module* pModule, { TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext); + if (sigTH.GetMethodTable()->IsValueType()) + { + // For value types, we need to handle the "value type marshalled as a COM interface" + // case here for back-compat. + // Otherwise, we can go to the value-type case. +#ifdef FEATURE_COMINTEROP + if (nativeType != NATIVE_TYPE_INTF) + { + goto lValueClass; + } +#else + goto lValueClass; +#endif + } + // Disallow marshaling generic types. if (sigTH.HasInstantiation()) { @@ -1968,14 +2074,13 @@ MarshalInfo::MarshalInfo(Module* pModule, } } - else if (m_pMT->IsArray()) { _ASSERTE(!"This invalid signature should never be hit!"); IfFailGoto(E_FAIL, lFail); } #endif // FEATURE_COMINTEROP - else if (!m_pMT->IsValueType()) + else { if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT)) { @@ -1990,12 +2095,6 @@ MarshalInfo::MarshalInfo(Module* pModule, IfFailGoto(E_FAIL, lFail); #endif // FEATURE_COMINTEROP } - - else - { - _ASSERTE(m_pMT->IsValueType()); - goto lValueClass; - } } break; } @@ -2166,8 +2265,7 @@ MarshalInfo::MarshalInfo(Module* pModule, || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR64T)) || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR128T)) || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR256T)) - // Crossgen scenarios block Vector from even being loaded - || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTORT)) + || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTORT)) ))) { m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION; @@ -2902,6 +3000,15 @@ UINT16 MarshalInfo::GetNativeSize(MarshalType mtype) if (nativeSize == VARIABLESIZE) { _ASSERTE(IsValueClass(mtype)); + // For blittable types, use the GetNumInstanceFieldBytes method. + // When we generate IL stubs when marshalling is disabled, + // we reuse the blittable value class marshalling mechanism. + // In that scenario, only GetNumInstanceFieldBytes will return the correct value. + // GetNativeSize will return the size for when runtime marshalling is enabled. + if (mtype == MARSHAL_TYPE_BLITTABLEVALUECLASS) + { + return (UINT16) m_pMT->GetNumInstanceFieldBytes(); + } return (UINT16) m_pMT->GetNativeSize(); } diff --git a/src/coreclr/vm/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index b747608a18478..18a0a141a8228 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -234,11 +234,11 @@ FileLoadLevel MulticoreJitManager::GetModuleFileLoadLevel(Module * pModule) if (pModule != NULL) { - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); - if (pDomainFile != NULL) + if (pDomainAssembly != NULL) { - level = pDomainFile->GetLoadLevel(); + level = pDomainAssembly->GetLoadLevel(); } } @@ -310,7 +310,7 @@ bool RecorderModuleInfo::SetModule(Module * pMod) SString sAssemblyName; StackScratchBuffer scratch; - pMod->GetAssembly()->GetManifestFile()->GetDisplayName(sAssemblyName); + pMod->GetAssembly()->GetPEAssembly()->GetDisplayName(sAssemblyName); LPCUTF8 pAssemblyName = sAssemblyName.GetUTF8(scratch); unsigned lenAssemblyName = sAssemblyName.GetCount(); @@ -770,21 +770,8 @@ HRESULT MulticoreJitModuleEnumerator::HandleAssembly(DomainAssembly * pAssembly) { STANDARD_VM_CONTRACT; - DomainAssembly::ModuleIterator modIt = pAssembly->IterateModules(kModIterIncludeLoaded); - - HRESULT hr = S_OK; - - while (modIt.Next() && SUCCEEDED(hr)) - { - Module * pModule = modIt.GetModule(); - - if (pModule != NULL) - { - hr = OnModule(pModule); - } - } - - return hr; + Module * pModule = pAssembly->GetModule(); + return OnModule(pModule); } diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index 3bb47cff1acb3..2664a44ad2d18 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -289,7 +289,7 @@ void NativeImage::CheckAssemblyMvid(Assembly *assembly) const } GUID assemblyMvid; - assembly->GetManifestImport()->GetScopeProps(NULL, &assemblyMvid); + assembly->GetMDImport()->GetScopeProps(NULL, &assemblyMvid); const byte *pImageBase = (const BYTE *)m_pImageLayout->GetBase(); const GUID *componentMvid = (const GUID *)&pImageBase[m_pComponentAssemblyMvids->VirtualAddress] + assemblyNameIndex->Index; diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index d5a91b4863c2f..e050e0b1719ff 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -318,7 +318,7 @@ namespace #endif // !TARGET_UNIX NATIVE_LIBRARY_HANDLE hmod = NULL; - PEAssembly *pManifestFile = pAssembly->GetManifestFile(); + PEAssembly *pManifestFile = pAssembly->GetPEAssembly(); PTR_AssemblyBinder pBinder = pManifestFile->GetAssemblyBinder(); //Step 0: Check if the assembly was bound using TPA. @@ -363,7 +363,7 @@ namespace { STANDARD_VM_CONTRACT; - PTR_AssemblyBinder pBinder = pAssembly->GetManifestFile()->GetAssemblyBinder(); + PTR_AssemblyBinder pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); return pBinder->GetManagedAssemblyLoadContext(); } @@ -461,7 +461,7 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; - SString path = pAssembly->GetManifestFile()->GetPath(); + SString path = pAssembly->GetPEAssembly()->GetPath(); SString::Iterator lastPathSeparatorIter = path.End(); if (PEAssembly::FindLastPathSeparator(path, lastPathSeparatorIter)) @@ -610,7 +610,7 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; -#if defined(FEATURE_CORESYSTEM) && !defined(TARGET_UNIX) +#if !defined(TARGET_UNIX) // Try to go straight to System32 for Windows API sets. This is replicating quick check from // the OS implementation of api sets. if (IsWindowsAPISet(wszLibName)) @@ -621,7 +621,7 @@ namespace return hmod; } } -#endif // FEATURE_CORESYSTEM && !TARGET_UNIX +#endif // !TARGET_UNIX if (g_hostpolicy_embedded) { @@ -771,7 +771,7 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryByName(LPCWSTR libraryName, Asse } else { - GetDllImportSearchPathFlags(callingAssembly->GetManifestModule(), + GetDllImportSearchPathFlags(callingAssembly->GetModule(), &dllImportSearchPathFlags, &searchAssemblyDirectory); } diff --git a/src/coreclr/vm/object.inl b/src/coreclr/vm/object.inl index e61f2eb443bab..46b8db4d0d841 100644 --- a/src/coreclr/vm/object.inl +++ b/src/coreclr/vm/object.inl @@ -272,38 +272,4 @@ inline TypeHandle Object::GetGCSafeTypeHandle() const return TypeHandle(pMT); } -template -inline void FindByRefPointerOffsetsInByRefLikeObject(PTR_MethodTable pMT, SIZE_T baseOffset, const F processPointerOffset) -{ - WRAPPER_NO_CONTRACT; - _ASSERTE(pMT != nullptr); - _ASSERTE(pMT->IsByRefLike()); - - if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) - { - processPointerOffset(baseOffset); - return; - } - - ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); - for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) - { - if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE) - { - continue; - } - - // TODO: GetApproxFieldTypeHandleThrowing may throw. This is a potential stress problem for fragile NGen of non-CoreLib - // assemblies. It won't ever throw for CoreCLR with R2R. Figure out if anything needs to be done to deal with the - // exception. - PTR_MethodTable pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); - if (!pFieldMT->IsByRefLike()) - { - continue; - } - - FindByRefPointerOffsetsInByRefLikeObject(pFieldMT, baseOffset + pFD->GetOffset(), processPointerOffset); - } -} - #endif // _OBJECT_INL_ diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 9f228fdb5af82..7926fa8b85bf8 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -552,7 +552,7 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, pDomainAssembly = pAssembly->GetDomainAssembly(); pPEAssembly = pDomainAssembly->GetPEAssembly(); - if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName( + if (FAILED(pAssembly->GetMDImport()->FindManifestResourceByName( szName, &mdResource))) { @@ -1080,7 +1080,7 @@ void PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - DAC_ENUM_VTHIS(); + DAC_ENUM_DTHIS(); EMEM_OUT(("MEM: %p PEAssembly\n", dac_cast(this))); #ifdef _DEBUG diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index 3342e835f265a..8cb12f986c8bb 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -83,11 +83,6 @@ typedef VPTR(PEAssembly) PTR_PEAssembly; class PEAssembly final { - // ------------------------------------------------------------ - // SOS support - // ------------------------------------------------------------ - VPTR_BASE_CONCRETE_VTABLE_CLASS(PEAssembly) - public: // ------------------------------------------------------------ @@ -98,7 +93,7 @@ class PEAssembly final STDMETHOD_(ULONG, Release)(); #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif #if CHECK_INVARIANTS @@ -381,7 +376,7 @@ class PEAssembly final #ifdef DACCESS_COMPILE // just to make the DAC and GCC happy. - virtual ~PEAssembly() {}; + ~PEAssembly() {}; PEAssembly() = default; #else PEAssembly( @@ -393,7 +388,7 @@ class PEAssembly final BINDER_SPACE::Assembly* pHostAssembly = NULL ); - virtual ~PEAssembly(); + ~PEAssembly(); #endif void OpenMDImport(); diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 1b72b89106df6..946943cc3cd61 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -456,34 +456,6 @@ void PEImage::GetMVID(GUID *pMvid) #endif // _DEBUG } -void PEImage::VerifyIsAssembly() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // buch of legacy stuff here wrt the error codes... - - if (!HasNTHeaders()) - ThrowFormat(COR_E_BADIMAGEFORMAT); - - if(!HasCorHeader()) - ThrowFormat(COR_E_ASSEMBLYEXPECTED); - - CHECK checkGoodFormat; - checkGoodFormat = CheckILFormat(); - if (!checkGoodFormat) - ThrowFormat(COR_E_BADIMAGEFORMAT); - - mdAssembly a; - if (FAILED(GetMDImport()->GetAssemblyFromScope(&a))) - ThrowFormat(COR_E_ASSEMBLYEXPECTED); -} - void DECLSPEC_NORETURN PEImage::ThrowFormat(HRESULT hrError) { CONTRACTL diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index 6451283d007ce..f353cebe978d1 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -182,8 +182,6 @@ class PEImage final CHECK CheckILFormat(); CHECK CheckUniqueInstance(); - void VerifyIsAssembly(); - void SetModuleFileNameHintForDAC(); #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 30708584c3f72..5e004f6ed0c1f 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -393,7 +393,7 @@ NativeImagePerfMap::NativeImagePerfMap(Assembly * pAssembly, BSTR pDestPath) // Get the native image signature (GUID). // Used to ensure that we match symbols to the correct NGEN image. WCHAR wszSignature[39]; - GetNativeImageSignature(pAssembly->GetManifestFile(), wszSignature, ARRAY_SIZE(wszSignature)); + GetNativeImageSignature(pAssembly->GetPEAssembly(), wszSignature, ARRAY_SIZE(wszSignature)); // Build the path to the perfmap file, which consists of .ni..map. // Example: /tmp/System.Private.CoreLib.ni.{GUID}.map diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index d8488e7e583b8..681301621f72f 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -520,7 +520,7 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) // Lookup in the entry point assembly for a R2R entrypoint (generics with large version bubble enabled) if (pCode == NULL && HasClassOrMethodInstantiation() && SystemDomain::System()->DefaultDomain()->GetRootAssembly() != NULL) { - pModule = SystemDomain::System()->DefaultDomain()->GetRootAssembly()->GetManifestModule(); + pModule = SystemDomain::System()->DefaultDomain()->GetRootAssembly()->GetModule(); _ASSERT(pModule != NULL); if (pModule->IsReadyToRun() && pModule->IsInSameVersionBubble(GetModule())) @@ -2262,10 +2262,6 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo // use the prestub. //========================================================================== -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) -static PCODE g_UMThunkPreStub; -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL - #ifndef DACCESS_COMPILE void ThePreStubManager::Init(void) @@ -2286,10 +2282,6 @@ void InitPreStubManager(void) { STANDARD_VM_CONTRACT; -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) - g_UMThunkPreStub = GenerateUMThunkPrestub()->GetEntryPoint(); -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL - ThePreStubManager::Init(); } @@ -2297,11 +2289,7 @@ PCODE TheUMThunkPreStub() { LIMITED_METHOD_CONTRACT; -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) - return g_UMThunkPreStub; -#else // TARGET_X86 && !FEATURE_STUBS_AS_IL return GetEEFuncEntryPoint(TheUMEntryPrestub); -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL } PCODE TheVarargNDirectStub(BOOL hasRetBuffArg) diff --git a/src/coreclr/vm/profilingenumerators.cpp b/src/coreclr/vm/profilingenumerators.cpp index 609b57cf4ee3a..7d537924df891 100644 --- a/src/coreclr/vm/profilingenumerators.cpp +++ b/src/coreclr/vm/profilingenumerators.cpp @@ -250,7 +250,7 @@ HRESULT IterateUnsharedModules(AppDomain * pAppDomain, // enumerable. // // Note: To determine what happens in a given load stage of a module or assembly, - // look at the switch statement in code:DomainFile::DoIncrementalLoad, and keep in + // look at the switch statement in code:DomainAssembly::DoIncrementalLoad, and keep in // mind that it takes cases on the *next* load stage; in other words, the actions // that appear in a case for a given load stage are actually executed as we attempt // to transition TO that load stage, and thus they actually execute while the module @@ -282,21 +282,14 @@ HRESULT IterateUnsharedModules(AppDomain * pAppDomain, // < Module NOT available from catch-up enumeration // < ModuleUnloadStarted issued // - // The IterateModules parameter below ensures only modules at level >= - // code:FILE_LOAD_LOADLIBRARY will be included in the iteration. - // // Details for module callbacks are the same as those for assemblies, so see // code:#ProfilerEnumAssemblies for info on how the timing works. - DomainModuleIterator domainModuleIterator = - pDomainAssembly->IterateModules(kModIterIncludeAvailableToProfilers); - while (domainModuleIterator.Next()) + + // Call user-supplied callback, and cancel iteration if requested + HRESULT hr = (callbackObj->*callbackMethod)(pDomainAssembly->GetModule()); + if (hr != S_OK) { - // Call user-supplied callback, and cancel iteration if requested - HRESULT hr = (callbackObj->*callbackMethod)(domainModuleIterator.GetModule()); - if (hr != S_OK) - { - return hr; - } + return hr; } } @@ -402,9 +395,9 @@ HRESULT ProfilerModuleEnum::Init() HRESULT hr = S_OK; - // When an assembly or module is loaded into an AppDomain, a separate DomainFile is - // created (one per pairing of the AppDomain with the module or assembly). This means - // that we'll create multiple DomainFiles for the same module if it is loaded + // When an assembly is loaded into an AppDomain, a DomainAssembly is + // created (one per pairing of the AppDomain with the assembly). This means + // that we'll create multiple DomainAssemblys for the same module if it is loaded // domain-neutral (i.e., "shared"). The profiling API callbacks shield the profiler // from this, and only report a given module the first time it's loaded. So a // profiler sees only one ModuleLoadFinished for a module loaded domain-neutral, even @@ -457,8 +450,8 @@ HRESULT IterateAppDomainContainingModule::AddAppDomainContainingModule(AppDomain } CONTRACTL_END; - DomainFile * pDomainFile = m_pModule->GetDomainFile(); - if ((pDomainFile != NULL) && (pDomainFile->IsAvailableToProfilers())) + DomainAssembly * pDomainAssembly = m_pModule->GetDomainAssembly(); + if ((pDomainAssembly != NULL) && (pDomainAssembly->IsAvailableToProfilers())) { if (m_index < m_cAppDomainIds) { diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 749fa73126b08..5162ac38a3bb4 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -1274,7 +1274,7 @@ bool AllocByClassHelper(Object * pBO, void * pv) _ASSERTE(pv != NULL); { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackAllocations()); + BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC()); // Pass along the call g_profControlBlock.AllocByClass( (ObjectID) pBO, @@ -5710,7 +5710,7 @@ HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID assemblyId, // Find the module the manifest lives in. if (pModuleId) { - *pModuleId = (ModuleID) pAssembly->GetManifestModule(); + *pModuleId = (ModuleID) pAssembly->GetModule(); // This is the case where the profiler has called GetAssemblyInfo // on an assembly that has been completely created yet. diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 96971b8180195..2d5d1cfc92b37 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -27,7 +27,6 @@ #include "comdatetime.h" #include "compatibilityswitch.h" #include "debugdebugger.h" -#include "assemblyname.hpp" #include "assemblynative.hpp" #include "comthreadpool.h" #include "comwaithandle.h" diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 495e10e4f4a36..e49ad881f5fe5 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -1579,19 +1579,17 @@ extern "C" void QCALLTYPE ReflectionInvocation_RunClassConstructor(QCall::TypeHa END_QCALL; } -// This method triggers the module constructor for a give module +// This method triggers the module constructor for a given module extern "C" void QCALLTYPE ReflectionInvocation_RunModuleConstructor(QCall::ModuleHandle pModule) { QCALL_CONTRACT; - DomainFile *pDomainFile = pModule->GetDomainFile(); - if (pDomainFile != NULL && pDomainFile->IsActive()) + DomainAssembly *pDomainAssembly = pModule->GetDomainAssembly(); + if (pDomainAssembly != NULL && pDomainAssembly->IsActive()) return; BEGIN_QCALL; - if(pDomainFile == NULL) - pDomainFile = pModule->GetDomainFile(); - pDomainFile->EnsureActive(); + pDomainAssembly->EnsureActive(); END_QCALL; } diff --git a/src/coreclr/vm/rejit.cpp b/src/coreclr/vm/rejit.cpp index aaf335390764c..80f05489ad3b2 100644 --- a/src/coreclr/vm/rejit.cpp +++ b/src/coreclr/vm/rejit.cpp @@ -811,35 +811,31 @@ HRESULT ReJitManager::UpdateNativeInlinerActiveILVersions( _ASSERTE(pDomainAssembly != NULL); _ASSERTE(pDomainAssembly->GetAssembly() != NULL); - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) + Module * pModule = pDomainAssembly->GetModule(); + if (pModule->HasReadyToRunInlineTrackingMap()) { - Module * pCurModule = domainModuleIterator.GetModule(); - if (pCurModule->HasReadyToRunInlineTrackingMap()) - { - inlinerIter.Reset(pCurModule, pInlinee); + inlinerIter.Reset(pModule, pInlinee); - MethodDesc *pInliner = NULL; - while (inlinerIter.Next()) + MethodDesc *pInliner = NULL; + while (inlinerIter.Next()) + { + pInliner = inlinerIter.GetMethodDesc(); { - pInliner = inlinerIter.GetMethodDesc(); + CodeVersionManager *pCodeVersionManager = pModule->GetCodeVersionManager(); + CodeVersionManager::LockHolder codeVersioningLockHolder; + ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(pInliner); + if (!ilVersion.HasDefaultIL()) { - CodeVersionManager *pCodeVersionManager = pCurModule->GetCodeVersionManager(); - CodeVersionManager::LockHolder codeVersioningLockHolder; - ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(pInliner); - if (!ilVersion.HasDefaultIL()) - { - // This method has already been ReJITted, no need to request another ReJIT at this point. - // The ReJITted method will be in the JIT inliner check below. - continue; - } + // This method has already been ReJITted, no need to request another ReJIT at this point. + // The ReJITted method will be in the JIT inliner check below. + continue; } + } - hr = UpdateActiveILVersion(pMgrToCodeActivationBatch, pInliner->GetModule(), pInliner->GetMemberDef(), fIsRevert, flags); - if (FAILED(hr)) - { - ReportReJITError(pInliner->GetModule(), pInliner->GetMemberDef(), NULL, hr); - } + hr = UpdateActiveILVersion(pMgrToCodeActivationBatch, pInliner->GetModule(), pInliner->GetMemberDef(), fIsRevert, flags); + if (FAILED(hr)) + { + ReportReJITError(pInliner->GetModule(), pInliner->GetMemberDef(), NULL, hr); } } } diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 41057e01620d3..362ea14986498 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -186,9 +186,9 @@ NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pM if (pModule == NULL) return NULL; - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); - OBJECTREF refModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + OBJECTREF refModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if(refModule != NULL) return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); @@ -354,7 +354,7 @@ FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObj if (refType == NULL) FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - Module *pModule = refType->GetType().GetAssembly()->GetManifestModule(); + Module *pModule = refType->GetType().GetAssembly()->GetModule(); DomainAssembly *pDomainAssembly = pModule->GetDomainAssembly(); FC_RETURN_ASSEMBLY_OBJECT(pDomainAssembly, refType); @@ -2667,20 +2667,20 @@ FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBas FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); - Assembly* currentAssembly = pAssembly->GetCurrentAssembly(); + Assembly* currentAssembly = pAssembly->GetAssembly(); - Module *pModule = currentAssembly->GetManifestModule(); - DomainFile * pDomainFile = pModule->GetDomainFile(); + Module *pModule = currentAssembly->GetModule(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); #ifdef _DEBUG OBJECTREF orModule; HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly); - orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + orModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if (orModule == NULL) orModule = pModule->GetExposedObject(); #else - OBJECTREF orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + OBJECTREF orModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if (orModule != NULL) return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule); @@ -2705,7 +2705,7 @@ FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) { DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); mdAssembly token = mdAssemblyNil; - IMDInternalImport *mdImport = pAssembly->GetCurrentAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = pAssembly->GetAssembly()->GetMDImport(); if (mdImport != 0) { @@ -2905,7 +2905,7 @@ FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObjec HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - DomainFile *pDomainModule = pModule->GetDomainFile(); + DomainAssembly *pDomainModule = pModule->GetDomainAssembly(); U1ARRAYREF dataArray = (U1ARRAYREF)sig; DWORD sigSize = dataArray->GetNumComponents(); diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index a197fbc87cabd..5a277914d8cee 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -4903,20 +4903,67 @@ void PromoteCarefully(promote_func fn, (*fn) (ppObj, sc, flags); } +class ByRefPointerOffsetsReporter +{ + promote_func* _fn; + ScanContext* _sc; + PTR_VOID _src; + + void Report(SIZE_T pointerOffset) + { + WRAPPER_NO_CONTRACT; + PTR_PTR_Object fieldRef = dac_cast(PTR_BYTE(_src) + pointerOffset); + (*_fn)(fieldRef, _sc, GC_CALL_INTERIOR); + } + +public: + ByRefPointerOffsetsReporter(promote_func* fn, ScanContext* sc, PTR_VOID pSrc) + : _fn{fn} + , _sc{sc} + , _src{pSrc} + { + WRAPPER_NO_CONTRACT; + } + + void Find(PTR_MethodTable pMT, SIZE_T baseOffset) + { + WRAPPER_NO_CONTRACT; + _ASSERTE(pMT != nullptr); + _ASSERTE(pMT->IsByRefLike()); + + if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + Report(baseOffset); + return; + } + + ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); + for (FieldDesc* pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) + { + if (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE) + { + PTR_MethodTable pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); + if (pFieldMT->IsByRefLike()) + { + Find(pFieldMT, baseOffset + pFD->GetOffset()); + } + } + else if (pFD->IsByRef()) + { + Report(baseOffset + pFD->GetOffset()); + } + } + } +}; + void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc) { WRAPPER_NO_CONTRACT; if (pMT->IsByRefLike()) { - FindByRefPointerOffsetsInByRefLikeObject( - pMT, - 0 /* baseOffset */, - [&](SIZE_T pointerOffset) - { - PTR_PTR_Object fieldRef = dac_cast(PTR_BYTE(pSrc) + pointerOffset); - (*fn)(fieldRef, sc, GC_CALL_INTERIOR); - }); + ByRefPointerOffsetsReporter reporter{fn, sc, pSrc}; + reporter.Find(pMT, 0 /* baseOffset */); } if (!pMT->ContainsPointers()) diff --git a/src/coreclr/vm/stubgen.cpp b/src/coreclr/vm/stubgen.cpp index f829212a8ef6e..2249756c3358a 100644 --- a/src/coreclr/vm/stubgen.cpp +++ b/src/coreclr/vm/stubgen.cpp @@ -2669,7 +2669,7 @@ void ILStubLinker::TransformArgForJIT(LocalDesc *pLoc) // JIT will handle structures if (pLoc->InternalToken.IsValueType()) { - _ASSERTE(pLoc->InternalToken.IsBlittable()); + _ASSERTE(pLoc->InternalToken.IsNativeValueType() || !pLoc->InternalToken.GetMethodTable()->ContainsPointers()); break; } FALLTHROUGH; diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index 200d36586ef52..20bdfcc6fcc6e 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1124,8 +1124,12 @@ extern "C" void *JIT_WriteBarrier_Loc; #ifdef TARGET_ARM64 extern "C" void (*JIT_WriteBarrier_Table)(); -extern "C" void *JIT_WriteBarrier_Loc = 0; -extern "C" void *JIT_WriteBarrier_Table_Loc = 0; + +extern "C" void *JIT_WriteBarrier_Loc; +void *JIT_WriteBarrier_Loc = 0; + +extern "C" void *JIT_WriteBarrier_Table_Loc; +void *JIT_WriteBarrier_Table_Loc = 0; #endif // TARGET_ARM64 #ifdef TARGET_ARM @@ -8526,8 +8530,8 @@ Thread::EnumMemoryRegionsWorker(CLRDataEnumMemoryFlags flags) DacEnumCodeForStackwalk(callEnd); // To stackwalk through funceval frames, we need to be sure to preserve the - // DebuggerModule's m_pRuntimeDomainFile. This is the only case that doesn't use the current - // vmDomainFile in code:DacDbiInterfaceImpl::EnumerateInternalFrames. The following + // DebuggerModule's m_pRuntimeDomainAssembly. This is the only case that doesn't use the current + // vmDomainAssembly in code:DacDbiInterfaceImpl::EnumerateInternalFrames. The following // code mimics that function. // Allow failure, since we want to continue attempting to walk the stack regardless of the outcome. EX_TRY diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 1bfccb85e10d6..f51f75445b399 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -132,7 +132,7 @@ class Frame; class ThreadBaseObject; class AppDomainStack; class LoadLevelLimiter; -class DomainFile; +class DomainAssembly; class DeadlockAwareLock; struct HelperMethodFrameCallerList; class ThreadLocalIBCInfo; diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp index 524a9e595bc24..dab28d4703f17 100644 --- a/src/coreclr/vm/typeparse.cpp +++ b/src/coreclr/vm/typeparse.cpp @@ -1273,7 +1273,7 @@ TypeName::GetTypeHaveAssemblyHelper( TypeHandle th = TypeHandle(); SArray & names = GetNames(); - Module * pManifestModule = pAssembly->GetManifestModule(); + Module * pManifestModule = pAssembly->GetModule(); Module * pLookOnlyInModule = NULL; ClassLoader * pClassLoader = pAssembly->GetLoader(); @@ -1427,7 +1427,7 @@ DomainAssembly * LoadDomainAssembly( { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEAssembly *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); + PEAssembly *pRequestingAssemblyManifestFile = pRequestingAssembly->GetPEAssembly(); spec.SetFallbackBinderForRequestingAssembly(pRequestingAssemblyManifestFile->GetFallbackBinder()); } diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 026ba5da743a5..12a4ed3225739 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -329,22 +329,6 @@ void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) while (BytesToWrite > 0) { DWORD dwChunkToWrite = (DWORD) min(BytesToWrite, maxWriteFileSize); - // No CharNextExA on CoreSystem, we just assume no multi-byte characters (this code path shouldn't be - // used in the production codepath for currently supported CoreSystem based products anyway). -#ifndef FEATURE_CORESYSTEM - if (dwChunkToWrite < BytesToWrite) { - break; - // must go by char to find biggest string that will fit, taking DBCS chars into account - //dwChunkToWrite = 0; - //const char *charNext = pszString; - //while (dwChunkToWrite < maxWriteFileSize-2 && charNext) { - // charNext = CharNextExA(0, pszString+dwChunkToWrite, 0); - // dwChunkToWrite = (DWORD)(charNext - pszString); - //} - //if (dwChunkToWrite == 0) - // break; - } -#endif // !FEATURE_CORESYSTEM // Try to write to handle. If this is not a CUI app, then this is probably // not going to work unless the dev took special pains to set their own console diff --git a/src/coreclr/vm/win32threadpool.cpp b/src/coreclr/vm/win32threadpool.cpp index 7ffbc34948a47..3e16f18a2d83b 100644 --- a/src/coreclr/vm/win32threadpool.cpp +++ b/src/coreclr/vm/win32threadpool.cpp @@ -494,11 +494,7 @@ void ThreadpoolMgr::InitPlatformVariables() _ASSERTE(hNtDll); if (!UsePortableThreadPool()) { -#ifdef FEATURE_CORESYSTEM hCoreSynch = CLRLoadLibrary(W("api-ms-win-core-synch-l1-1-0.dll")); -#else - hCoreSynch = CLRLoadLibrary(W("kernel32.dll")); -#endif _ASSERTE(hCoreSynch); } } @@ -3999,7 +3995,7 @@ DWORD WINAPI ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) * 2. GCCpuGroups=1, CLR creates GC threads for all processors in all CPU groups * thus, the threadpool thread would use a whole CPU group (if Thread_UseAllCpuGroups is not set). * ==> use g_SystemInfo.dwNumberOfProcessors. - * 3. !defined(TARGET_UNIX) but defined(FEATURE_CORESYSTEM), GetCurrentProcessCpuCount() + * 3. !defined(TARGET_UNIX), GetCurrentProcessCpuCount() * returns g_SystemInfo.dwNumberOfProcessors ==> use g_SystemInfo.dwNumberOfProcessors; * Other cases: * 1. Normal case: the mask is all or a subset of all processors in a CPU group; diff --git a/src/coreclr/vm/zapsig.cpp b/src/coreclr/vm/zapsig.cpp index dbdff7a98c8f5..b66c7b1057138 100644 --- a/src/coreclr/vm/zapsig.cpp +++ b/src/coreclr/vm/zapsig.cpp @@ -620,7 +620,7 @@ Module *ZapSig::DecodeModuleFromIndex(Module *fromModule, } } - return pAssembly->GetManifestModule(); + return pAssembly->GetModule(); } Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, @@ -686,7 +686,7 @@ Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, if (pAssembly == NULL) return NULL; - return pAssembly->GetManifestModule(); + return pAssembly->GetModule(); } diff --git a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs index f17bbbe6378cc..e1e81da93ff4d 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs @@ -94,7 +94,7 @@ void UpdateResources() try { // Open the source host file. - appHostSourceStream = new FileStream(appHostSourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + appHostSourceStream = new FileStream(appHostSourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); memoryMappedFile = MemoryMappedFile.CreateFromFile(appHostSourceStream, null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, true); memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.CopyOnWrite); diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props new file mode 100644 index 0000000000000..1f343d09fe105 --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + $(MSBuildThisFileDirectory)ILCompilerRIDs.props + + + + + diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props new file mode 100644 index 0000000000000..70e13f311b74a --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj new file mode 100644 index 0000000000000..65fd54d7bf3fb --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj @@ -0,0 +1,26 @@ + + + + true + true + Provides a native AOT compiler and runtime for .NET + + + + + + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/nativeaot-packages.proj b/src/installer/pkg/projects/nativeaot-packages.proj new file mode 100644 index 0000000000000..10ab1d60c56fa --- /dev/null +++ b/src/installer/pkg/projects/nativeaot-packages.proj @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/netcoreappRIDs.props b/src/installer/pkg/projects/netcoreappRIDs.props index 37fa250ded667..6282d87b88a92 100644 --- a/src/installer/pkg/projects/netcoreappRIDs.props +++ b/src/installer/pkg/projects/netcoreappRIDs.props @@ -26,6 +26,9 @@ arm + + armv6 + arm64 diff --git a/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs index b750a2de5e9d8..d3c442760423c 100644 --- a/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs +++ b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs @@ -143,7 +143,6 @@ static int GetDerLengthLength(int payloadLength) } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS /// /// Converts IeeeP1363 format to the specified signature format /// @@ -182,7 +181,6 @@ internal static byte[] ConvertSignatureToIeeeP1363( currentFormat.ToString()); } } -#endif public static int BitsToBytes(int bitLength) { @@ -214,7 +212,6 @@ private static void CopySignatureField(ReadOnlySpan signatureField, Span signatureField, Span source, Span destination hashAlgorithm == HashAlgorithmName.MD5 ? MD5.TryHashData(source, destination, out bytesWritten) : throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name); } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")] - private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmName) => - hashAlgorithmName == HashAlgorithmName.SHA256 ? SHA256.Create() : - hashAlgorithmName == HashAlgorithmName.SHA1 ? SHA1.Create() : - hashAlgorithmName == HashAlgorithmName.SHA512 ? SHA512.Create() : - hashAlgorithmName == HashAlgorithmName.SHA384 ? SHA384.Create() : - hashAlgorithmName == HashAlgorithmName.MD5 ? MD5.Create() : - throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName.Name); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs index 6cf3766ad8ed5..993d6d42ae751 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs @@ -16,7 +16,15 @@ internal static partial class AppleCrypto internal static partial SafeHmacHandle HmacCreate(PAL_HashAlgorithm algorithm, ref int cbDigest); [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacInit")] - internal static partial int HmacInit(SafeHmacHandle ctx, byte[] pbKey, int cbKey); + private static unsafe partial int HmacInit(SafeHmacHandle ctx, byte* pbKey, int cbKey); + + internal static unsafe int HmacInit(SafeHmacHandle ctx, ReadOnlySpan key) + { + fixed (byte* pKey = &MemoryMarshal.GetReference(key)) + { + return HmacInit(ctx, pKey, key.Length); + } + } internal static int HmacUpdate(SafeHmacHandle ctx, ReadOnlySpan data) => HmacUpdate(ctx, ref MemoryMarshal.GetReference(data), data.Length); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs index 567f97df901ce..4bbd79987510b 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Text; internal static partial class Interop { @@ -33,6 +32,19 @@ public bool IsIPv6 private uint _isIPv6; // Non-zero if this is an IPv6 address; zero for IPv4. internal uint ScopeId; // Scope ID (IPv6 only) + public override unsafe int GetHashCode() + { + HashCode h = default; + fixed (byte* ptr = Address) + { + h.AddBytes(new ReadOnlySpan(ptr, IsIPv6 ? IPv6AddressBytes : IPv4AddressBytes)); + } + return h.ToHashCode(); + } + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IPAddress other && Equals(other); + public bool Equals(IPAddress other) { int addressByteCount; diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs index 2b1b67784e87d..cbc05ad5a85b6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs @@ -25,5 +25,11 @@ internal enum UserFlags : uint [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflagsCanSetHiddenFlag")] [SuppressGCTransition] private static partial int LChflagsCanSetHiddenFlag(); + + internal static readonly bool SupportsHiddenFlag = (CanGetHiddenFlag() != 0); + + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CanGetHiddenFlag")] + [SuppressGCTransition] + private static partial int CanGetHiddenFlag(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs index 593c6f4e593f6..95e9ab89fc505 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs @@ -105,18 +105,28 @@ internal static unsafe SafeEvpPKeyHandle DecodePkcs8PrivateKey( } [GeneratedDllImport(Libraries.CryptoNative)] - private static partial int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey); + private static partial int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey, out int p8size); private static int GetPkcs8PrivateKeySize(IntPtr pkey) { - int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey); + const int Success = 1; + const int Error = -1; + const int MissingPrivateKey = -2; - if (ret < 0) + int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey, out int p8size); + + switch (ret) { - throw CreateOpenSslCryptographicException(); + case Success: + return p8size; + case Error: + throw CreateOpenSslCryptographicException(); + case MissingPrivateKey: + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + default: + Debug.Fail($"Unexpected return '{ret}' value from {nameof(CryptoNative_GetPkcs8PrivateKeySize)}."); + throw new CryptographicException(); } - - return ret; } [GeneratedDllImport(Libraries.CryptoNative)] diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index d403daac342ad..12b75443f7472 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -327,12 +327,9 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia Crypto.ErrClearError(); } - if (sslAuthenticationOptions.CertSelectionDelegate != null && sslAuthenticationOptions.CertificateContext == null) - { - // We don't have certificate but we have callback. We should wait for remote certificate and - // possible trusted issuer list. - Interop.Ssl.SslSetClientCertCallback(sslHandle, 1); - } + // Set client cert callback, this will interrupt the handshake with SecurityStatusPalErrorCode.CredentialsNeeded + // if server actually requests a certificate. + Ssl.SslSetClientCertCallback(sslHandle, 1); } if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index c01b829cd189d..379ab7586ed38 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Net.Security; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; @@ -47,7 +48,7 @@ internal static partial class Ssl internal static partial void SslSetAcceptState(SafeSslHandle ssl); [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAlpnProtos")] - internal static partial int SslSetAlpnProtos(SafeSslHandle ssl, IntPtr protos, int len); + internal static unsafe partial int SslSetAlpnProtos(SafeSslHandle ssl, byte* protos, int len); [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetVersion")] internal static partial IntPtr SslGetVersion(SafeSslHandle ssl); @@ -168,16 +169,7 @@ internal static class Capabilities internal static readonly bool Tls13Supported = Tls13SupportedImpl() != 0; } - internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, List protocols) - { - byte[] buffer = ConvertAlpnProtocolListToByteArray(protocols); - fixed (byte* b = buffer) - { - return SslSetAlpnProtos(ssl, (IntPtr)b, buffer.Length); - } - } - - internal static byte[] ConvertAlpnProtocolListToByteArray(List applicationProtocols) + internal static int GetAlpnProtocolListSerializedLength(List applicationProtocols) { int protocolSize = 0; foreach (SslApplicationProtocol protocol in applicationProtocols) @@ -190,16 +182,37 @@ internal static byte[] ConvertAlpnProtocolListToByteArray(List applicationProtocols, Span buffer) + { + Debug.Assert(GetAlpnProtocolListSerializedLength(applicationProtocols) == buffer.Length, + "GetAlpnProtocolListSerializedSize(applicationProtocols) == buffer.Length"); + + int offset = 0; foreach (SslApplicationProtocol protocol in applicationProtocols) { - buffer[offset++] = (byte)(protocol.Protocol.Length); - protocol.Protocol.Span.CopyTo(buffer.AsSpan(offset)); + buffer[offset++] = (byte)protocol.Protocol.Length; + protocol.Protocol.Span.CopyTo(buffer.Slice(offset)); offset += protocol.Protocol.Length; } + } + + internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, List applicationProtocols) + { + int length = GetAlpnProtocolListSerializedLength(applicationProtocols); + Span buffer = length <= 256 ? stackalloc byte[256].Slice(0, length) : new byte[length]; + SerializeAlpnProtocolList(applicationProtocols, buffer); + return SslSetAlpnProtos(ssl, buffer); + } - return buffer; + internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, Span serializedProtocols) + { + fixed (byte* pBuffer = &MemoryMarshal.GetReference(serializedProtocols)) + { + return SslSetAlpnProtos(ssl, pBuffer, serializedProtocols.Length); + } } [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslAddExtraChainCert")] diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs index 0a60ee7918ac3..b57a4b0f61927 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs @@ -19,7 +19,7 @@ internal enum CryptCreateHashFlags : int internal static partial bool CryptCreateHash( SafeProvHandle hProv, int Algid, - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, CryptCreateHashFlags dwFlags, out SafeHashHandle phHash); } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs index 7865c1180ff8f..3f05d5c223e7c 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs @@ -16,7 +16,7 @@ internal enum CryptDecryptFlags : int [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] public static partial bool CryptDecrypt( - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, SafeHashHandle hHash, bool Final, int dwFlags, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs index 2bc7d4ed8d8ba..51b77aef3d0ac 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs @@ -14,6 +14,6 @@ internal static partial bool CryptDeriveKey( int Algid, SafeHashHandle hBaseData, int dwFlags, - out SafeKeyHandle phKey); + out SafeCapiKeyHandle phKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs index fa883e5eef421..17e50c1e59d0f 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs @@ -10,7 +10,7 @@ internal static partial class Advapi32 { [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] public static partial bool CryptEncrypt( - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, SafeHashHandle hHash, bool Final, int dwFlags, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs index 9eb16f4019035..633997f99880e 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs @@ -10,8 +10,8 @@ internal static partial class Advapi32 { [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] public static partial bool CryptExportKey( - SafeKeyHandle hKey, - SafeKeyHandle hExpKey, + SafeCapiKeyHandle hKey, + SafeCapiKeyHandle hExpKey, int dwBlobType, int dwFlags, byte[]? pbData, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs index d19c090d84d60..cf6aaf36b1c15 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class Advapi32 { [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static partial bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeKeyHandle phKey); + internal static partial bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeCapiKeyHandle phKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs index 9737c2b066388..63f33ffa39227 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs @@ -19,7 +19,7 @@ internal enum CryptGetKeyParamFlags : int [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] public static partial bool CryptGetKeyParam( - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, CryptGetKeyParamFlags dwParam, byte[]? pbData, ref int pdwDataLen, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs index c5080a0078470..88b5d00e56389 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class Advapi32 { [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] - internal static partial bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeKeyHandle phUserKey); + internal static partial bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeCapiKeyHandle phUserKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs index f5e73879d99ca..3c8cb90d99f5c 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs @@ -13,8 +13,8 @@ internal static unsafe partial bool CryptImportKey( SafeProvHandle hProv, byte* pbData, int dwDataLen, - SafeKeyHandle hPubKey, + SafeCapiKeyHandle hPubKey, int dwFlags, - out SafeKeyHandle phKey); + out SafeCapiKeyHandle phKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs index 5fb1c83ff37e5..07d510705e2f7 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs @@ -9,9 +9,9 @@ internal static partial class Interop internal static partial class Advapi32 { [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] - public static partial bool CryptSetKeyParam(SafeKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags); + public static partial bool CryptSetKeyParam(SafeCapiKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags); [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] - public static partial bool CryptSetKeyParam(SafeKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags); + public static partial bool CryptSetKeyParam(SafeCapiKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs index 0d9f3a1703141..dd7a12c30b397 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs @@ -38,7 +38,7 @@ public static partial bool CryptVerifySignature( SafeHashHandle hHash, byte[] pbSignature, int dwSigLen, - SafeKeyHandle hPubKey, + SafeCapiKeyHandle hPubKey, string? szDescription, CryptSignAndVerifyHashFlags dwFlags); } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs index 5f12dd16db064..b8a0e5c944b20 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs @@ -16,13 +16,13 @@ namespace System.Security.Cryptography /// of the key handle and provider handle. This also applies to hash handles, which point to a /// CRYPT_HASH_CTX. Those structures are defined in COMCryptography.h /// - internal sealed class SafeKeyHandle : SafeHandleZeroOrMinusOneIsInvalid + internal sealed class SafeCapiKeyHandle : SafeHandleZeroOrMinusOneIsInvalid { private int _keySpec; private bool _fPublicOnly; private SafeProvHandle? _parent; - public SafeKeyHandle() : base(true) + public SafeCapiKeyHandle() : base(true) { SetHandle(IntPtr.Zero); _keySpec = 0; @@ -70,14 +70,14 @@ internal void SetParent(SafeProvHandle parent) _parent.DangerousAddRef(ref ignored); } - internal static SafeKeyHandle InvalidHandle + internal static SafeCapiKeyHandle InvalidHandle { - get { return SafeHandleCache.GetInvalidHandle(() => new SafeKeyHandle()); } + get { return SafeHandleCache.GetInvalidHandle(() => new SafeCapiKeyHandle()); } } protected override void Dispose(bool disposing) { - if (!SafeHandleCache.IsCachedInvalidHandle(this)) + if (!SafeHandleCache.IsCachedInvalidHandle(this)) { base.Dispose(disposing); } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs index 13d709643a184..913261e58915c 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs @@ -37,7 +37,7 @@ internal static unsafe SafeKeyHandle BCryptImportKey(SafeAlgorithmHandle hAlg, R } [StructLayout(LayoutKind.Sequential)] - private struct BCRYPT_KEY_DATA_BLOB_HEADER + internal struct BCRYPT_KEY_DATA_BLOB_HEADER { public uint dwMagic; public uint dwVersion; diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs index 406e0177f8ecf..5d9fbe7595ed0 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs @@ -11,8 +11,11 @@ internal static partial class Interop { internal static partial class NCrypt { + internal const string NCRYPT_CIPHER_KEY_BLOB = "CipherKeyBlob"; internal const string NCRYPT_PKCS8_PRIVATE_KEY_BLOB = "PKCS8_PRIVATEKEY"; + internal const int NCRYPT_CIPHER_KEY_BLOB_MAGIC = 0x52485043; //'CPHR' + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] internal static partial ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs index 7a1574155a7d9..e1a9bc4cce2ac 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs @@ -198,6 +198,7 @@ internal static partial class User32 public const int WAIT_TIMEOUT = 0x00000102; + public const int WM_DESTROY = 0x0002; public const int WM_CLOSE = 0x0010; public const int WM_QUERYENDSESSION = 0x0011; public const int WM_QUIT = 0x0012; diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs similarity index 77% rename from src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs rename to src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs index 6bcfa1488d684..5f9af4ffc2aa7 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class User32 { [GeneratedDllImport(Libraries.User32, CharSet = CharSet.Unicode, ExactSpelling = true)] - public static partial bool PeekMessageW(ref MSG msg, IntPtr hwnd, int msgMin, int msgMax, int remove); + public static partial int GetMessageW(ref MSG msg, IntPtr hwnd, int msgMin, int msgMax); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs new file mode 100644 index 0000000000000..511e68c0f883b --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs @@ -0,0 +1,14 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class User32 + { + [GeneratedDllImport(Libraries.User32, CharSet = CharSet.Unicode, ExactSpelling = true)] + public static partial void PostQuitMessage(int exitCode); + } +} diff --git a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs index 20f987f6cc053..54d6284d601c9 100644 --- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs +++ b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal; +using System.Security.Cryptography.X509Certificates; namespace Microsoft.Win32.SafeHandles { diff --git a/src/libraries/Common/src/System/Net/CookieComparer.cs b/src/libraries/Common/src/System/Net/CookieComparer.cs index 7d511ace0a9ac..529ec06a51a1f 100644 --- a/src/libraries/Common/src/System/Net/CookieComparer.cs +++ b/src/libraries/Common/src/System/Net/CookieComparer.cs @@ -5,23 +5,29 @@ namespace System.Net { internal static class CookieComparer { - internal static int Compare(Cookie left, Cookie right) + internal static bool Equals(Cookie left, Cookie right) { - int result; - - if ((result = string.Compare(left.Name, right.Name, StringComparison.OrdinalIgnoreCase)) != 0) + if (!string.Equals(left.Name, right.Name, StringComparison.OrdinalIgnoreCase)) { - return result; + return false; } - if ((result = string.Compare(left.Domain, right.Domain, StringComparison.OrdinalIgnoreCase)) != 0) + if (!EqualDomains(left.Domain, right.Domain)) { - return result; + return false; } // NB: Only the path is case sensitive as per spec. However, many Windows applications assume // case-insensitivity. - return string.Compare(left.Path, right.Path, StringComparison.Ordinal); + return string.Equals(left.Path, right.Path, StringComparison.Ordinal); + } + + internal static bool EqualDomains(ReadOnlySpan left, ReadOnlySpan right) + { + if (left.Length != 0 && left[0] == '.') left = left.Slice(1); + if (right.Length != 0 && right[0] == '.') right = right.Slice(1); + + return left.Equals(right, StringComparison.OrdinalIgnoreCase); } } } diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs index 6e109d6f8c547..e254c3a1ef0bc 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs @@ -48,7 +48,7 @@ public static bool TryGetStatusIndex(int status, out int index) // TODO: just use Dictionary directly to avoid interface dispatch. public static IReadOnlyDictionary MethodIndex => s_methodIndex; - public static ref HeaderField Get(int index) => ref s_staticTable[index]; + public static ref readonly HeaderField Get(int index) => ref s_staticTable[index]; private static readonly HeaderField[] s_staticTable = new HeaderField[] { diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs index 579e69a153f04..c2fcca169d21d 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs @@ -90,7 +90,8 @@ public static string ConstructCommandLine(int packetSize, int timeout, string ad // OSX: ping requires -W flag which accepts timeout in MILLISECONDS; ping6 doesn't support timeout if (OperatingSystem.IsFreeBSD()) { - if (ipv4) + // Syntax changed in FreeBSD 13.0 and options are not common for both address families + if (ipv4 || Environment.OSVersion.Version.Major > 12) { sb.Append(" -W "); } @@ -135,7 +136,8 @@ public static string ConstructCommandLine(int packetSize, int timeout, string ad if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsMacOS()) { // OSX and FreeBSD use -h to set hop limit for IPv6 and -m ttl for IPv4 - if (ipv4) + // Syntax changed in FreeBSD 13.0 and options are not common for both address families + if (ipv4 || (OperatingSystem.IsFreeBSD() && Environment.OSVersion.Version.Major > 12)) { sb.Append(" -m "); } diff --git a/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs b/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs index 8de1e2a0f4ce3..c755c16517c77 100644 --- a/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs +++ b/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs @@ -15,7 +15,9 @@ private static unsafe bool IsSupported(AddressFamily af) IntPtr socket = invalid; try { - return Interop.Sys.Socket(af, SocketType.Dgram, 0, &socket) != Interop.Error.EAFNOSUPPORT; + Interop.Error result = Interop.Sys.Socket(af, SocketType.Dgram, 0, &socket); + // we get EAFNOSUPPORT when family is not supported by Kernel, EPROTONOSUPPORT may come from policy enforcement like FreeBSD jail() + return result != Interop.Error.EAFNOSUPPORT && result != Interop.Error.EPROTONOSUPPORT; } finally { diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs index a16f66c40c89e..67e9d869a68db 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs @@ -34,6 +34,18 @@ internal Asn1Tag PeekTag() return Asn1Tag.Decode(_span, out _); } + internal ReadOnlySpan PeekContentBytes() + { + AsnDecoder.ReadEncodedValue( + _span, + _ruleSet, + out int contentOffset, + out int contentLength, + out _); + + return _span.Slice(contentOffset, contentLength); + } + internal ReadOnlySpan PeekEncodedValue() { AsnDecoder.ReadEncodedValue(_span, _ruleSet, out _, out _, out int consumed); diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs index b5e8c50c42b51..f9ec1cb44be8e 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs @@ -11,432 +11,425 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class DSAImplementation + public sealed partial class DSACng : DSA { -#endif - public sealed partial class DSACng : DSA - { - // For keysizes up to and including 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB. - // For keysizes exceeding 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB_V2. - private const int MaxV1KeySize = 1024; - - private const int Sha1HashOutputSize = 20; - private const int Sha256HashOutputSize = 32; - private const int Sha512HashOutputSize = 64; + // For keysizes up to and including 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB. + // For keysizes exceeding 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB_V2. + private const int MaxV1KeySize = 1024; - public override void ImportParameters(DSAParameters parameters) - { - if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); + private const int Sha1HashOutputSize = 20; + private const int Sha256HashOutputSize = 32; + private const int Sha512HashOutputSize = 64; - // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check - // is just to maintain parity with DSACryptoServiceProvider, which also performs this check. - if (parameters.J != null && parameters.J.Length >= parameters.P.Length) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); + public override void ImportParameters(DSAParameters parameters) + { + if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); - bool hasPrivateKey = parameters.X != null; + // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check + // is just to maintain parity with DSACryptoServiceProvider, which also performs this check. + if (parameters.J != null && parameters.J.Length >= parameters.P.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); - int keySizeInBytes = parameters.P.Length; - int keySizeInBits = keySizeInBytes * 8; + bool hasPrivateKey = parameters.X != null; - if (parameters.G.Length != keySizeInBytes || parameters.Y.Length != keySizeInBytes) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); + int keySizeInBytes = parameters.P.Length; + int keySizeInBits = keySizeInBytes * 8; - if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); + if (parameters.G.Length != keySizeInBytes || parameters.Y.Length != keySizeInBytes) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); - byte[] blob; - if (keySizeInBits <= MaxV1KeySize) - { - GenerateV1DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey); - } - else - { - GenerateV2DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey); - } + if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); - ImportKeyBlob(blob, hasPrivateKey); + byte[] blob; + if (keySizeInBits <= MaxV1KeySize) + { + GenerateV1DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey); } - - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) + else { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + GenerateV2DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey); } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) + ImportKeyBlob(blob, hasPrivateKey); + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters); + } + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) + { + if (pbeParameters == null) { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + throw new ArgumentNullException(nameof(pbeParameters)); } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters) - { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters); + if (CngPkcs8.IsPlatformScheme(pbeParameters)) + { + return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters) - { - if (pbeParameters == null) - { - throw new ArgumentNullException(nameof(pbeParameters)); - } + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters); + } - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + ReadOnlySpan.Empty, + passwordBytes); + + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters, + destination, + out bytesWritten); + } - if (CngPkcs8.IsPlatformScheme(pbeParameters)) - { - return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); - } + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - password, - pbeParameters); - } + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) + if (CngPkcs8.IsPlatformScheme(pbeParameters)) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); - - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - ReadOnlySpan.Empty, - passwordBytes); - - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters, + return TryExportEncryptedPkcs8( + password, + pbeParameters.IterationCount, destination, out bytesWritten); } - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters, + destination, + out bytesWritten); + } + + private static unsafe void GenerateV1DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivate) + { + // We need to build a key blob structured as follows: + // + // BCRYPT_DSA_KEY_BLOB header + // byte[cbKey] P + // byte[cbKey] G + // byte[cbKey] Y + // -- Private only -- + // byte[Sha1HashOutputSize] X + + int blobSize = + sizeof(BCRYPT_DSA_KEY_BLOB) + + cbKey + + cbKey + + cbKey; + + if (includePrivate) + { + blobSize += Sha1HashOutputSize; + } + + blob = new byte[blobSize]; + fixed (byte* pDsaBlob = &blob[0]) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); + // Build the header + BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob; - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + pBcryptBlob->Magic = includePrivate ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC; + pBcryptBlob->cbKey = cbKey; - if (CngPkcs8.IsPlatformScheme(pbeParameters)) + int offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey + + if (parameters.Seed != null) { - return TryExportEncryptedPkcs8( - password, - pbeParameters.IterationCount, - destination, - out bytesWritten); + // The Seed length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message. + if (parameters.Seed.Length != Sha1HashOutputSize) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_SeedRestriction_ShortKey); + + Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter); + Interop.BCrypt.Emit(blob, ref offset, parameters.Seed); + } + else + { + // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject + // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng. + Interop.BCrypt.EmitByte(blob, ref offset, 0xff, Sha1HashOutputSize + sizeof(int)); } - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, - password, - pbeParameters, - destination, - out bytesWritten); - } + // The Q length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message. + if (parameters.Q!.Length != Sha1HashOutputSize) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_QRestriction_ShortKey); - private static unsafe void GenerateV1DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivate) - { - // We need to build a key blob structured as follows: - // - // BCRYPT_DSA_KEY_BLOB header - // byte[cbKey] P - // byte[cbKey] G - // byte[cbKey] Y - // -- Private only -- - // byte[Sha1HashOutputSize] X - - int blobSize = - sizeof(BCRYPT_DSA_KEY_BLOB) + - cbKey + - cbKey + - cbKey; + Interop.BCrypt.Emit(blob, ref offset, parameters.Q); + + Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}"); + Interop.BCrypt.Emit(blob, ref offset, parameters.P!); + Interop.BCrypt.Emit(blob, ref offset, parameters.G!); + Interop.BCrypt.Emit(blob, ref offset, parameters.Y!); if (includePrivate) { - blobSize += Sha1HashOutputSize; + Interop.BCrypt.Emit(blob, ref offset, parameters.X!); } - blob = new byte[blobSize]; - fixed (byte* pDsaBlob = &blob[0]) - { - // Build the header - BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob; - - pBcryptBlob->Magic = includePrivate ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC; - pBcryptBlob->cbKey = cbKey; - - int offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey + Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}"); + } + } - if (parameters.Seed != null) - { - // The Seed length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message. - if (parameters.Seed.Length != Sha1HashOutputSize) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_SeedRestriction_ShortKey); + private static unsafe void GenerateV2DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivateParameters) + { + // We need to build a key blob structured as follows: + // BCRYPT_DSA_KEY_BLOB_V2 header + // byte[cbSeedLength] Seed + // byte[cbGroupSize] Q + // byte[cbKey] P + // byte[cbKey] G + // byte[cbKey] Y + // -- Private only -- + // byte[cbGroupSize] X + + int blobSize = + sizeof(BCRYPT_DSA_KEY_BLOB_V2) + + (parameters.Seed == null ? parameters.Q!.Length : parameters.Seed.Length) + // Use Q size if Seed is not present + parameters.Q!.Length + + parameters.P!.Length + + parameters.G!.Length + + parameters.Y!.Length + + (includePrivateParameters ? parameters.X!.Length : 0); + + blob = new byte[blobSize]; + fixed (byte* pDsaBlob = &blob[0]) + { + // Build the header + BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob; - Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter); - Interop.BCrypt.Emit(blob, ref offset, parameters.Seed); - } - else - { - // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject - // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng. - Interop.BCrypt.EmitByte(blob, ref offset, 0xff, Sha1HashOutputSize + sizeof(int)); - } + pBcryptBlob->Magic = includePrivateParameters ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2 : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2; + pBcryptBlob->cbKey = cbKey; - // The Q length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message. - if (parameters.Q!.Length != Sha1HashOutputSize) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_QRestriction_ShortKey); + // For some reason, Windows bakes the hash algorithm into the key itself. Furthermore, it demands that the Q length match the + // length of the named hash algorithm's output - otherwise, the Import fails. So we have to give it the hash algorithm that matches + // the Q length - and if there is no matching hash algorithm, we throw up our hands and throw a PlatformNotSupported. + // + // Note that this has no bearing on the hash algorithm you pass to SignData(). The class library (not Windows) hashes that according + // to the hash algorithm passed to SignData() and presents the hash result to NCryptSignHash(), truncating the hash to the Q length + // if necessary (and as demanded by the NIST spec.) Windows will be no wiser and we'll get the result we want. + pBcryptBlob->hashAlgorithm = parameters.Q.Length switch + { + Sha1HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA1, + Sha256HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA256, + Sha512HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA512, + _ => throw new PlatformNotSupportedException(SR.Cryptography_InvalidDsaParameters_QRestriction_LargeKey), + }; + pBcryptBlob->standardVersion = DSAFIPSVERSION_ENUM.DSA_FIPS186_3; - Interop.BCrypt.Emit(blob, ref offset, parameters.Q); + int offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4] - Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}"); + if (parameters.Seed != null) + { + Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter); + Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); + pBcryptBlob->cbSeedLength = parameters.Seed.Length; + pBcryptBlob->cbGroupSize = parameters.Q.Length; + Interop.BCrypt.Emit(blob, ref offset, parameters.Seed); + } + else + { + // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject + // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng. + Interop.BCrypt.EmitByte(blob, ref offset, 0xff, sizeof(int)); + Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); + int defaultSeedLength = parameters.Q.Length; + pBcryptBlob->cbSeedLength = defaultSeedLength; + pBcryptBlob->cbGroupSize = parameters.Q.Length; + Interop.BCrypt.EmitByte(blob, ref offset, 0xff, defaultSeedLength); + } - Interop.BCrypt.Emit(blob, ref offset, parameters.P!); - Interop.BCrypt.Emit(blob, ref offset, parameters.G!); - Interop.BCrypt.Emit(blob, ref offset, parameters.Y!); - if (includePrivate) - { - Interop.BCrypt.Emit(blob, ref offset, parameters.X!); - } + Interop.BCrypt.Emit(blob, ref offset, parameters.Q); + Interop.BCrypt.Emit(blob, ref offset, parameters.P); + Interop.BCrypt.Emit(blob, ref offset, parameters.G); + Interop.BCrypt.Emit(blob, ref offset, parameters.Y); - Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}"); + if (includePrivateParameters) + { + Interop.BCrypt.Emit(blob, ref offset, parameters.X!); } + + Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}"); } + } - private static unsafe void GenerateV2DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivateParameters) - { - // We need to build a key blob structured as follows: - // BCRYPT_DSA_KEY_BLOB_V2 header - // byte[cbSeedLength] Seed - // byte[cbGroupSize] Q - // byte[cbKey] P - // byte[cbKey] G - // byte[cbKey] Y - // -- Private only -- - // byte[cbGroupSize] X - - int blobSize = - sizeof(BCRYPT_DSA_KEY_BLOB_V2) + - (parameters.Seed == null ? parameters.Q!.Length : parameters.Seed.Length) + // Use Q size if Seed is not present - parameters.Q!.Length + - parameters.P!.Length + - parameters.G!.Length + - parameters.Y!.Length + - (includePrivateParameters ? parameters.X!.Length : 0); - - blob = new byte[blobSize]; - fixed (byte* pDsaBlob = &blob[0]) - { - // Build the header - BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob; - - pBcryptBlob->Magic = includePrivateParameters ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2 : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2; - pBcryptBlob->cbKey = cbKey; - - // For some reason, Windows bakes the hash algorithm into the key itself. Furthermore, it demands that the Q length match the - // length of the named hash algorithm's output - otherwise, the Import fails. So we have to give it the hash algorithm that matches - // the Q length - and if there is no matching hash algorithm, we throw up our hands and throw a PlatformNotSupported. - // - // Note that this has no bearing on the hash algorithm you pass to SignData(). The class library (not Windows) hashes that according - // to the hash algorithm passed to SignData() and presents the hash result to NCryptSignHash(), truncating the hash to the Q length - // if necessary (and as demanded by the NIST spec.) Windows will be no wiser and we'll get the result we want. - pBcryptBlob->hashAlgorithm = parameters.Q.Length switch - { - Sha1HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA1, - Sha256HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA256, - Sha512HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA512, - _ => throw new PlatformNotSupportedException(SR.Cryptography_InvalidDsaParameters_QRestriction_LargeKey), - }; - pBcryptBlob->standardVersion = DSAFIPSVERSION_ENUM.DSA_FIPS186_3; + public override DSAParameters ExportParameters(bool includePrivateParameters) + { + byte[] dsaBlob = ExportKeyBlob(includePrivateParameters); - int offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4] + KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(dsaBlob, 0); - if (parameters.Seed != null) - { - Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter); - Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); - pBcryptBlob->cbSeedLength = parameters.Seed.Length; - pBcryptBlob->cbGroupSize = parameters.Q.Length; - Interop.BCrypt.Emit(blob, ref offset, parameters.Seed); - } - else - { - // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject - // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng. - Interop.BCrypt.EmitByte(blob, ref offset, 0xff, sizeof(int)); - Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); - int defaultSeedLength = parameters.Q.Length; - pBcryptBlob->cbSeedLength = defaultSeedLength; - pBcryptBlob->cbGroupSize = parameters.Q.Length; - Interop.BCrypt.EmitByte(blob, ref offset, 0xff, defaultSeedLength); - } + // Check the magic value in the key blob header. If the blob does not have the required magic, + // then throw a CryptographicException. + CheckMagicValueOfKey(magic, includePrivateParameters); - Interop.BCrypt.Emit(blob, ref offset, parameters.Q); - Interop.BCrypt.Emit(blob, ref offset, parameters.P); - Interop.BCrypt.Emit(blob, ref offset, parameters.G); - Interop.BCrypt.Emit(blob, ref offset, parameters.Y); + unsafe + { + DSAParameters dsaParams = default; - if (includePrivateParameters) + fixed (byte* pDsaBlob = dsaBlob) + { + int offset; + if (magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC) { - Interop.BCrypt.Emit(blob, ref offset, parameters.X!); + if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB)) + throw ErrorCode.E_FAIL.ToCryptographicException(); + + BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob; + // We now have a buffer laid out as follows: + // BCRYPT_DSA_KEY_BLOB header + // byte[cbKey] P + // byte[cbKey] G + // byte[cbKey] Y + // -- Private only -- + // byte[Sha1HashOutputSize] X + + offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey + + // Read out a (V1) BCRYPT_DSA_KEY_BLOB structure. + dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); + dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); + dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); + + Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}"); + dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + if (includePrivateParameters) + { + dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); + } } + else + { + Debug.Assert(magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2); - Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}"); - } - } + if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2)) + throw ErrorCode.E_FAIL.ToCryptographicException(); - public override DSAParameters ExportParameters(bool includePrivateParameters) - { - byte[] dsaBlob = ExportKeyBlob(includePrivateParameters); + BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob; + // We now have a buffer laid out as follows: + // BCRYPT_DSA_KEY_BLOB_V2 header + // byte[cbSeedLength] Seed + // byte[cbGroupSize] Q + // byte[cbKey] P + // byte[cbKey] G + // byte[cbKey] Y + // -- Private only -- + // byte[cbGroupSize] X - KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(dsaBlob, 0); + offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4] - // Check the magic value in the key blob header. If the blob does not have the required magic, - // then throw a CryptographicException. - CheckMagicValueOfKey(magic, includePrivateParameters); + // Read out a BCRYPT_DSA_KEY_BLOB_V2 structure. + dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); - unsafe - { - DSAParameters dsaParams = default; + Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); - fixed (byte* pDsaBlob = dsaBlob) - { - int offset; - if (magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC) - { - if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB)) - throw ErrorCode.E_FAIL.ToCryptographicException(); - - BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob; - // We now have a buffer laid out as follows: - // BCRYPT_DSA_KEY_BLOB header - // byte[cbKey] P - // byte[cbKey] G - // byte[cbKey] Y - // -- Private only -- - // byte[Sha1HashOutputSize] X - - offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey - - // Read out a (V1) BCRYPT_DSA_KEY_BLOB structure. - dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); - dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); - dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); - - Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}"); - dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - if (includePrivateParameters) - { - dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); - } - } - else + dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbSeedLength); + dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); + dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); + if (includePrivateParameters) { - Debug.Assert(magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2); - - if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2)) - throw ErrorCode.E_FAIL.ToCryptographicException(); - - BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob; - // We now have a buffer laid out as follows: - // BCRYPT_DSA_KEY_BLOB_V2 header - // byte[cbSeedLength] Seed - // byte[cbGroupSize] Q - // byte[cbKey] P - // byte[cbKey] G - // byte[cbKey] Y - // -- Private only -- - // byte[cbGroupSize] X - - offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4] - - // Read out a BCRYPT_DSA_KEY_BLOB_V2 structure. - dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); - - Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); - - dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbSeedLength); - dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); - dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); - if (includePrivateParameters) - { - dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); - } + dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); } + } - // If no counter/seed information is present, normalize Counter and Seed to 0/null to maintain parity with the CAPI version of DSA. - if (dsaParams.Counter == -1) - { - dsaParams.Counter = 0; - dsaParams.Seed = null; - } + // If no counter/seed information is present, normalize Counter and Seed to 0/null to maintain parity with the CAPI version of DSA. + if (dsaParams.Counter == -1) + { + dsaParams.Counter = 0; + dsaParams.Seed = null; + } - Debug.Assert(offset == dsaBlob.Length, $"Expected offset = dsaBlob.Length, got {offset} != {dsaBlob.Length}"); + Debug.Assert(offset == dsaBlob.Length, $"Expected offset = dsaBlob.Length, got {offset} != {dsaBlob.Length}"); - return dsaParams; - } + return dsaParams; } } + } - /// - /// This function checks the magic value in the key blob header - /// - /// The expected magic number. - /// Private blob if true else public key blob - private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters) + /// + /// This function checks the magic value in the key blob header + /// + /// The expected magic number. + /// Private blob if true else public key blob + private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters) + { + if (includePrivateParameters) { - if (includePrivateParameters) - { - if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) - throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); - } - else - { - if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2) - throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); - } + if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) + throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); + } + else + { + if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2) + throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } - } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs index 7971a35a2adf9..9393dc735880f 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs @@ -9,199 +9,174 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class DSAImplementation + public sealed partial class DSACng : DSA { -#endif - public sealed partial class DSACng : DSA - { - // As of FIPS 186-4 the maximum Q size is 32 bytes. - // - // See also: cbGroupSize at - // https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_dsa_key_blob_v2 - private const int WindowsMaxQSize = 32; + // As of FIPS 186-4 the maximum Q size is 32 bytes. + // + // See also: cbGroupSize at + // https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_dsa_key_blob_v2 + private const int WindowsMaxQSize = 32; - public override byte[] CreateSignature(byte[] rgbHash) + public override byte[] CreateSignature(byte[] rgbHash) + { + if (rgbHash == null) { - if (rgbHash == null) - { - throw new ArgumentNullException(nameof(rgbHash)); - } - - Span stackBuf = stackalloc byte[WindowsMaxQSize]; - ReadOnlySpan source = AdjustHashSizeIfNecessary(rgbHash, stackBuf); - - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - unsafe - { - return CngCommon.SignHash(keyHandle, source, AsymmetricPaddingMode.None, null, source.Length * 2); - } - } + throw new ArgumentNullException(nameof(rgbHash)); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - protected override unsafe bool TryCreateSignatureCore( - ReadOnlySpan hash, - Span destination, - DSASignatureFormat signatureFormat, - out int bytesWritten) -#else - public override unsafe bool TryCreateSignature(ReadOnlySpan hash, Span destination, out int bytesWritten) -#endif - { - Span stackBuf = stackalloc byte[WindowsMaxQSize]; - ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf); + Span stackBuf = stackalloc byte[WindowsMaxQSize]; + ReadOnlySpan source = AdjustHashSizeIfNecessary(rgbHash, stackBuf); - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + { + unsafe { - if (!CngCommon.TrySignHash(keyHandle, source, destination, AsymmetricPaddingMode.None, null, out bytesWritten)) - { - bytesWritten = 0; - return false; - } + return CngCommon.SignHash(keyHandle, source, AsymmetricPaddingMode.None, null, source.Length * 2); } + } + } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) - { - return true; - } + protected override unsafe bool TryCreateSignatureCore( + ReadOnlySpan hash, + Span destination, + DSASignatureFormat signatureFormat, + out int bytesWritten) + { + Span stackBuf = stackalloc byte[WindowsMaxQSize]; + ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf); - if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) + using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + { + if (!CngCommon.TrySignHash(keyHandle, source, destination, AsymmetricPaddingMode.None, null, out bytesWritten)) { - Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); - throw new CryptographicException( - SR.Cryptography_UnknownSignatureFormat, - signatureFormat.ToString()); + bytesWritten = 0; + return false; } + } - return AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer( - destination.Slice(0, bytesWritten), - destination, - out bytesWritten); -#else + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) + { return true; -#endif } - public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) { - if (rgbHash == null) - { - throw new ArgumentNullException(nameof(rgbHash)); - } - if (rgbSignature == null) - { - throw new ArgumentNullException(nameof(rgbSignature)); - } + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } + + return AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer( + destination.Slice(0, bytesWritten), + destination, + out bytesWritten); + } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - return VerifySignatureCore(rgbHash, rgbSignature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); -#else - return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature); -#endif + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + { + if (rgbHash == null) + { + throw new ArgumentNullException(nameof(rgbHash)); + } + if (rgbSignature == null) + { + throw new ArgumentNullException(nameof(rgbSignature)); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - protected override bool VerifySignatureCore( - ReadOnlySpan hash, - ReadOnlySpan signature, - DSASignatureFormat signatureFormat) + return VerifySignatureCore(rgbHash, rgbSignature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); + } + + protected override bool VerifySignatureCore( + ReadOnlySpan hash, + ReadOnlySpan signature, + DSASignatureFormat signatureFormat) + { + Span stackBuf = stackalloc byte[WindowsMaxQSize]; + ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf); + + if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) { - Span stackBuf = stackalloc byte[WindowsMaxQSize]; - ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf); + // source.Length is the field size, in bytes, so just convert to bits. + int fieldSizeBits = source.Length * 8; + signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature, fieldSizeBits); + } + else if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation) + { + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } - if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) - { - // source.Length is the field size, in bytes, so just convert to bits. - int fieldSizeBits = source.Length * 8; - signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature, fieldSizeBits); - } - else if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation) - { - Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); - throw new CryptographicException( - SR.Cryptography_UnknownSignatureFormat, - signatureFormat.ToString()); - } -#else - public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) + using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { - Span stackBuf = stackalloc byte[WindowsMaxQSize]; - ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf); -#endif - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + unsafe { - unsafe - { - return CngCommon.VerifyHash(keyHandle, source, signature, AsymmetricPaddingMode.None, null); - } + return CngCommon.VerifyHash(keyHandle, source, signature, AsymmetricPaddingMode.None, null); } } + } - private ReadOnlySpan AdjustHashSizeIfNecessary(ReadOnlySpan hash, Span stackBuf) - { - Debug.Assert(stackBuf.Length == WindowsMaxQSize); + private ReadOnlySpan AdjustHashSizeIfNecessary(ReadOnlySpan hash, Span stackBuf) + { + Debug.Assert(stackBuf.Length == WindowsMaxQSize); - // Windows CNG requires that the hash output and q match sizes, but we can better - // interoperate with other FIPS 186-3 implementations if we perform truncation - // here, before sending it to CNG. Since this is a scenario presented in the - // CAVP reference test suite, we can confirm our implementation. - // - // If, on the other hand, Q is too big, we need to left-pad the hash with zeroes - // (since it gets treated as a big-endian number). Since this is also a scenario - // presented in the CAVP reference test suite, we can confirm our implementation. + // Windows CNG requires that the hash output and q match sizes, but we can better + // interoperate with other FIPS 186-3 implementations if we perform truncation + // here, before sending it to CNG. Since this is a scenario presented in the + // CAVP reference test suite, we can confirm our implementation. + // + // If, on the other hand, Q is too big, we need to left-pad the hash with zeroes + // (since it gets treated as a big-endian number). Since this is also a scenario + // presented in the CAVP reference test suite, we can confirm our implementation. - int qLength = ComputeQLength(); - Debug.Assert(qLength <= WindowsMaxQSize); + int qLength = ComputeQLength(); + Debug.Assert(qLength <= WindowsMaxQSize); - if (qLength == hash.Length) - { - return hash; - } + if (qLength == hash.Length) + { + return hash; + } - if (qLength < hash.Length) - { - return hash.Slice(0, qLength); - } + if (qLength < hash.Length) + { + return hash.Slice(0, qLength); + } + + int zeroByteCount = qLength - hash.Length; + stackBuf.Slice(0, zeroByteCount).Clear(); + hash.CopyTo(stackBuf.Slice(zeroByteCount)); + return stackBuf.Slice(0, qLength); + } - int zeroByteCount = qLength - hash.Length; - stackBuf.Slice(0, zeroByteCount).Clear(); - hash.CopyTo(stackBuf.Slice(zeroByteCount)); - return stackBuf.Slice(0, qLength); + private int ComputeQLength() + { + byte[] blob; + using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + { + blob = this.ExportKeyBlob(false); } - private int ComputeQLength() + unsafe { - byte[] blob; - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) + if (blob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2)) { - blob = this.ExportKeyBlob(false); + return Sha1HashOutputSize; } - unsafe + fixed (byte* pBlobBytes = blob) { - if (blob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2)) + BCRYPT_DSA_KEY_BLOB_V2* pBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pBlobBytes; + if (pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 && pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) { + // This is a V1 BCRYPT_DSA_KEY_BLOB, which hardcodes the Q length to 20 bytes. return Sha1HashOutputSize; } - fixed (byte* pBlobBytes = blob) - { - BCRYPT_DSA_KEY_BLOB_V2* pBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pBlobBytes; - if (pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 && pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) - { - // This is a V1 BCRYPT_DSA_KEY_BLOB, which hardcodes the Q length to 20 bytes. - return Sha1HashOutputSize; - } - - return pBlob->cbGroupSize; - } + return pBlob->cbGroupSize; } } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs index a89f2706a23d4..d9f8ed5cafa68 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs @@ -5,84 +5,80 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; +using System.Runtime.Versioning; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class DSAImplementation + public sealed partial class DSACng : DSA { -#endif - public sealed partial class DSACng : DSA + /// + /// Create a DSACng algorithm with a random 2048 bit key pair. + /// + [SupportedOSPlatform("windows")] + public DSACng() + : this(keySize: s_defaultKeySize) { - /// - /// Create a DSACng algorithm with a random 2048 bit key pair. - /// - public DSACng() - : this(keySize: s_defaultKeySize) - { - } + } - /// - /// Creates a new DSACng object that will use a randomly generated key of the specified size. - /// Valid key sizes range from 512 to 3072 bits, in increments of 64. It's suggested that a - /// minimum size of 2048 bits be used for all keys. - /// - /// Size of the key to generate, in bits. - /// if is not valid - public DSACng(int keySize) - { - LegalKeySizesValue = s_legalKeySizes; - KeySize = keySize; - } + /// + /// Creates a new DSACng object that will use a randomly generated key of the specified size. + /// Valid key sizes range from 512 to 3072 bits, in increments of 64. It's suggested that a + /// minimum size of 2048 bits be used for all keys. + /// + /// Size of the key to generate, in bits. + /// if is not valid + [SupportedOSPlatform("windows")] + public DSACng(int keySize) + { + LegalKeySizesValue = s_legalKeySizes; + KeySize = keySize; + } - public override KeySizes[] LegalKeySizes + public override KeySizes[] LegalKeySizes + { + get { - get - { - return base.LegalKeySizes; - } + return base.LegalKeySizes; } + } - public override string SignatureAlgorithm => "DSA"; - public override string? KeyExchangeAlgorithm => null; - - // Need to override since base methods throw a "override me" exception: makes SignData/VerifyData function. - protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => - CngCommon.HashData(data, offset, count, hashAlgorithm); + public override string SignatureAlgorithm => "DSA"; + public override string? KeyExchangeAlgorithm => null; - protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => - CngCommon.HashData(data, hashAlgorithm); + // Need to override since base methods throw a "override me" exception: makes SignData/VerifyData function. + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + CngCommon.HashData(data, offset, count, hashAlgorithm); - protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => - CngCommon.TryHashData(source, destination, hashAlgorithm, out bytesWritten); + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + CngCommon.HashData(data, hashAlgorithm); - private void ForceSetKeySize(int newKeySize) - { - // Our LegalKeySizes value stores the values that we encoded as being the correct - // legal key size limitations for this algorithm, as documented on MSDN. - // - // But on a new OS version we might not question if our limit is accurate, or MSDN - // could have been inaccurate to start with. - // - // Since the key is already loaded, we know that Windows thought it to be valid; - // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance - // check. - // - KeySizeValue = newKeySize; - } + protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => + CngCommon.TryHashData(source, destination, hashAlgorithm, out bytesWritten); - private static bool Supports2048KeySize() - { - Debug.Assert(OperatingSystem.IsWindows()); - Version version = Environment.OSVersion.Version; - bool isAtLeastWindows8 = version.Major > 6 || (version.Major == 6 && version.Minor >= 2); - return isAtLeastWindows8; - } + private void ForceSetKeySize(int newKeySize) + { + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been inaccurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + KeySizeValue = newKeySize; + } - private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) }; - private static readonly int s_defaultKeySize = Supports2048KeySize() ? 2048 : 1024; + private static bool Supports2048KeySize() + { + Debug.Assert(OperatingSystem.IsWindows()); + Version version = Environment.OSVersion.Version; + bool isAtLeastWindows8 = version.Major > 6 || (version.Major == 6 && version.Minor >= 2); + return isAtLeastWindows8; } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + + private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) }; + private static readonly int s_defaultKeySize = Supports2048KeySize() ? 2048 : 1024; } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs index d51e1a3a8e5d3..8a8445fe17f5b 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs @@ -3,425 +3,400 @@ using System.Diagnostics; using System.IO; +using System.Runtime.Versioning; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class DSA : AsymmetricAlgorithm + public sealed partial class DSAOpenSsl : DSA { - private static DSA CreateCore() + // The biggest key allowed by FIPS 186-4 has N=256 (bit), which + // maximally produces a 72-byte DER signature. + // If a future version of the standard continues to enhance DSA, + // we may want to bump this limit to allow the max-1 (expected size) + // TryCreateSignature to pass. + // Future updates seem unlikely, though, as FIPS 186-5 October 2019 draft has + // DSA as a no longer supported/updated algorithm. + private const int SignatureStackBufSize = 72; + private const int BitsPerByte = 8; + + private Lazy _key = null!; + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl() + : this(2048) { - return new DSAImplementation.DSAOpenSsl(); } - } - internal static partial class DSAImplementation - { -#endif - public sealed partial class DSAOpenSsl : DSA + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl(int keySize) { - // The biggest key allowed by FIPS 186-4 has N=256 (bit), which - // maximally produces a 72-byte DER signature. - // If a future version of the standard continues to enhance DSA, - // we may want to bump this limit to allow the max-1 (expected size) - // TryCreateSignature to pass. - // Future updates seem unlikely, though, as FIPS 186-5 October 2019 draft has - // DSA as a no longer supported/updated algorithm. - private const int SignatureStackBufSize = 72; - private const int BitsPerByte = 8; - - private Lazy _key = null!; - - public DSAOpenSsl() - : this(2048) - { - } - - public DSAOpenSsl(int keySize) - { - ThrowIfNotSupported(); - LegalKeySizesValue = s_legalKeySizes; - base.KeySize = keySize; - _key = new Lazy(GenerateKey); - } + ThrowIfNotSupported(); + LegalKeySizesValue = s_legalKeySizes; + base.KeySize = keySize; + _key = new Lazy(GenerateKey); + } - public override int KeySize + public override int KeySize + { + set { - set + if (KeySize == value) { - if (KeySize == value) - { - return; - } + return; + } - // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key - base.KeySize = value; + // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key + base.KeySize = value; - ThrowIfDisposed(); - FreeKey(); - _key = new Lazy(GenerateKey); - } + ThrowIfDisposed(); + FreeKey(); + _key = new Lazy(GenerateKey); } + } - private void ForceSetKeySize(int newKeySize) - { - // In the event that a key was loaded via ImportParameters or an IntPtr/SafeHandle - // it could be outside of the bounds that we currently represent as "legal key sizes". - // Since that is our view into the underlying component it can be detached from the - // component's understanding. If it said it has opened a key, and this is the size, trust it. - KeySizeValue = newKeySize; - } + private void ForceSetKeySize(int newKeySize) + { + // In the event that a key was loaded via ImportParameters or an IntPtr/SafeHandle + // it could be outside of the bounds that we currently represent as "legal key sizes". + // Since that is our view into the underlying component it can be detached from the + // component's understanding. If it said it has opened a key, and this is the size, trust it. + KeySizeValue = newKeySize; + } - public override KeySizes[] LegalKeySizes + public override KeySizes[] LegalKeySizes + { + get { - get - { - return base.LegalKeySizes; - } + return base.LegalKeySizes; } + } - public override DSAParameters ExportParameters(bool includePrivateParameters) - { - // It's entirely possible that this line will cause the key to be generated in the first place. - SafeDsaHandle key = GetKey(); - - DSAParameters dsaParameters = Interop.Crypto.ExportDsaParameters(key, includePrivateParameters); - bool hasPrivateKey = dsaParameters.X != null; - - if (hasPrivateKey != includePrivateParameters) - throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + public override DSAParameters ExportParameters(bool includePrivateParameters) + { + // It's entirely possible that this line will cause the key to be generated in the first place. + SafeDsaHandle key = GetKey(); - return dsaParameters; - } + DSAParameters dsaParameters = Interop.Crypto.ExportDsaParameters(key, includePrivateParameters); + bool hasPrivateKey = dsaParameters.X != null; - public override void ImportParameters(DSAParameters parameters) - { - if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); + if (hasPrivateKey != includePrivateParameters) + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); - // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check - // is just to maintain parity with DSACNG and DSACryptoServiceProvider, which also perform this check. - if (parameters.J != null && parameters.J.Length >= parameters.P.Length) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); + return dsaParameters; + } - bool hasPrivateKey = parameters.X != null; + public override void ImportParameters(DSAParameters parameters) + { + if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); - int keySize = parameters.P.Length; - if (parameters.G.Length != keySize || parameters.Y.Length != keySize) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); + // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check + // is just to maintain parity with DSACNG and DSACryptoServiceProvider, which also perform this check. + if (parameters.J != null && parameters.J.Length >= parameters.P.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); - if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length) - throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); + bool hasPrivateKey = parameters.X != null; - ThrowIfDisposed(); + int keySize = parameters.P.Length; + if (parameters.G.Length != keySize || parameters.Y.Length != keySize) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); - SafeDsaHandle key; - if (!Interop.Crypto.DsaKeyCreateByExplicitParameters( - out key, - parameters.P, parameters.P.Length, - parameters.Q, parameters.Q.Length, - parameters.G, parameters.G.Length, - parameters.Y, parameters.Y.Length, - parameters.X, parameters.X != null ? parameters.X.Length : 0)) - { - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } + if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); - SetKey(key); - } + ThrowIfDisposed(); - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) + SafeDsaHandle key; + if (!Interop.Crypto.DsaKeyCreateByExplicitParameters( + out key, + parameters.P, parameters.P.Length, + parameters.Q, parameters.Q.Length, + parameters.G, parameters.G.Length, + parameters.Y, parameters.Y.Length, + parameters.X, parameters.X != null ? parameters.X.Length : 0)) { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + throw Interop.Crypto.CreateOpenSslCryptographicException(); } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); - } + SetKey(key); + } - protected override void Dispose(bool disposing) - { - if (disposing) - { - FreeKey(); - _key = null!; - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } - base.Dispose(disposing); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } - private void FreeKey() + protected override void Dispose(bool disposing) + { + if (disposing) { - if (_key != null && _key.IsValueCreated) - { - SafeDsaHandle handle = _key.Value; - - if (handle != null) - { - handle.Dispose(); - } - } + FreeKey(); + _key = null!; } - private static void CheckInvalidKey(SafeDsaHandle key) + base.Dispose(disposing); + } + + private void FreeKey() + { + if (_key != null && _key.IsValueCreated) { - if (key == null || key.IsInvalid) + SafeDsaHandle handle = _key.Value; + + if (handle != null) { - throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); + handle.Dispose(); } } + } - private SafeDsaHandle GenerateKey() + private static void CheckInvalidKey(SafeDsaHandle key) + { + if (key == null || key.IsInvalid) { - SafeDsaHandle key; + throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); + } + } - if (!Interop.Crypto.DsaGenerateKey(out key, KeySize)) - { - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } + private SafeDsaHandle GenerateKey() + { + SafeDsaHandle key; - return key; + if (!Interop.Crypto.DsaGenerateKey(out key, KeySize)) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); } - protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) - { - // we're sealed and the base should have checked this already - Debug.Assert(data != null); - Debug.Assert(offset >= 0 && offset <= data.Length); - Debug.Assert(count >= 0 && count <= data.Length); - Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); + return key; + } - return AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); - } + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + // we're sealed and the base should have checked this already + Debug.Assert(data != null); + Debug.Assert(offset >= 0 && offset <= data.Length); + Debug.Assert(count >= 0 && count <= data.Length); + Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); - protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => - AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + return AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + } - protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => - AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten); + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); - public override byte[] CreateSignature(byte[] rgbHash) - { - if (rgbHash == null) - throw new ArgumentNullException(nameof(rgbHash)); + protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => + AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten); - SafeDsaHandle key = GetKey(); - int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); - int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte; - Span signDestination = stackalloc byte[SignatureStackBufSize]; + public override byte[] CreateSignature(byte[] rgbHash) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); - ReadOnlySpan derSignature = SignHash(rgbHash, signDestination, signatureSize, key); - return AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize); - } + SafeDsaHandle key = GetKey(); + int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); + int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte; + Span signDestination = stackalloc byte[SignatureStackBufSize]; -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public override bool TryCreateSignature( - ReadOnlySpan hash, - Span destination, - out int bytesWritten) - { - return TryCreateSignatureCore( - hash, - destination, - DSASignatureFormat.IeeeP1363FixedFieldConcatenation, - out bytesWritten); - } + ReadOnlySpan derSignature = SignHash(rgbHash, signDestination, signatureSize, key); + return AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize); + } + + public override bool TryCreateSignature( + ReadOnlySpan hash, + Span destination, + out int bytesWritten) + { + return TryCreateSignatureCore( + hash, + destination, + DSASignatureFormat.IeeeP1363FixedFieldConcatenation, + out bytesWritten); + } + + protected override bool TryCreateSignatureCore( + ReadOnlySpan hash, + Span destination, + DSASignatureFormat signatureFormat, + out int bytesWritten) + { + SafeDsaHandle key = GetKey(); + int maxSignatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); + Span signDestination = stackalloc byte[SignatureStackBufSize]; - protected override bool TryCreateSignatureCore( - ReadOnlySpan hash, - Span destination, - DSASignatureFormat signatureFormat, - out int bytesWritten) -#else - public override bool TryCreateSignature(ReadOnlySpan hash, Span destination, out int bytesWritten) -#endif + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { - SafeDsaHandle key = GetKey(); - int maxSignatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); - Span signDestination = stackalloc byte[SignatureStackBufSize]; + int fieldSizeBytes = Interop.Crypto.DsaSignatureFieldSize(key); + int p1363SignatureSize = 2 * fieldSizeBytes; -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) -#endif + if (destination.Length < p1363SignatureSize) { - int fieldSizeBytes = Interop.Crypto.DsaSignatureFieldSize(key); - int p1363SignatureSize = 2 * fieldSizeBytes; - - if (destination.Length < p1363SignatureSize) - { - bytesWritten = 0; - return false; - } + bytesWritten = 0; + return false; + } - int fieldSizeBits = fieldSizeBytes * 8; + int fieldSizeBits = fieldSizeBytes * 8; - ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); - bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination); - Debug.Assert(bytesWritten == p1363SignatureSize); - return true; - } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) + ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); + bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination); + Debug.Assert(bytesWritten == p1363SignatureSize); + return true; + } + else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) + { + if (destination.Length >= maxSignatureSize) { - if (destination.Length >= maxSignatureSize) - { - signDestination = destination; - } - else if (maxSignatureSize > signDestination.Length) - { - Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)"); - bytesWritten = 0; - return false; - } - - ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); - - if (destination == signDestination) - { - bytesWritten = derSignature.Length; - return true; - } - - return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten); + signDestination = destination; } - else + else if (maxSignatureSize > signDestination.Length) { - Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); - throw new CryptographicException( - SR.Cryptography_UnknownSignatureFormat, - signatureFormat.ToString()); + Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)"); + bytesWritten = 0; + return false; } -#endif - } - private static ReadOnlySpan SignHash( - ReadOnlySpan hash, - Span destination, - int signatureLength, - SafeDsaHandle key) - { - if (signatureLength > destination.Length) - { - Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); - destination = new byte[signatureLength]; - } + ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); - if (!Interop.Crypto.DsaSign(key, hash, destination, out int actualLength)) + if (destination == signDestination) { - throw Interop.Crypto.CreateOpenSslCryptographicException(); + bytesWritten = derSignature.Length; + return true; } - Debug.Assert( - actualLength <= signatureLength, - "DSA_sign reported an unexpected signature size", - "DSA_sign reported signatureSize was {0}, when <= {1} was expected", - actualLength, - signatureLength); - - return destination.Slice(0, actualLength); + return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten); } + else + { + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } + } - public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + private static ReadOnlySpan SignHash( + ReadOnlySpan hash, + Span destination, + int signatureLength, + SafeDsaHandle key) + { + if (signatureLength > destination.Length) { - if (rgbHash == null) - throw new ArgumentNullException(nameof(rgbHash)); - if (rgbSignature == null) - throw new ArgumentNullException(nameof(rgbSignature)); + Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); + destination = new byte[signatureLength]; + } - return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature); + if (!Interop.Crypto.DsaSign(key, hash, destination, out int actualLength)) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + Debug.Assert( + actualLength <= signatureLength, + "DSA_sign reported an unexpected signature size", + "DSA_sign reported signatureSize was {0}, when <= {1} was expected", + actualLength, + signatureLength); - public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) => - VerifySignatureCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); + return destination.Slice(0, actualLength); + } - protected override bool VerifySignatureCore( - ReadOnlySpan hash, - ReadOnlySpan signature, - DSASignatureFormat signatureFormat) -#else - public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) -#endif - { - SafeDsaHandle key = GetKey(); + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (rgbSignature == null) + throw new ArgumentNullException(nameof(rgbSignature)); + + return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature); + } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) - { -#endif - int expectedSignatureBytes = Interop.Crypto.DsaSignatureFieldSize(key) * 2; - if (signature.Length != expectedSignatureBytes) - { - // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER. - return false; - } - - signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } - else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) - { - Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); - throw new CryptographicException( - SR.Cryptography_UnknownSignatureFormat, - signatureFormat.ToString()); - } -#endif - return Interop.Crypto.DsaVerify(key, hash, signature); - } - private void ThrowIfDisposed() + public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) => + VerifySignatureCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); + + protected override bool VerifySignatureCore( + ReadOnlySpan hash, + ReadOnlySpan signature, + DSASignatureFormat signatureFormat) + { + SafeDsaHandle key = GetKey(); + + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { - if (_key == null) + int expectedSignatureBytes = Interop.Crypto.DsaSignatureFieldSize(key) * 2; + if (signature.Length != expectedSignatureBytes) { - throw new ObjectDisposedException( -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - nameof(DSA) -#else - nameof(DSAOpenSsl) -#endif - ); + // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER. + return false; } - } - private SafeDsaHandle GetKey() + signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); + } + else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) { - ThrowIfDisposed(); + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } - SafeDsaHandle key = _key.Value; - CheckInvalidKey(key); + return Interop.Crypto.DsaVerify(key, hash, signature); + } - return key; + private void ThrowIfDisposed() + { + if (_key == null) + { + throw new ObjectDisposedException(nameof(DSAOpenSsl)); } + } - private void SetKey(SafeDsaHandle newKey) - { - // Do not call ThrowIfDisposed here, as it breaks the SafeEvpPKey ctor + private SafeDsaHandle GetKey() + { + ThrowIfDisposed(); - // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere - // with the already loaded key. - ForceSetKeySize(BitsPerByte * Interop.Crypto.DsaKeySize(newKey)); + SafeDsaHandle key = _key.Value; + CheckInvalidKey(key); - _key = new Lazy(newKey); - } + return key; + } - static partial void ThrowIfNotSupported(); + private void SetKey(SafeDsaHandle newKey) + { + // Do not call ThrowIfDisposed here, as it breaks the SafeEvpPKey ctor - private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) }; + // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere + // with the already loaded key. + ForceSetKeySize(BitsPerByte * Interop.Crypto.DsaKeySize(newKey)); + + _key = new Lazy(newKey); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + + static partial void ThrowIfNotSupported(); + + private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) }; } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs index 8b7e0dbb4ec71..1a4cbf4072782 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs @@ -1,26 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; -using System.Diagnostics; -using System.Formats.Asn1; using System.IO; -using System.Runtime.InteropServices; using System.Security.Cryptography.Apple; using Internal.Cryptography; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class DSA : AsymmetricAlgorithm - { - private static DSA CreateCore() - { - return new DSAImplementation.DSASecurityTransforms(); - } - } -#endif - internal static partial class DSAImplementation { public sealed partial class DSASecurityTransforms : DSA diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs index a0b8af82113da..dc902e555081b 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs @@ -23,10 +23,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); @@ -45,10 +43,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs index a18e08635b934..ebe5922994637 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs @@ -5,260 +5,253 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman { -#endif - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + public override void ImportParameters(ECParameters parameters) { - public override void ImportParameters(ECParameters parameters) - { - parameters.Validate(); - ThrowIfDisposed(); + parameters.Validate(); + ThrowIfDisposed(); - ECCurve curve = parameters.Curve; - bool includePrivateParameters = parameters.D != null; - bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null; + ECCurve curve = parameters.Curve; + bool includePrivateParameters = parameters.D != null; + bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null; - if (curve.IsPrime) - { - if (!hasPublicParameters && includePrivateParameters) - { - byte[] zero = new byte[parameters.D!.Length]; - ECParameters ecParamsCopy = parameters; - ecParamsCopy.Q.X = zero; - ecParamsCopy.Q.Y = zero; - byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: true); - ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true); - } - else - { - byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: true); - ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters); - } - } - else if (curve.IsNamed) + if (curve.IsPrime) + { + if (!hasPublicParameters && includePrivateParameters) { - // FriendlyName is required; an attempt was already made to default it in ECCurve - if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) - { - throw new PlatformNotSupportedException( - SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); - } - - if (!hasPublicParameters && includePrivateParameters) - { - byte[] zero = new byte[parameters.D!.Length]; - ECParameters ecParamsCopy = parameters; - ecParamsCopy.Q.X = zero; - ecParamsCopy.Q.Y = zero; - byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: true); - ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true); - } - else - { - byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: true); - ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters); - } + byte[] zero = new byte[parameters.D!.Length]; + ECParameters ecParamsCopy = parameters; + ecParamsCopy.Q.X = zero; + ecParamsCopy.Q.Y = zero; + byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: true); + ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true); } else { - throw new PlatformNotSupportedException( - SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: true); + ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters); } } - - public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + else if (curve.IsNamed) { - byte[] blob = ExportFullKeyBlob(includePrivateParameters); + // FriendlyName is required; an attempt was already made to default it in ECCurve + if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) + { + throw new PlatformNotSupportedException( + SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); + } - try + if (!hasPublicParameters && includePrivateParameters) { - ECParameters ecparams = default; - ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); - return ecparams; + byte[] zero = new byte[parameters.D!.Length]; + ECParameters ecParamsCopy = parameters; + ecParamsCopy.Q.X = zero; + ecParamsCopy.Q.Y = zero; + byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: true); + ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true); } - finally + else { - Array.Clear(blob); + byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: true); + ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters); } } + else + { + throw new PlatformNotSupportedException( + SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + } + } - public override ECParameters ExportParameters(bool includePrivateParameters) + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + { + byte[] blob = ExportFullKeyBlob(includePrivateParameters); + + try { ECParameters ecparams = default; + ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); + return ecparams; + } + finally + { + Array.Clear(blob); + } + } - string? curveName = GetCurveName(out string? oidValue); - byte[]? blob = null; + public override ECParameters ExportParameters(bool includePrivateParameters) + { + ECParameters ecparams = default; - try + string? curveName = GetCurveName(out string? oidValue); + byte[]? blob = null; + + try + { + if (string.IsNullOrEmpty(curveName)) { - if (string.IsNullOrEmpty(curveName)) - { - blob = ExportFullKeyBlob(includePrivateParameters); - ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); - } - else - { - blob = ExportKeyBlob(includePrivateParameters); - ECCng.ExportNamedCurveParameters(ref ecparams, blob, includePrivateParameters); - ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName)); - } - - return ecparams; + blob = ExportFullKeyBlob(includePrivateParameters); + ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); } - finally + else { - if (blob != null) - { - Array.Clear(blob); - } + blob = ExportKeyBlob(includePrivateParameters); + ECCng.ExportNamedCurveParameters(ref ecparams, blob, includePrivateParameters); + ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName)); } - } - - public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) - { - ThrowIfDisposed(); - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead); - ProcessPkcs8Response(response); - bytesRead = localRead; + return ecparams; } - - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) + finally { - ThrowIfDisposed(); - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( - passwordBytes, - source, - out int localRead); - - ProcessPkcs8Response(response); - bytesRead = localRead; + if (blob != null) + { + Array.Clear(blob); + } } + } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( - password, - source, - out int localRead); + public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) + { + ThrowIfDisposed(); + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead); - ProcessPkcs8Response(response); - bytesRead = localRead; - } + ProcessPkcs8Response(response); + bytesRead = localRead; + } - private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response) - { - // Wrong algorithm? - if (response.GetAlgorithmGroup() != BCryptNative.AlgorithmName.ECDH) - { - response.FreeKey(); - throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( + passwordBytes, + source, + out int localRead); + + ProcessPkcs8Response(response); + bytesRead = localRead; + } - AcceptImport(response); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( + password, + source, + out int localRead); + + ProcessPkcs8Response(response); + bytesRead = localRead; + } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters) + private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response) + { + // Wrong algorithm? + if (response.GetAlgorithmGroup() != BCryptNative.AlgorithmName.ECDH) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); - - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters); + response.FreeKey(); + throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters) - { - if (pbeParameters == null) - { - throw new ArgumentNullException(nameof(pbeParameters)); - } + AcceptImport(response); + } - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); - if (CngPkcs8.IsPlatformScheme(pbeParameters)) - { - return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); - } + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters); + } - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - password, - pbeParameters); + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) + { + if (pbeParameters == null) + { + throw new ArgumentNullException(nameof(pbeParameters)); } - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); + + if (CngPkcs8.IsPlatformScheme(pbeParameters)) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); - - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - ReadOnlySpan.Empty, - passwordBytes); - - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters, - destination, - out bytesWritten); + return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); } - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) - { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters); + } - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + ReadOnlySpan.Empty, + passwordBytes); + + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters, + destination, + out bytesWritten); + } - if (CngPkcs8.IsPlatformScheme(pbeParameters)) - { - return TryExportEncryptedPkcs8( - password, - pbeParameters.IterationCount, - destination, - out bytesWritten); - } + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, + if (CngPkcs8.IsPlatformScheme(pbeParameters)) + { + return TryExportEncryptedPkcs8( password, - pbeParameters, + pbeParameters.IterationCount, destination, out bytesWritten); } + + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters, + destination, + out bytesWritten); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs index 90d2e4f01145c..f1db21ff401e7 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs @@ -1,145 +1,138 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman { -#endif - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng() : this(521) { } + + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(int keySize) { - public ECDiffieHellmanCng() : this(521) { } + KeySize = keySize; + } - public ECDiffieHellmanCng(int keySize) - { - KeySize = keySize; - } + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(ECCurve curve) + { + // GenerateKey will already do all of the validation we need. + GenerateKey(curve); + } - public ECDiffieHellmanCng(ECCurve curve) + public override int KeySize + { + get { - // GenerateKey will already do all of the validation we need. - GenerateKey(curve); + return base.KeySize; } - - public override int KeySize + set { - get + if (KeySize == value) { - return base.KeySize; + return; } - set - { - if (KeySize == value) - { - return; - } - // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key - base.KeySize = value; + // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key + base.KeySize = value; - DisposeKey(); - // Key will be lazily re-created - } + DisposeKey(); + // Key will be lazily re-created } + } - /// - /// Set the KeySize without validating against LegalKeySizes. - /// - /// The value to set the KeySize to. - private void ForceSetKeySize(int newKeySize) - { - // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle - // it could be outside of the bounds that we currently represent as "legal key sizes". - // Since that is our view into the underlying component it can be detached from the - // component's understanding. If it said it has opened a key, and this is the size, trust it. - KeySizeValue = newKeySize; - } + /// + /// Set the KeySize without validating against LegalKeySizes. + /// + /// The value to set the KeySize to. + private void ForceSetKeySize(int newKeySize) + { + // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle + // it could be outside of the bounds that we currently represent as "legal key sizes". + // Since that is our view into the underlying component it can be detached from the + // component's understanding. If it said it has opened a key, and this is the size, trust it. + KeySizeValue = newKeySize; + } - public override KeySizes[] LegalKeySizes + public override KeySizes[] LegalKeySizes + { + get { - get - { - // Return the three sizes that can be explicitly set (for backwards compatibility) - return new[] { - new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), - new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), - }; - } + // Return the three sizes that can be explicitly set (for backwards compatibility) + return new[] { + new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), + new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), + }; } + } - public override byte[] DeriveKeyFromHash( - ECDiffieHellmanPublicKey otherPartyPublicKey, - HashAlgorithmName hashAlgorithm, - byte[]? secretPrepend, - byte[]? secretAppend) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + public override byte[] DeriveKeyFromHash( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? secretPrepend, + byte[]? secretAppend) + { + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); - using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) - { - return Interop.NCrypt.DeriveKeyMaterialHash( - secretAgreement, - hashAlgorithm.Name, - secretPrepend, - secretAppend, - Interop.NCrypt.SecretAgreementFlags.None); - } + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) + { + return Interop.NCrypt.DeriveKeyMaterialHash( + secretAgreement, + hashAlgorithm.Name, + secretPrepend, + secretAppend, + Interop.NCrypt.SecretAgreementFlags.None); } + } - public override byte[] DeriveKeyFromHmac( - ECDiffieHellmanPublicKey otherPartyPublicKey, - HashAlgorithmName hashAlgorithm, - byte[]? hmacKey, - byte[]? secretPrepend, - byte[]? secretAppend) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + public override byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? hmacKey, + byte[]? secretPrepend, + byte[]? secretAppend) + { + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); - using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) - { - Interop.NCrypt.SecretAgreementFlags flags = hmacKey == null ? - Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey : - Interop.NCrypt.SecretAgreementFlags.None; - - return Interop.NCrypt.DeriveKeyMaterialHmac( - secretAgreement, - hashAlgorithm.Name, - hmacKey, - secretPrepend, - secretAppend, - flags); - } + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) + { + Interop.NCrypt.SecretAgreementFlags flags = hmacKey == null ? + Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey : + Interop.NCrypt.SecretAgreementFlags.None; + + return Interop.NCrypt.DeriveKeyMaterialHmac( + secretAgreement, + hashAlgorithm.Name, + hmacKey, + secretPrepend, + secretAppend, + flags); } + } - public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) + public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) + { + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); + if (prfLabel == null) + throw new ArgumentNullException(nameof(prfLabel)); + if (prfSeed == null) + throw new ArgumentNullException(nameof(prfSeed)); + + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (prfLabel == null) - throw new ArgumentNullException(nameof(prfLabel)); - if (prfSeed == null) - throw new ArgumentNullException(nameof(prfSeed)); - - using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) - { - return Interop.NCrypt.DeriveKeyMaterialTls( - secretAgreement, - prfLabel, - prfSeed, - Interop.NCrypt.SecretAgreementFlags.None); - } + return Interop.NCrypt.DeriveKeyMaterialTls( + secretAgreement, + prfLabel, + prfSeed, + Interop.NCrypt.SecretAgreementFlags.None); } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs index 11638ed44be8a..bee07782afc3d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs @@ -6,200 +6,189 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman { -#endif - public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman + /// + /// Given a second party's public key, derive shared key material + /// + public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) => + DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256, null, null); + + public override byte[] DeriveKeyFromHash( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? secretPrepend, + byte[]? secretAppend) { - /// - /// Given a second party's public key, derive shared key material - /// - public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) => - DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256, null, null); - - public override byte[] DeriveKeyFromHash( - ECDiffieHellmanPublicKey otherPartyPublicKey, - HashAlgorithmName hashAlgorithm, - byte[]? secretPrepend, - byte[]? secretAppend) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - - ThrowIfDisposed(); - - return ECDiffieHellmanDerivation.DeriveKeyFromHash( - otherPartyPublicKey, - hashAlgorithm, - secretPrepend, - secretAppend, - (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); - } + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); - public override byte[] DeriveKeyFromHmac( - ECDiffieHellmanPublicKey otherPartyPublicKey, - HashAlgorithmName hashAlgorithm, - byte[]? hmacKey, - byte[]? secretPrepend, - byte[]? secretAppend) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - - ThrowIfDisposed(); - - return ECDiffieHellmanDerivation.DeriveKeyFromHmac( - otherPartyPublicKey, - hashAlgorithm, - hmacKey, - secretPrepend, - secretAppend, - (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); - } + ThrowIfDisposed(); - public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (prfLabel == null) - throw new ArgumentNullException(nameof(prfLabel)); - if (prfSeed == null) - throw new ArgumentNullException(nameof(prfSeed)); - - ThrowIfDisposed(); - - return ECDiffieHellmanDerivation.DeriveKeyTls( - otherPartyPublicKey, - prfLabel, - prfSeed, - (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); - } + return ECDiffieHellmanDerivation.DeriveKeyFromHash( + otherPartyPublicKey, + hashAlgorithm, + secretPrepend, + secretAppend, + (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); + } + + public override byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? hmacKey, + byte[]? secretPrepend, + byte[]? secretAppend) + { + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + + ThrowIfDisposed(); + + return ECDiffieHellmanDerivation.DeriveKeyFromHmac( + otherPartyPublicKey, + hashAlgorithm, + hmacKey, + secretPrepend, + secretAppend, + (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); + } + + public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) + { + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); + if (prfLabel == null) + throw new ArgumentNullException(nameof(prfLabel)); + if (prfSeed == null) + throw new ArgumentNullException(nameof(prfSeed)); + + ThrowIfDisposed(); + + return ECDiffieHellmanDerivation.DeriveKeyTls( + otherPartyPublicKey, + prfLabel, + prfSeed, + (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)); + } - /// - /// Get the secret agreement generated between two parties - /// - private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash? hasher) + /// + /// Get the secret agreement generated between two parties + /// + private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash? hasher) + { + Debug.Assert(otherPartyPublicKey != null); + + // Ensure that this ECDH object contains a private key by attempting a parameter export + // which will throw an OpenSslCryptoException if no private key is available + ECParameters thisKeyExplicit = ExportExplicitParameters(true); + bool thisIsNamed = Interop.Crypto.EcKeyHasCurveName(_key.Value); + ECDiffieHellmanOpenSslPublicKey? otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey; + bool disposeOtherKey = false; + + if (otherKey == null) { - Debug.Assert(otherPartyPublicKey != null); + disposeOtherKey = true; - // Ensure that this ECDH object contains a private key by attempting a parameter export - // which will throw an OpenSslCryptoException if no private key is available - ECParameters thisKeyExplicit = ExportExplicitParameters(true); - bool thisIsNamed = Interop.Crypto.EcKeyHasCurveName(_key.Value); - ECDiffieHellmanOpenSslPublicKey? otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey; - bool disposeOtherKey = false; + ECParameters otherParameters = + thisIsNamed + ? otherPartyPublicKey.ExportParameters() + : otherPartyPublicKey.ExportExplicitParameters(); - if (otherKey == null) - { - disposeOtherKey = true; + otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters); + } - ECParameters otherParameters = - thisIsNamed - ? otherPartyPublicKey.ExportParameters() - : otherPartyPublicKey.ExportExplicitParameters(); + bool otherIsNamed = otherKey.HasCurveName; - otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters); - } + SafeEvpPKeyHandle? ourKey = null; + SafeEvpPKeyHandle? theirKey = null; + byte[]? rented = null; + int secretLength = 0; - bool otherIsNamed = otherKey.HasCurveName; + try + { + if (otherKey.KeySize != KeySize) + { + throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); + } - SafeEvpPKeyHandle? ourKey = null; - SafeEvpPKeyHandle? theirKey = null; - byte[]? rented = null; - int secretLength = 0; + if (otherIsNamed == thisIsNamed) + { + ourKey = _key.UpRefKeyHandle(); + theirKey = otherKey.DuplicateKeyHandle(); + } + else if (otherIsNamed) + { + ourKey = _key.UpRefKeyHandle(); - try + using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters())) + { + theirKey = tmp.UpRefKeyHandle(); + } + } + else { - if (otherKey.KeySize != KeySize) + using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit)) { - throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); + ourKey = tmp.UpRefKeyHandle(); } - if (otherIsNamed == thisIsNamed) + theirKey = otherKey.DuplicateKeyHandle(); + } + + using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU)) + { + if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue) { - ourKey = _key.UpRefKeyHandle(); - theirKey = otherKey.DuplicateKeyHandle(); + throw Interop.Crypto.CreateOpenSslCryptographicException(); } - else if (otherIsNamed) - { - ourKey = _key.UpRefKeyHandle(); - using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters())) - { - theirKey = tmp.UpRefKeyHandle(); - } + secretLength = (int)secretLengthU; + + // Indicate that secret can hold stackallocs from nested scopes + Span secret = stackalloc byte[0]; + + // Arbitrary limit. But it covers secp521r1, which is the biggest common case. + const int StackAllocMax = 66; + + if (secretLength > StackAllocMax) + { + rented = CryptoPool.Rent(secretLength); + secret = new Span(rented, 0, secretLength); } else { - using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit)) - { - ourKey = tmp.UpRefKeyHandle(); - } - - theirKey = otherKey.DuplicateKeyHandle(); + secret = stackalloc byte[secretLength]; } - using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU)) - { - if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue) - { - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } - - secretLength = (int)secretLengthU; - - // Indicate that secret can hold stackallocs from nested scopes - Span secret = stackalloc byte[0]; - - // Arbitrary limit. But it covers secp521r1, which is the biggest common case. - const int StackAllocMax = 66; - - if (secretLength > StackAllocMax) - { - rented = CryptoPool.Rent(secretLength); - secret = new Span(rented, 0, secretLength); - } - else - { - secret = stackalloc byte[secretLength]; - } - - Interop.Crypto.EvpPKeyDeriveSecretAgreement(ctx, secret); - - if (hasher == null) - { - return secret.ToArray(); - } - else - { - hasher.AppendData(secret); - return null; - } - } - } - finally - { - theirKey?.Dispose(); - ourKey?.Dispose(); + Interop.Crypto.EvpPKeyDeriveSecretAgreement(ctx, secret); - if (disposeOtherKey) + if (hasher == null) { - otherKey.Dispose(); + return secret.ToArray(); } - - if (rented != null) + else { - CryptoPool.Return(rented, secretLength); + hasher.AppendData(secret); + return null; } } } + finally + { + theirKey?.Dispose(); + ourKey?.Dispose(); + + if (disposeOtherKey) + { + otherKey.Dispose(); + } + + if (rented != null) + { + CryptoPool.Return(rented, secretLength); + } + } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs index d1fa05f1db39c..29a082879de22 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs @@ -1,144 +1,147 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman { -#endif - public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman + private ECOpenSsl _key; + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(ECCurve curve) { - private ECOpenSsl _key; + ThrowIfNotSupported(); + _key = new ECOpenSsl(curve); + KeySizeValue = _key.KeySize; + } - public ECDiffieHellmanOpenSsl(ECCurve curve) - { - ThrowIfNotSupported(); - _key = new ECOpenSsl(curve); - KeySizeValue = _key.KeySize; - } + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl() + : this(521) + { + } - public ECDiffieHellmanOpenSsl() - : this(521) - { - } + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(int keySize) + { + ThrowIfNotSupported(); + base.KeySize = keySize; + _key = new ECOpenSsl(this); + } - public ECDiffieHellmanOpenSsl(int keySize) + public override KeySizes[] LegalKeySizes => + new[] { + new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), + new KeySizes(minSize: 521, maxSize: 521, skipSize: 0) + }; + + protected override void Dispose(bool disposing) + { + if (disposing) { - ThrowIfNotSupported(); - base.KeySize = keySize; - _key = new ECOpenSsl(this); + _key?.Dispose(); + _key = null!; } - public override KeySizes[] LegalKeySizes => - new[] { - new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), - new KeySizes(minSize: 521, maxSize: 521, skipSize: 0) - }; + base.Dispose(disposing); + } - protected override void Dispose(bool disposing) + public override int KeySize + { + get { - if (disposing) - { - _key?.Dispose(); - _key = null!; - } - - base.Dispose(disposing); + return base.KeySize; } - - public override int KeySize + set { - get + if (KeySize == value) { - return base.KeySize; + return; } - set - { - if (KeySize == value) - { - return; - } - // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key - base.KeySize = value; + // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key + base.KeySize = value; - ThrowIfDisposed(); - _key.Dispose(); - _key = new ECOpenSsl(this); - } - } - - public override void GenerateKey(ECCurve curve) - { ThrowIfDisposed(); - KeySizeValue = _key.GenerateKey(curve); + _key.Dispose(); + _key = new ECOpenSsl(this); } + } - public override ECDiffieHellmanPublicKey PublicKey - { - get - { - ThrowIfDisposed(); - return new ECDiffieHellmanOpenSslPublicKey(_key.UpRefKeyHandle()); - } - } + public override void GenerateKey(ECCurve curve) + { + ThrowIfDisposed(); + KeySizeValue = _key.GenerateKey(curve); + } - public override void ImportParameters(ECParameters parameters) + public override ECDiffieHellmanPublicKey PublicKey + { + get { ThrowIfDisposed(); - KeySizeValue = _key.ImportParameters(parameters); + return new ECDiffieHellmanOpenSslPublicKey(_key.UpRefKeyHandle()); } + } - public override ECParameters ExportExplicitParameters(bool includePrivateParameters) => - ECOpenSsl.ExportExplicitParameters(GetKey(), includePrivateParameters); + public override void ImportParameters(ECParameters parameters) + { + ThrowIfDisposed(); + KeySizeValue = _key.ImportParameters(parameters); + } - public override ECParameters ExportParameters(bool includePrivateParameters) => - ECOpenSsl.ExportParameters(GetKey(), includePrivateParameters); + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) => + ECOpenSsl.ExportExplicitParameters(GetKey(), includePrivateParameters); - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); - } + public override ECParameters ExportParameters(bool includePrivateParameters) => + ECOpenSsl.ExportParameters(GetKey(), includePrivateParameters); - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } - private void ThrowIfDisposed() - { - if (_key == null) - { - throw new ObjectDisposedException( -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - nameof(ECDiffieHellman) -#else - nameof(ECDiffieHellmanOpenSsl) -#endif - ); - } - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } - private SafeEcKeyHandle GetKey() + private void ThrowIfDisposed() + { + if (_key == null) { - ThrowIfDisposed(); - return _key.Value; + throw new ObjectDisposedException(nameof(ECDiffieHellmanOpenSsl)); } + } - static partial void ThrowIfNotSupported(); + private SafeEcKeyHandle GetKey() + { + ThrowIfDisposed(); + return _key.Value; } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + + static partial void ThrowIfNotSupported(); } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs index 00dde9c3b1bf2..d36370d054f9a 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs @@ -5,121 +5,108 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDiffieHellmanImplementation + internal sealed class ECDiffieHellmanOpenSslPublicKey : ECDiffieHellmanPublicKey { -#endif - internal sealed class ECDiffieHellmanOpenSslPublicKey : ECDiffieHellmanPublicKey + private ECOpenSsl _key; + + internal ECDiffieHellmanOpenSslPublicKey(SafeEvpPKeyHandle pkeyHandle) { - private ECOpenSsl _key; + if (pkeyHandle == null) + throw new ArgumentNullException(nameof(pkeyHandle)); + if (pkeyHandle.IsInvalid) + throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(pkeyHandle)); + + // If ecKey is valid it has already been up-ref'd, so we can just use this handle as-is. + SafeEcKeyHandle key = Interop.Crypto.EvpPkeyGetEcKey(pkeyHandle); - internal ECDiffieHellmanOpenSslPublicKey(SafeEvpPKeyHandle pkeyHandle) + if (key.IsInvalid) { - if (pkeyHandle == null) - throw new ArgumentNullException(nameof(pkeyHandle)); - if (pkeyHandle.IsInvalid) - throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(pkeyHandle)); + key.Dispose(); + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } - // If ecKey is valid it has already been up-ref'd, so we can just use this handle as-is. - SafeEcKeyHandle key = Interop.Crypto.EvpPkeyGetEcKey(pkeyHandle); + _key = new ECOpenSsl(key); + } - if (key.IsInvalid) - { - key.Dispose(); - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } + internal ECDiffieHellmanOpenSslPublicKey(ECParameters parameters) + { + _key = new ECOpenSsl(parameters); + } - _key = new ECOpenSsl(key); - } + public override string ToXmlString() + { + throw new PlatformNotSupportedException(); + } - internal ECDiffieHellmanOpenSslPublicKey(ECParameters parameters) - { - _key = new ECOpenSsl(parameters); - } + public override byte[] ToByteArray() + { + throw new PlatformNotSupportedException(); + } + + public override ECParameters ExportExplicitParameters() => + ECOpenSsl.ExportExplicitParameters(GetKey(), includePrivateParameters: false); + + public override ECParameters ExportParameters() => + ECOpenSsl.ExportParameters(GetKey(), includePrivateParameters: false); - public override string ToXmlString() + internal bool HasCurveName => Interop.Crypto.EcKeyHasCurveName(GetKey()); + + internal int KeySize + { + get { - throw new PlatformNotSupportedException(); + ThrowIfDisposed(); + return _key.KeySize; } + } - public override byte[] ToByteArray() + protected override void Dispose(bool disposing) + { + if (disposing) { - throw new PlatformNotSupportedException(); + _key?.Dispose(); + _key = null!; } - public override ECParameters ExportExplicitParameters() => - ECOpenSsl.ExportExplicitParameters(GetKey(), includePrivateParameters: false); - - public override ECParameters ExportParameters() => - ECOpenSsl.ExportParameters(GetKey(), includePrivateParameters: false); - - internal bool HasCurveName => Interop.Crypto.EcKeyHasCurveName(GetKey()); + base.Dispose(disposing); + } - internal int KeySize - { - get - { - ThrowIfDisposed(); - return _key.KeySize; - } - } + internal SafeEvpPKeyHandle DuplicateKeyHandle() + { + SafeEcKeyHandle currentKey = GetKey(); + SafeEvpPKeyHandle pkeyHandle = Interop.Crypto.EvpPkeyCreate(); - protected override void Dispose(bool disposing) + try { - if (disposing) + // Wrapping our key in an EVP_PKEY will up_ref our key. + // When the EVP_PKEY is Disposed it will down_ref the key. + // So everything should be copacetic. + if (!Interop.Crypto.EvpPkeySetEcKey(pkeyHandle, currentKey)) { - _key?.Dispose(); - _key = null!; + throw Interop.Crypto.CreateOpenSslCryptographicException(); } - base.Dispose(disposing); + return pkeyHandle; } - - internal SafeEvpPKeyHandle DuplicateKeyHandle() + catch { - SafeEcKeyHandle currentKey = GetKey(); - SafeEvpPKeyHandle pkeyHandle = Interop.Crypto.EvpPkeyCreate(); - - try - { - // Wrapping our key in an EVP_PKEY will up_ref our key. - // When the EVP_PKEY is Disposed it will down_ref the key. - // So everything should be copacetic. - if (!Interop.Crypto.EvpPkeySetEcKey(pkeyHandle, currentKey)) - { - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } - - return pkeyHandle; - } - catch - { - pkeyHandle.Dispose(); - throw; - } + pkeyHandle.Dispose(); + throw; } + } - private void ThrowIfDisposed() + private void ThrowIfDisposed() + { + if (_key == null) { - if (_key == null) - { - throw new ObjectDisposedException( -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - nameof(ECDiffieHellmanPublicKey) -#else - nameof(ECDiffieHellmanOpenSslPublicKey) -#endif - ); - } + throw new ObjectDisposedException(nameof(ECDiffieHellmanOpenSslPublicKey)); } + } - private SafeEcKeyHandle GetKey() - { - ThrowIfDisposed(); - return _key.Value; - } + private SafeEcKeyHandle GetKey() + { + ThrowIfDisposed(); + return _key.Value; } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs index 214bc96f8b0e9..ff17de4523cde 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs @@ -79,6 +79,11 @@ public override ECParameters ExportParameters(bool includePrivateParameters) return _ecc.ExportParameters(includePrivateParameters, KeySize); } + internal bool TryExportDataKeyParameters(bool includePrivateParameters, ref ECParameters ecParameters) + { + return _ecc.TryExportDataKeyParameters(includePrivateParameters, KeySize, ref ecParameters); + } + public override void ImportParameters(ECParameters parameters) { KeySizeValue = _ecc.ImportParameters(parameters); @@ -121,10 +126,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); @@ -143,10 +146,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.HashData.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.HashData.cs index 7733428958396..fcbc2db36376e 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.HashData.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.HashData.cs @@ -1,18 +1,12 @@ // 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.Diagnostics; using System.IO; using Internal.Cryptography; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDsaImplementation - { -#endif public sealed partial class ECDsaCng : ECDsa { protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => @@ -24,7 +18,4 @@ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => CngCommon.TryHashData(source, destination, hashAlgorithm, out bytesWritten); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.ImportExport.cs index f37c712f70daf..003c6ba312f40 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.ImportExport.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.ImportExport.cs @@ -5,277 +5,270 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDsaImplementation + public sealed partial class ECDsaCng : ECDsa { -#endif - public sealed partial class ECDsaCng : ECDsa + /// + /// ImportParameters will replace the existing key that ECDsaCng is working with by creating a + /// new CngKey. If the parameters contains only Q, then only a public key will be imported. + /// If the parameters also contains D, then a full key pair will be imported. + /// The parameters Curve value specifies the type of the curve to import. + /// + /// + /// if does not contain valid values. + /// + /// + /// if references a curve that cannot be imported. + /// + /// + /// if references a curve that is not supported by this platform. + /// + public override void ImportParameters(ECParameters parameters) { - /// - /// ImportParameters will replace the existing key that ECDsaCng is working with by creating a - /// new CngKey. If the parameters contains only Q, then only a public key will be imported. - /// If the parameters also contains D, then a full key pair will be imported. - /// The parameters Curve value specifies the type of the curve to import. - /// - /// - /// if does not contain valid values. - /// - /// - /// if references a curve that cannot be imported. - /// - /// - /// if references a curve that is not supported by this platform. - /// - public override void ImportParameters(ECParameters parameters) - { - parameters.Validate(); - ThrowIfDisposed(); + parameters.Validate(); + ThrowIfDisposed(); - ECCurve curve = parameters.Curve; - bool includePrivateParameters = parameters.D != null; - bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null; + ECCurve curve = parameters.Curve; + bool includePrivateParameters = parameters.D != null; + bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null; - if (curve.IsPrime) - { - if (!hasPublicParameters && includePrivateParameters) - { - byte[] zero = new byte[parameters.D!.Length]; - ECParameters ecParamsCopy = parameters; - ecParamsCopy.Q.X = zero; - ecParamsCopy.Q.Y = zero; - byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: false); - ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true); - } - else - { - byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: false); - ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters); - } - } - else if (curve.IsNamed) + if (curve.IsPrime) + { + if (!hasPublicParameters && includePrivateParameters) { - // FriendlyName is required; an attempt was already made to default it in ECCurve - if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value!.ToString())); - - if (!hasPublicParameters && includePrivateParameters) - { - byte[] zero = new byte[parameters.D!.Length]; - ECParameters ecParamsCopy = parameters; - ecParamsCopy.Q.X = zero; - ecParamsCopy.Q.Y = zero; - byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: false); - ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true); - } - else - { - byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: false); - ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters); - } + byte[] zero = new byte[parameters.D!.Length]; + ECParameters ecParamsCopy = parameters; + ecParamsCopy.Q.X = zero; + ecParamsCopy.Q.Y = zero; + byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: false); + ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true); } else { - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: false); + ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters); } } - - /// - /// Exports the key and explicit curve parameters used by the ECC object into an object. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// - /// if explicit export is not supported by this platform. Windows 10 or higher is required. - /// - /// The key and explicit curve parameters used by the ECC object. - public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + else if (curve.IsNamed) { - byte[] blob = ExportFullKeyBlob(includePrivateParameters); - ECParameters ecparams = default; - ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); - return ecparams; - } - - /// - /// Exports the key used by the ECC object into an object. - /// If the curve has a name, the Curve property will contain named curve parameters otherwise it will contain explicit parameters. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// The key and named curve parameters used by the ECC object. - public override ECParameters ExportParameters(bool includePrivateParameters) - { - ECParameters ecparams = default; - - string? curveName = GetCurveName(out string? oidValue); + // FriendlyName is required; an attempt was already made to default it in ECCurve + if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value!.ToString())); - if (string.IsNullOrEmpty(curveName)) + if (!hasPublicParameters && includePrivateParameters) { - byte[] fullKeyBlob = ExportFullKeyBlob(includePrivateParameters); - ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters); + byte[] zero = new byte[parameters.D!.Length]; + ECParameters ecParamsCopy = parameters; + ecParamsCopy.Q.X = zero; + ecParamsCopy.Q.Y = zero; + byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: false); + ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true); } else { - byte[] keyBlob = ExportKeyBlob(includePrivateParameters); - ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters); - ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName)); + byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: false); + ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters); } - - return ecparams; } - - public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) + else { - ThrowIfDisposed(); + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + } + } - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead); + /// + /// Exports the key and explicit curve parameters used by the ECC object into an object. + /// + /// + /// if there was an issue obtaining the curve values. + /// + /// + /// if explicit export is not supported by this platform. Windows 10 or higher is required. + /// + /// The key and explicit curve parameters used by the ECC object. + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + { + byte[] blob = ExportFullKeyBlob(includePrivateParameters); + ECParameters ecparams = default; + ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); + return ecparams; + } - ProcessPkcs8Response(response); - bytesRead = localRead; - } + /// + /// Exports the key used by the ECC object into an object. + /// If the curve has a name, the Curve property will contain named curve parameters otherwise it will contain explicit parameters. + /// + /// + /// if there was an issue obtaining the curve values. + /// + /// The key and named curve parameters used by the ECC object. + public override ECParameters ExportParameters(bool includePrivateParameters) + { + ECParameters ecparams = default; - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) + string? curveName = GetCurveName(out string? oidValue); + + if (string.IsNullOrEmpty(curveName)) + { + byte[] fullKeyBlob = ExportFullKeyBlob(includePrivateParameters); + ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters); + } + else { - ThrowIfDisposed(); + byte[] keyBlob = ExportKeyBlob(includePrivateParameters); + ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters); + ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName)); + } - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( - passwordBytes, - source, - out int localRead); + return ecparams; + } - ProcessPkcs8Response(response); - bytesRead = localRead; - } + public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) + { + ThrowIfDisposed(); - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead); - CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( - password, - source, - out int localRead); + ProcessPkcs8Response(response); + bytesRead = localRead; + } - ProcessPkcs8Response(response); - bytesRead = localRead; - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); - private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response) - { - // Wrong algorithm? - switch (response.GetAlgorithmGroup()) - { - // CNG ECDH and ECDSA keys can both do ECDSA. - case BCryptNative.AlgorithmName.ECDsa: - case BCryptNative.AlgorithmName.ECDH: - AcceptImport(response); - return; - } + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( + passwordBytes, + source, + out int localRead); - response.FreeKey(); - throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); - } + ProcessPkcs8Response(response); + bytesRead = localRead; + } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters) - { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters); - } + CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey( + password, + source, + out int localRead); + + ProcessPkcs8Response(response); + bytesRead = localRead; + } - public override byte[] ExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters) + private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response) + { + // Wrong algorithm? + switch (response.GetAlgorithmGroup()) { - if (pbeParameters == null) - { - throw new ArgumentNullException(nameof(pbeParameters)); - } + // CNG ECDH and ECDSA keys can both do ECDSA. + case BCryptNative.AlgorithmName.ECDsa: + case BCryptNative.AlgorithmName.ECDH: + AcceptImport(response); + return; + } - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + response.FreeKey(); + throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); + } - if (CngPkcs8.IsPlatformScheme(pbeParameters)) - { - return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); - } + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); - return CngPkcs8.ExportEncryptedPkcs8PrivateKey( - this, - password, - pbeParameters); - } + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters); + } - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) + { + if (pbeParameters == null) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); - - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - ReadOnlySpan.Empty, - passwordBytes); - - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, - passwordBytes, - pbeParameters, - destination, - out bytesWritten); + throw new ArgumentNullException(nameof(pbeParameters)); } - public override bool TryExportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - PbeParameters pbeParameters, - Span destination, - out int bytesWritten) + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); + + if (CngPkcs8.IsPlatformScheme(pbeParameters)) { - if (pbeParameters == null) - throw new ArgumentNullException(nameof(pbeParameters)); + return ExportEncryptedPkcs8(password, pbeParameters.IterationCount); + } - PasswordBasedEncryption.ValidatePbeParameters( - pbeParameters, - password, - ReadOnlySpan.Empty); + return CngPkcs8.ExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters); + } - if (CngPkcs8.IsPlatformScheme(pbeParameters)) - { - return TryExportEncryptedPkcs8( - password, - pbeParameters.IterationCount, - destination, - out bytesWritten); - } + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + ReadOnlySpan.Empty, + passwordBytes); + + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + passwordBytes, + pbeParameters, + destination, + out bytesWritten); + } + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + if (pbeParameters == null) + throw new ArgumentNullException(nameof(pbeParameters)); + + PasswordBasedEncryption.ValidatePbeParameters( + pbeParameters, + password, + ReadOnlySpan.Empty); - return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( - this, + if (CngPkcs8.IsPlatformScheme(pbeParameters)) + { + return TryExportEncryptedPkcs8( password, - pbeParameters, + pbeParameters.IterationCount, destination, out bytesWritten); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + + return CngPkcs8.TryExportEncryptedPkcs8PrivateKey( + this, + password, + pbeParameters, + destination, + out bytesWritten); } -#endif } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.SignVerify.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.SignVerify.cs index 0d121937d9658..8ecfd35843706 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.SignVerify.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.SignVerify.cs @@ -11,10 +11,6 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDsaImplementation - { -#endif public sealed partial class ECDsaCng : ECDsa { /// @@ -45,7 +41,6 @@ public override byte[] SignHash(byte[] hash) } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS public override bool TrySignHash(ReadOnlySpan source, Span destination, out int bytesWritten) { return TrySignHashCore( @@ -61,11 +56,6 @@ protected override unsafe bool TrySignHashCore( DSASignatureFormat signatureFormat, out int bytesWritten) { -#else - public override unsafe bool TrySignHash(ReadOnlySpan source, Span destination, out int bytesWritten) - { - ReadOnlySpan hash = source; -#endif using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { if (!keyHandle.TrySignHash(hash, destination, AsymmetricPaddingMode.None, null, out bytesWritten)) @@ -75,7 +65,6 @@ public override unsafe bool TrySignHash(ReadOnlySpan source, Span de } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { return true; @@ -93,9 +82,6 @@ public override unsafe bool TrySignHash(ReadOnlySpan source, Span de destination.Slice(0, bytesWritten), destination, out bytesWritten); -#else - return true; -#endif } /// @@ -108,14 +94,9 @@ public override bool VerifyHash(byte[] hash, byte[] signature) if (signature == null) throw new ArgumentNullException(nameof(signature)); -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS return VerifyHashCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); -#else - return VerifyHash((ReadOnlySpan)hash, (ReadOnlySpan)signature); -#endif } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) => VerifyHashCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); @@ -123,16 +104,12 @@ protected override bool VerifyHashCore( ReadOnlySpan hash, ReadOnlySpan signature, DSASignatureFormat signatureFormat) -#else - public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) -#endif { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature); } -#endif + using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { unsafe @@ -142,7 +119,4 @@ public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan sign } } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.cs index 4a6c655fb82e7..082608c735dc3 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaCng.cs @@ -1,95 +1,90 @@ // 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 static Internal.NativeCrypto.BCryptNative; +using System.Runtime.Versioning; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDsaImplementation + public sealed partial class ECDsaCng : ECDsa { -#endif - public sealed partial class ECDsaCng : ECDsa + /// + /// Create an ECDsaCng algorithm with a named curve. + /// + /// The representing the curve. + /// if is null. + /// if does not contain an Oid with a FriendlyName. + [SupportedOSPlatform("windows")] + public ECDsaCng(ECCurve curve) { - /// - /// Create an ECDsaCng algorithm with a named curve. - /// - /// The representing the curve. - /// if is null. - /// if does not contain an Oid with a FriendlyName. - public ECDsaCng(ECCurve curve) - { - // Specified curves generate the key immediately - GenerateKey(curve); - } + // Specified curves generate the key immediately + GenerateKey(curve); + } - /// - /// Create an ECDsaCng algorithm with a random 521 bit key pair. - /// - public ECDsaCng() - : this(521) - { - } + /// + /// Create an ECDsaCng algorithm with a random 521 bit key pair. + /// + [SupportedOSPlatform("windows")] + public ECDsaCng() + : this(521) + { + } - /// - /// Creates a new ECDsaCng object that will use a randomly generated key of the specified size. - /// - /// Size of the key to generate, in bits. - /// if is not valid - public ECDsaCng(int keySize) + /// + /// Creates a new ECDsaCng object that will use a randomly generated key of the specified size. + /// + /// Size of the key to generate, in bits. + /// if is not valid + [SupportedOSPlatform("windows")] + public ECDsaCng(int keySize) + { + KeySize = keySize; + } + + public override int KeySize + { + get { - KeySize = keySize; + return base.KeySize; } - - public override int KeySize + set { - get + if (KeySize == value) { - return base.KeySize; + return; } - set - { - if (KeySize == value) - { - return; - } - // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key - base.KeySize = value; + // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key + base.KeySize = value; - DisposeKey(); + DisposeKey(); - // Key will be lazily re-created - } + // Key will be lazily re-created } + } - /// - /// Set the KeySize without validating against LegalKeySizes. - /// - /// The value to set the KeySize to. - private void ForceSetKeySize(int newKeySize) - { - // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle - // it could be outside of the bounds that we currently represent as "legal key sizes". - // Since that is our view into the underlying component it can be detached from the - // component's understanding. If it said it has opened a key, and this is the size, trust it. - KeySizeValue = newKeySize; - } + /// + /// Set the KeySize without validating against LegalKeySizes. + /// + /// The value to set the KeySize to. + private void ForceSetKeySize(int newKeySize) + { + // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle + // it could be outside of the bounds that we currently represent as "legal key sizes". + // Since that is our view into the underlying component it can be detached from the + // component's understanding. If it said it has opened a key, and this is the size, trust it. + KeySizeValue = newKeySize; + } - public override KeySizes[] LegalKeySizes + public override KeySizes[] LegalKeySizes + { + get { - get - { - // Return the three sizes that can be explicitly set (for backwards compatibility) - return new[] { - new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), - new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), - }; - } + // Return the three sizes that can be explicitly set (for backwards compatibility) + return new[] { + new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), + new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), + }; } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs index c56d3f4affa78..898fe32d37dc5 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs @@ -3,369 +3,356 @@ using System.Diagnostics; using System.IO; +using System.Runtime.Versioning; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class ECDsaImplementation + public sealed partial class ECDsaOpenSsl : ECDsa { -#endif - public sealed partial class ECDsaOpenSsl : ECDsa + // secp521r1 maxes out at 139 bytes, so 256 should always be enough + private const int SignatureStackBufSize = 256; + + private ECOpenSsl _key; + + /// + /// Create an ECDsaOpenSsl algorithm with a named curve. + /// + /// The representing the curve. + /// if is null. + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(ECCurve curve) { - // secp521r1 maxes out at 139 bytes, so 256 should always be enough - private const int SignatureStackBufSize = 256; + ThrowIfNotSupported(); + _key = new ECOpenSsl(curve); + ForceSetKeySize(_key.KeySize); + } - private ECOpenSsl _key; + /// + /// Create an ECDsaOpenSsl algorithm with a random 521 bit key pair. + /// + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl() + : this(521) + { + } - /// - /// Create an ECDsaOpenSsl algorithm with a named curve. - /// - /// The representing the curve. - /// if is null. - public ECDsaOpenSsl(ECCurve curve) - { - ThrowIfNotSupported(); - _key = new ECOpenSsl(curve); - ForceSetKeySize(_key.KeySize); - } + /// + /// Creates a new ECDsaOpenSsl object that will use a randomly generated key of the specified size. + /// + /// Size of the key to generate, in bits. + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(int keySize) + { + ThrowIfNotSupported(); + // Use the base setter to get the validation and field assignment without the + // side effect of dereferencing _key. + base.KeySize = keySize; + _key = new ECOpenSsl(this); + } - /// - /// Create an ECDsaOpenSsl algorithm with a random 521 bit key pair. - /// - public ECDsaOpenSsl() - : this(521) - { - } + /// + /// Set the KeySize without validating against LegalKeySizes. + /// + /// The value to set the KeySize to. + private void ForceSetKeySize(int newKeySize) + { + // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle + // it could be outside of the bounds that we currently represent as "legal key sizes". + // Since that is our view into the underlying component it can be detached from the + // component's understanding. If it said it has opened a key, and this is the size, trust it. + KeySizeValue = newKeySize; + } - /// - /// Creates a new ECDsaOpenSsl object that will use a randomly generated key of the specified size. - /// - /// Size of the key to generate, in bits. - public ECDsaOpenSsl(int keySize) + public override KeySizes[] LegalKeySizes + { + get { - ThrowIfNotSupported(); - // Use the base setter to get the validation and field assignment without the - // side effect of dereferencing _key. - base.KeySize = keySize; - _key = new ECOpenSsl(this); + // Return the three sizes that can be explicitly set (for backwards compatibility) + return new[] { + new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), + new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), + }; } + } - /// - /// Set the KeySize without validating against LegalKeySizes. - /// - /// The value to set the KeySize to. - private void ForceSetKeySize(int newKeySize) - { - // In the event that a key was loaded via ImportParameters, curve name, or an IntPtr/SafeHandle - // it could be outside of the bounds that we currently represent as "legal key sizes". - // Since that is our view into the underlying component it can be detached from the - // component's understanding. If it said it has opened a key, and this is the size, trust it. - KeySizeValue = newKeySize; - } + public override byte[] SignHash(byte[] hash) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); - public override KeySizes[] LegalKeySizes - { - get - { - // Return the three sizes that can be explicitly set (for backwards compatibility) - return new[] { - new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), - new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), - }; - } - } + ThrowIfDisposed(); + SafeEcKeyHandle key = _key.Value; + int signatureLength = Interop.Crypto.EcDsaSize(key); - public override byte[] SignHash(byte[] hash) - { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); + Span signDestination = stackalloc byte[SignatureStackBufSize]; + ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); - ThrowIfDisposed(); - SafeEcKeyHandle key = _key.Value; - int signatureLength = Interop.Crypto.EcDsaSize(key); + byte[] converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize); + return converted; + } - Span signDestination = stackalloc byte[SignatureStackBufSize]; - ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); + public override bool TrySignHash(ReadOnlySpan hash, Span destination, out int bytesWritten) + { + return TrySignHashCore( + hash, + destination, + DSASignatureFormat.IeeeP1363FixedFieldConcatenation, + out bytesWritten); + } - byte[] converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize); - return converted; - } + protected override bool TrySignHashCore( + ReadOnlySpan hash, + Span destination, + DSASignatureFormat signatureFormat, + out int bytesWritten) + { + ThrowIfDisposed(); + SafeEcKeyHandle key = _key.Value; -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public override bool TrySignHash(ReadOnlySpan hash, Span destination, out int bytesWritten) - { - return TrySignHashCore( - hash, - destination, - DSASignatureFormat.IeeeP1363FixedFieldConcatenation, - out bytesWritten); - } + int signatureLength = Interop.Crypto.EcDsaSize(key); + Span signDestination = stackalloc byte[SignatureStackBufSize]; - protected override bool TrySignHashCore( - ReadOnlySpan hash, - Span destination, - DSASignatureFormat signatureFormat, - out int bytesWritten) -#else - public override bool TrySignHash(ReadOnlySpan hash, Span destination, out int bytesWritten) -#endif + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { - ThrowIfDisposed(); - SafeEcKeyHandle key = _key.Value; - - int signatureLength = Interop.Crypto.EcDsaSize(key); - Span signDestination = stackalloc byte[SignatureStackBufSize]; + int encodedSize = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) - { -#endif - int encodedSize = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); - - if (destination.Length < encodedSize) - { - bytesWritten = 0; - return false; - } - - ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); - bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize, destination); - Debug.Assert(bytesWritten == encodedSize); - return true; -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } - else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) - { - if (destination.Length >= signatureLength) - { - signDestination = destination; - } - else if (signatureLength > signDestination.Length) - { - Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); - bytesWritten = 0; - return false; - } - - ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); - - if (destination == signDestination) - { - bytesWritten = derSignature.Length; - return true; - } - - return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten); - } - else + if (destination.Length < encodedSize) { - throw new ArgumentOutOfRangeException(nameof(signatureFormat)); + bytesWritten = 0; + return false; } -#endif - } - private static ReadOnlySpan SignHash( - ReadOnlySpan hash, - Span destination, - int signatureLength, - SafeEcKeyHandle key) + ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); + bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize, destination); + Debug.Assert(bytesWritten == encodedSize); + return true; + } + else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) { - if (signatureLength > destination.Length) + if (destination.Length >= signatureLength) + { + signDestination = destination; + } + else if (signatureLength > signDestination.Length) { Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); - destination = new byte[signatureLength]; + bytesWritten = 0; + return false; } - if (!Interop.Crypto.EcDsaSign(hash, destination, out int actualLength, key)) + ReadOnlySpan derSignature = SignHash(hash, signDestination, signatureLength, key); + + if (destination == signDestination) { - throw Interop.Crypto.CreateOpenSslCryptographicException(); + bytesWritten = derSignature.Length; + return true; } - Debug.Assert( - actualLength <= signatureLength, - "ECDSA_sign reported an unexpected signature size", - "ECDSA_sign reported signatureSize was {0}, when <= {1} was expected", - actualLength, - signatureLength); - - return destination.Slice(0, actualLength); + return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten); } - - public override bool VerifyHash(byte[] hash, byte[] signature) + else { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); + throw new ArgumentOutOfRangeException(nameof(signatureFormat)); + } + } - return VerifyHash((ReadOnlySpan)hash, (ReadOnlySpan)signature); + private static ReadOnlySpan SignHash( + ReadOnlySpan hash, + Span destination, + int signatureLength, + SafeEcKeyHandle key) + { + if (signatureLength > destination.Length) + { + Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); + destination = new byte[signatureLength]; } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) => - VerifyHashCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); - - protected override bool VerifyHashCore( - ReadOnlySpan hash, - ReadOnlySpan signature, - DSASignatureFormat signatureFormat) -#else - public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) -#endif + if (!Interop.Crypto.EcDsaSign(hash, destination, out int actualLength, key)) { - ThrowIfDisposed(); + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } - Span derSignature = stackalloc byte[SignatureStackBufSize]; - ReadOnlySpan toVerify = derSignature; + Debug.Assert( + actualLength <= signatureLength, + "ECDSA_sign reported an unexpected signature size", + "ECDSA_sign reported signatureSize was {0}, when <= {1} was expected", + actualLength, + signatureLength); -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) - { -#endif - // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even - // when they would have leading zeroes. If it's the correct size, then we need to encode it from - // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. - int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); - if (signature.Length != expectedBytes) - { - // The input isn't of the right length, so we can't sensibly re-encode it. - return false; - } - - if (AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer(signature, derSignature, out int derSize)) - { - toVerify = derSignature.Slice(0, derSize); - } - else - { - toVerify = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); - } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } - else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) - { - toVerify = signature; - } - else - { - Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); - throw new CryptographicException( - SR.Cryptography_UnknownSignatureFormat, - signatureFormat.ToString()); - } -#endif + return destination.Slice(0, actualLength); + } - SafeEcKeyHandle key = _key.Value; - int verifyResult = Interop.Crypto.EcDsaVerify(hash, toVerify, key); - return verifyResult == 1; - } + public override bool VerifyHash(byte[] hash, byte[] signature) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); + if (signature == null) + throw new ArgumentNullException(nameof(signature)); - protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => - AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + return VerifyHash((ReadOnlySpan)hash, (ReadOnlySpan)signature); + } + + public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) => + VerifyHashCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); - protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => - AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + protected override bool VerifyHashCore( + ReadOnlySpan hash, + ReadOnlySpan signature, + DSASignatureFormat signatureFormat) + { + ThrowIfDisposed(); - protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => - AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten); + Span derSignature = stackalloc byte[SignatureStackBufSize]; + ReadOnlySpan toVerify = derSignature; - protected override void Dispose(bool disposing) + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { - if (disposing) + // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even + // when they would have leading zeroes. If it's the correct size, then we need to encode it from + // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. + int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); + if (signature.Length != expectedBytes) { - _key?.Dispose(); - _key = null!; + // The input isn't of the right length, so we can't sensibly re-encode it. + return false; } - base.Dispose(disposing); - } - - public override int KeySize - { - get + if (AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer(signature, derSignature, out int derSize)) { - return base.KeySize; + toVerify = derSignature.Slice(0, derSize); } - set + else { - if (KeySize == value) - return; - - // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key - base.KeySize = value; - - ThrowIfDisposed(); - _key.Dispose(); - _key = new ECOpenSsl(this); + toVerify = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); } } - - public override void GenerateKey(ECCurve curve) + else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) { - ThrowIfDisposed(); - _key.GenerateKey(curve); - - // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere - // with the already loaded key. - ForceSetKeySize(_key.KeySize); + toVerify = signature; } - - public override void ImportParameters(ECParameters parameters) + else { - ThrowIfDisposed(); - _key.ImportParameters(parameters); - ForceSetKeySize(_key.KeySize); + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); } - public override ECParameters ExportExplicitParameters(bool includePrivateParameters) - { - ThrowIfDisposed(); - return ECOpenSsl.ExportExplicitParameters(_key.Value, includePrivateParameters); - } + SafeEcKeyHandle key = _key.Value; + int verifyResult = Interop.Crypto.EcDsaVerify(hash, toVerify, key); + return verifyResult == 1; + } + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); - public override ECParameters ExportParameters(bool includePrivateParameters) + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + + protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => + AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten); + + protected override void Dispose(bool disposing) + { + if (disposing) { - ThrowIfDisposed(); - return ECOpenSsl.ExportParameters(_key.Value, includePrivateParameters); + _key?.Dispose(); + _key = null!; } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) + base.Dispose(disposing); + } + + public override int KeySize + { + get { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + return base.KeySize; } - - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) + set { + if (KeySize == value) + return; + + // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key + base.KeySize = value; + ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + _key.Dispose(); + _key = new ECOpenSsl(this); } + } + + public override void GenerateKey(ECCurve curve) + { + ThrowIfDisposed(); + _key.GenerateKey(curve); + + // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere + // with the already loaded key. + ForceSetKeySize(_key.KeySize); + } + + public override void ImportParameters(ECParameters parameters) + { + ThrowIfDisposed(); + _key.ImportParameters(parameters); + ForceSetKeySize(_key.KeySize); + } + + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + { + ThrowIfDisposed(); + return ECOpenSsl.ExportExplicitParameters(_key.Value, includePrivateParameters); + } + + public override ECParameters ExportParameters(bool includePrivateParameters) + { + ThrowIfDisposed(); + return ECOpenSsl.ExportParameters(_key.Value, includePrivateParameters); + } - private void ThrowIfDisposed() + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } + + private void ThrowIfDisposed() + { + if (_key == null) { - if (_key == null) - { - throw new ObjectDisposedException( -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - nameof(ECDsa) -#else - nameof(ECDsaOpenSsl) -#endif - ); - } + throw new ObjectDisposedException(nameof(ECDsaOpenSsl)); } - - static partial void ThrowIfNotSupported(); } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS + + static partial void ThrowIfNotSupported(); } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaSecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaSecurityTransforms.cs index c1f9852191a4b..0f4bcb418c89b 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaSecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaSecurityTransforms.cs @@ -7,248 +7,213 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class ECDsa : ECAlgorithm + internal static partial class ECDsaImplementation { - /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. - /// - public static new partial ECDsa Create() + public sealed partial class ECDsaSecurityTransforms : ECDsa { - return new ECDsaImplementation.ECDsaSecurityTransforms(); - } + private readonly EccSecurityTransforms _ecc = new EccSecurityTransforms(nameof(ECDsa)); - /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. - /// - /// - /// The representing the elliptic curve. - /// - public static partial ECDsa Create(ECCurve curve) - { - ECDsa ecdsa = Create(); - ecdsa.GenerateKey(curve); - return ecdsa; - } + public ECDsaSecurityTransforms() + { + base.KeySize = 521; + } - /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. - /// - /// - /// The representing the elliptic curve parameters. - /// - public static partial ECDsa Create(ECParameters parameters) - { - ECDsa ecdsa = Create(); - ecdsa.ImportParameters(parameters); - return ecdsa; - } -#endif - internal static partial class ECDsaImplementation - { - public sealed partial class ECDsaSecurityTransforms : ECDsa + internal ECDsaSecurityTransforms(SafeSecKeyRefHandle publicKey) + { + KeySizeValue = _ecc.SetKeyAndGetSize(SecKeyPair.PublicOnly(publicKey)); + } + + internal ECDsaSecurityTransforms(SafeSecKeyRefHandle publicKey, SafeSecKeyRefHandle privateKey) { - private readonly EccSecurityTransforms _ecc = new EccSecurityTransforms(nameof(ECDsa)); + KeySizeValue = _ecc.SetKeyAndGetSize(SecKeyPair.PublicPrivatePair(publicKey, privateKey)); + } - public ECDsaSecurityTransforms() + public override KeySizes[] LegalKeySizes + { + get { - base.KeySize = 521; + // Return the three sizes that can be explicitly set (for backwards compatibility) + return new[] { + new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), + new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), + }; } + } - internal ECDsaSecurityTransforms(SafeSecKeyRefHandle publicKey) + public override int KeySize + { + get { - KeySizeValue = _ecc.SetKeyAndGetSize(SecKeyPair.PublicOnly(publicKey)); + return base.KeySize; } - - internal ECDsaSecurityTransforms(SafeSecKeyRefHandle publicKey, SafeSecKeyRefHandle privateKey) + set { - KeySizeValue = _ecc.SetKeyAndGetSize(SecKeyPair.PublicPrivatePair(publicKey, privateKey)); + if (KeySize == value) + return; + + // Set the KeySize before freeing the key so that an invalid value doesn't throw away the key + base.KeySize = value; + _ecc.DisposeKey(); } + } - public override KeySizes[] LegalKeySizes + public override byte[] SignHash(byte[] hash) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); + + SecKeyPair keys = GetKeys(); + + if (keys.PrivateKey == null) { - get - { - // Return the three sizes that can be explicitly set (for backwards compatibility) - return new[] { - new KeySizes(minSize: 256, maxSize: 384, skipSize: 128), - new KeySizes(minSize: 521, maxSize: 521, skipSize: 0), - }; - } + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } - public override int KeySize + byte[] derFormatSignature = Interop.AppleCrypto.CreateSignature( + keys.PrivateKey, + hash, + Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, + Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); + byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( + derFormatSignature.AsSpan(0, derFormatSignature.Length), + KeySize); + + return ieeeFormatSignature; + } + + public override bool TrySignHash(ReadOnlySpan source, Span destination, out int bytesWritten) + { + SecKeyPair keys = GetKeys(); + if (keys.PrivateKey == null) { - get - { - return base.KeySize; - } - set - { - if (KeySize == value) - return; - - // Set the KeySize before freeing the key so that an invalid value doesn't throw away the key - base.KeySize = value; - _ecc.DisposeKey(); - } + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } - public override byte[] SignHash(byte[] hash) + byte[] derFormatSignature = Interop.AppleCrypto.CreateSignature( + keys.PrivateKey, + source, + Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, + Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); + byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( + derFormatSignature.AsSpan(0, derFormatSignature.Length), + KeySize); + + if (ieeeFormatSignature.Length <= destination.Length) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - - SecKeyPair keys = GetKeys(); - - if (keys.PrivateKey == null) - { - throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); - } - - byte[] derFormatSignature = Interop.AppleCrypto.CreateSignature( - keys.PrivateKey, - hash, - Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, - Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); - byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( - derFormatSignature.AsSpan(0, derFormatSignature.Length), - KeySize); - - return ieeeFormatSignature; + new ReadOnlySpan(ieeeFormatSignature).CopyTo(destination); + bytesWritten = ieeeFormatSignature.Length; + return true; } - - public override bool TrySignHash(ReadOnlySpan source, Span destination, out int bytesWritten) + else { - SecKeyPair keys = GetKeys(); - if (keys.PrivateKey == null) - { - throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); - } - - byte[] derFormatSignature = Interop.AppleCrypto.CreateSignature( - keys.PrivateKey, - source, - Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, - Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); - byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( - derFormatSignature.AsSpan(0, derFormatSignature.Length), - KeySize); - - if (ieeeFormatSignature.Length <= destination.Length) - { - new ReadOnlySpan(ieeeFormatSignature).CopyTo(destination); - bytesWritten = ieeeFormatSignature.Length; - return true; - } - else - { - bytesWritten = 0; - return false; - } + bytesWritten = 0; + return false; } + } - public override bool VerifyHash(byte[] hash, byte[] signature) - { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); + public override bool VerifyHash(byte[] hash, byte[] signature) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); + if (signature == null) + throw new ArgumentNullException(nameof(signature)); - return VerifyHash((ReadOnlySpan)hash, (ReadOnlySpan)signature); - } + return VerifyHash((ReadOnlySpan)hash, (ReadOnlySpan)signature); + } - public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) + public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) + { + ThrowIfDisposed(); + + // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even + // when they would have leading zeroes. If it's the correct size, then we need to encode it from + // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. + int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); + if (signature.Length != expectedBytes) { - ThrowIfDisposed(); - - // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even - // when they would have leading zeroes. If it's the correct size, then we need to encode it from - // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. - int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); - if (signature.Length != expectedBytes) - { - // The input isn't of the right length, so we can't sensibly re-encode it. - return false; - } - - return Interop.AppleCrypto.VerifySignature( - GetKeys().PublicKey, - hash, - AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature), - Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, - Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); + // The input isn't of the right length, so we can't sensibly re-encode it. + return false; } - protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => - AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + return Interop.AppleCrypto.VerifySignature( + GetKeys().PublicKey, + hash, + AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature), + Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, + Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); + } + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); - protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => - AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); - protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => - AsymmetricAlgorithmHelpers.TryHashData(source, destination, hashAlgorithm, out bytesWritten); + protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => + AsymmetricAlgorithmHelpers.TryHashData(source, destination, hashAlgorithm, out bytesWritten); - private void ThrowIfDisposed() + private void ThrowIfDisposed() + { + _ecc.ThrowIfDisposed(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) { - _ecc.ThrowIfDisposed(); + _ecc.Dispose(); } - protected override void Dispose(bool disposing) - { - if (disposing) - { - _ecc.Dispose(); - } + base.Dispose(disposing); + } - base.Dispose(disposing); - } + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) + { + throw new PlatformNotSupportedException(SR.Cryptography_ECC_NamedCurvesOnly); + } - public override ECParameters ExportExplicitParameters(bool includePrivateParameters) - { - throw new PlatformNotSupportedException(SR.Cryptography_ECC_NamedCurvesOnly); - } + public override ECParameters ExportParameters(bool includePrivateParameters) + { + return _ecc.ExportParameters(includePrivateParameters, KeySize); + } - public override ECParameters ExportParameters(bool includePrivateParameters) - { - return _ecc.ExportParameters(includePrivateParameters, KeySize); - } + internal bool TryExportDataKeyParameters(bool includePrivateParameters, ref ECParameters ecParameters) + { + return _ecc.TryExportDataKeyParameters(includePrivateParameters, KeySize, ref ecParameters); + } - public override void ImportParameters(ECParameters parameters) - { - KeySizeValue = _ecc.ImportParameters(parameters); - } + public override void ImportParameters(ECParameters parameters) + { + KeySizeValue = _ecc.ImportParameters(parameters); + } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan passwordBytes, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } - public override void ImportEncryptedPkcs8PrivateKey( - ReadOnlySpan password, - ReadOnlySpan source, - out int bytesRead) - { - ThrowIfDisposed(); - base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); - } + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } - public override void GenerateKey(ECCurve curve) - { - KeySizeValue = _ecc.GenerateKey(curve); - } + public override void GenerateKey(ECCurve curve) + { + KeySizeValue = _ecc.GenerateKey(curve); + } - internal SecKeyPair GetKeys() - { - return _ecc.GetOrGenerateKeys(KeySize); - } + internal SecKeyPair GetKeys() + { + return _ecc.GetOrGenerateKeys(KeySize); } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/EccSecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/EccSecurityTransforms.cs index 6d16c38f68baa..9c73fca281ca7 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/EccSecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/EccSecurityTransforms.cs @@ -119,7 +119,32 @@ private void SetKey(SecKeyPair keyPair) internal ECParameters ExportParameters(bool includePrivateParameters, int keySizeInBits) { SecKeyPair keys = GetOrGenerateKeys(keySizeInBits); + ECParameters key = default; + if (!TryExportDataKeyParameters(keys, includePrivateParameters, ref key)) + { + return ExportParametersFromLegacyKey(keys, includePrivateParameters); + } + + return key; + } + + internal bool TryExportDataKeyParameters( + bool includePrivateParameters, + int keySizeInBits, + ref ECParameters ecParameters) + { + return TryExportDataKeyParameters( + GetOrGenerateKeys(keySizeInBits), + includePrivateParameters, + ref ecParameters); + } + + private static bool TryExportDataKeyParameters( + SecKeyPair keys, + bool includePrivateParameters, + ref ECParameters ecParameters) + { if (includePrivateParameters && keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); @@ -131,7 +156,7 @@ internal ECParameters ExportParameters(bool includePrivateParameters, int keySiz if (!gotKeyBlob) { - return ExportParametersFromLegacyKey(keys, includePrivateParameters); + return false; } try @@ -139,19 +164,19 @@ internal ECParameters ExportParameters(bool includePrivateParameters, int keySiz AsymmetricAlgorithmHelpers.DecodeFromUncompressedAnsiX963Key( keyBlob, includePrivateParameters, - out ECParameters key); + out ecParameters); switch (GetKeySize(keys)) { - case 256: key.Curve = ECCurve.NamedCurves.nistP256; break; - case 384: key.Curve = ECCurve.NamedCurves.nistP384; break; - case 521: key.Curve = ECCurve.NamedCurves.nistP521; break; + case 256: ecParameters.Curve = ECCurve.NamedCurves.nistP256; break; + case 384: ecParameters.Curve = ECCurve.NamedCurves.nistP384; break; + case 521: ecParameters.Curve = ECCurve.NamedCurves.nistP521; break; default: Debug.Fail("Unsupported curve"); throw new CryptographicException(); } - return key; + return true; } finally { diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs index c78de73548035..86d98f5014f6c 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs @@ -678,12 +678,9 @@ protected override bool TryHashData(ReadOnlySpan data, Span destinat public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (!TrySignHash( hash, @@ -708,14 +705,8 @@ public override bool TrySignHash( RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); bool ret = TrySignHash( hash, @@ -817,14 +808,8 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (padding != RSASignaturePadding.Pkcs1 && padding != RSASignaturePadding.Pss) { throw PaddingModeNotSupported(); @@ -894,9 +879,6 @@ public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan sign private static Exception PaddingModeNotSupported() => new CryptographicException(SR.Cryptography_InvalidPaddingMode); - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSACng.EncryptDecrypt.cs b/src/libraries/Common/src/System/Security/Cryptography/RSACng.EncryptDecrypt.cs index ace52b302c552..856cf4b6f2aa2 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSACng.EncryptDecrypt.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSACng.EncryptDecrypt.cs @@ -11,10 +11,6 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class RSAImplementation - { -#endif public sealed partial class RSACng : RSA { private const int Pkcs1PaddingOverhead = 11; @@ -319,7 +315,4 @@ private static unsafe ErrorCode EncryptOrDecrypt( return errorCode; } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSACng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/RSACng.ImportExport.cs index 67328cb35e8a7..66206156ece89 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSACng.ImportExport.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSACng.ImportExport.cs @@ -11,10 +11,6 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class RSAImplementation - { -#endif public sealed partial class RSACng : RSA { /// @@ -372,7 +368,4 @@ private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includeP } } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs b/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs index 82709832cd88d..947a73416d7d3 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs @@ -13,10 +13,6 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal static partial class RSAImplementation - { -#endif public sealed partial class RSACng : RSA { private static readonly ConcurrentDictionary s_hashSizes = @@ -52,14 +48,9 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS } string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + + ArgumentNullException.ThrowIfNull(padding); if (hash.Length != GetHashSizeInBytes(hashAlgorithm)) { @@ -99,14 +90,8 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS public override unsafe bool TrySignHash(ReadOnlySpan hash, Span destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { @@ -159,14 +144,8 @@ public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName public override unsafe bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { @@ -199,7 +178,4 @@ public override unsafe bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan /// Create an RSACng algorithm with a random 2048 bit key pair. /// + [SupportedOSPlatform("windows")] public RSACng() : this(2048) { @@ -27,6 +25,7 @@ public RSACng() /// /// Size of the key to generate, in bits. /// if is not valid + [SupportedOSPlatform("windows")] public RSACng(int keySize) { // Set the property directly so that it gets validated against LegalKeySizes. @@ -74,7 +73,4 @@ private void ForceSetKeySize(int newKeySize) KeySizeValue = newKeySize; } } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs index 149e240893039..e87f36e6a0d9d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs @@ -5,32 +5,34 @@ using System.Diagnostics; using System.Formats.Asn1; using System.IO; +using System.Runtime.Versioning; using System.Security.Cryptography.Asn1; using Microsoft.Win32.SafeHandles; using Internal.Cryptography; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class RSA : AsymmetricAlgorithm - { - public static new partial RSA Create() => new RSAImplementation.RSAOpenSsl(); - } - - internal static partial class RSAImplementation - { -#endif public sealed partial class RSAOpenSsl : RSA { private const int BitsPerByte = 8; private Lazy _key; + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public RSAOpenSsl() : this(2048) { } + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public RSAOpenSsl(int keySize) { ThrowIfNotSupported(); @@ -710,13 +712,7 @@ private void ThrowIfDisposed() { if (_key == null) { - throw new ObjectDisposedException( -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - nameof(RSA) -#else - nameof(RSAOpenSsl) -#endif - ); + throw new ObjectDisposedException(nameof(RSAOpenSsl)); } } @@ -750,12 +746,9 @@ protected override bool TryHashData(ReadOnlySpan data, Span destinat public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (!TrySignHash( hash, @@ -780,14 +773,8 @@ public override bool TrySignHash( RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); bool ret = TrySignHash( hash, @@ -860,11 +847,7 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ValidatePadding(padding); IntPtr digestAlgorithm = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithm.Name); @@ -951,11 +934,5 @@ private static void ValidatePadding(RSASignaturePadding padding) private static Exception PaddingModeNotSupported() => new CryptographicException(SR.Cryptography_InvalidPaddingMode); - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); - } -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } -#endif } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs index 7bce2648d443a..c449167fde4f3 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Formats.Asn1; using System.IO; -using System.Numerics; using System.Runtime.InteropServices; using System.Security.Cryptography.Apple; using System.Security.Cryptography.Asn1; @@ -13,16 +12,6 @@ namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class RSA : AsymmetricAlgorithm - { - public static new partial RSA Create() - { - return new RSAImplementation.RSASecurityTransforms(); - } - } -#endif - internal static partial class RSAImplementation { public sealed partial class RSASecurityTransforms : RSA @@ -386,12 +375,9 @@ private bool TryDecrypt( public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -443,14 +429,8 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS public override bool TrySignHash(ReadOnlySpan hash, Span destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -550,14 +530,8 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -795,8 +769,5 @@ private static bool HasConsistentPrivateKey(in RSAParameters parameters) return true; } } - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } } diff --git a/src/libraries/Common/tests/Resources/Strings.resx b/src/libraries/Common/tests/Resources/Strings.resx index 1673683936a79..7d48d2b4fe49d 100644 --- a/src/libraries/Common/tests/Resources/Strings.resx +++ b/src/libraries/Common/tests/Resources/Strings.resx @@ -156,9 +156,6 @@ IO_PathTooLong_Path {0} - - Arg_InvalidSearchPattern {0} - The argv[0] argument cannot include a double quote. @@ -168,9 +165,6 @@ HPACK integer exceeds limits or has an overlong encoding. - - Failed to HPACK encode the headers. - Huffman-coded literal string failed to decode. @@ -201,9 +195,6 @@ Connection aborted by peer ({0}). - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. diff --git a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs index 7dc9519665c58..792e5387fd04a 100644 --- a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs +++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs @@ -711,7 +711,6 @@ public abstract class StandaloneStreamConformanceTests : StreamConformanceTests } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ArgumentValidation_ThrowsExpectedException() { await foreach (Stream? stream in GetStreamsForValidation()) @@ -725,7 +724,6 @@ public virtual async Task ArgumentValidation_ThrowsExpectedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Disposed_ThrowsObjectDisposedException() { await foreach (Stream? stream in GetStreamsForValidation()) @@ -815,7 +813,6 @@ public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Write_DataReadFromDesiredOffset(ReadWriteMode mode) { using Stream? stream = await CreateReadWriteStream(); @@ -1599,7 +1596,6 @@ protected static bool Bidirectional(StreamPair streams) => streams.Stream2.CanRead && streams.Stream2.CanWrite; [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ArgumentValidation_ThrowsExpectedException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1611,7 +1607,6 @@ public virtual async Task ArgumentValidation_ThrowsExpectedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Disposed_ThrowsObjectDisposedException() { StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1624,7 +1619,6 @@ public virtual async Task Disposed_ThrowsObjectDisposedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWriteAsync_PrecanceledOperations_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1636,7 +1630,6 @@ public virtual async Task ReadWriteAsync_PrecanceledOperations_ThrowsCancellatio } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_CancelPendingTask_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1646,7 +1639,6 @@ public virtual async Task ReadAsync_CancelPendingTask_ThrowsCancellationExceptio } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_CancelPendingValueTask_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1656,7 +1648,6 @@ public virtual async Task ReadAsync_CancelPendingValueTask_ThrowsCancellationExc } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWriteByte_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1729,7 +1720,6 @@ public virtual async Task ReadWrite_Success_Large(ReadWriteMode mode, int writeS [Theory] [MemberData(nameof(ReadWrite_Success_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_Success(ReadWriteMode mode, int writeSize, bool startWithFlush) { foreach (CancellationToken nonCanceledToken in new[] { CancellationToken.None, new CancellationTokenSource().Token }) @@ -1786,7 +1776,6 @@ public virtual async Task ReadWrite_Success(ReadWriteMode mode, int writeSize, b [Theory] [MemberData(nameof(ReadWrite_Modes))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_MessagesSmallerThanReadBuffer_Success(ReadWriteMode mode) { if (!FlushGuaranteesAllDataWritten) @@ -1835,7 +1824,6 @@ public virtual async Task ReadWrite_MessagesSmallerThanReadBuffer_Success(ReadWr [Theory] [MemberData(nameof(AllReadWriteModesAndValue), false)] [MemberData(nameof(AllReadWriteModesAndValue), true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Read_Eof_Returns0(ReadWriteMode mode, bool dataAvailableFirst) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1874,7 +1862,6 @@ public virtual async Task Read_Eof_Returns0(ReadWriteMode mode, bool dataAvailab [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1904,7 +1891,6 @@ public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Write_DataReadFromDesiredOffset(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2003,7 +1989,6 @@ public static IEnumerable ReadAsync_ContinuesOnCurrentContextIfDesired [Theory] [MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx @@ -2086,7 +2071,6 @@ public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDe [Theory] [MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_ContinuesOnCurrentTaskSchedulerIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx @@ -2176,7 +2160,6 @@ await Task.Factory.StartNew(() => [InlineData(ReadWriteMode.AsyncMemory)] [InlineData(ReadWriteMode.SyncAPM)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ZeroByteRead_BlocksUntilDataAvailableOrNops(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2243,7 +2226,6 @@ public virtual async Task ZeroByteRead_BlocksUntilDataAvailableOrNops(ReadWriteM [InlineData(ReadWriteMode.AsyncMemory)] [InlineData(ReadWriteMode.SyncAPM)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ZeroByteWrite_OtherDataReceivedSuccessfully(ReadWriteMode mode) { byte[][] buffers = new[] { Array.Empty(), Encoding.UTF8.GetBytes("hello"), Array.Empty(), Encoding.UTF8.GetBytes("world") }; @@ -2297,7 +2279,6 @@ public virtual async Task ZeroByteWrite_OtherDataReceivedSuccessfully(ReadWriteM [Theory] [InlineData(false)] [InlineData(true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_CustomMemoryManager_Success(bool useAsync) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2418,7 +2399,6 @@ public virtual async Task CopyToAsync_AllDataCopied_Large(bool useAsync) => [Theory] [MemberData(nameof(CopyToAsync_AllDataCopied_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task CopyToAsync_AllDataCopied(int byteCount, bool useAsync) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2456,7 +2436,6 @@ await Task.WhenAll(Enumerable.Range(0, 20).Select(_ => Task.Run(async () => } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Timeout_Roundtrips() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2491,7 +2470,6 @@ public virtual async Task Timeout_Roundtrips() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadTimeout_Expires_Throws() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2626,7 +2604,6 @@ public virtual async Task ReadAsync_DuringReadAsync_ThrowsIfUnsupported() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Flush_ValidOnWriteableStreamWithNoData_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2641,7 +2618,6 @@ public virtual async Task Flush_ValidOnWriteableStreamWithNoData_Success() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Flush_ValidOnReadableStream_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2659,7 +2635,6 @@ public virtual async Task Flush_ValidOnReadableStream_Success() [InlineData(0)] [InlineData(1)] [InlineData(2)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Dispose_ClosesStream(int disposeMode) { if (!CansReturnFalseAfterDispose) diff --git a/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs b/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs index 2935ef6fd3f82..ba9e6b86b092a 100644 --- a/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs +++ b/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs @@ -320,7 +320,7 @@ IEnumerable> CtorFunctions() } else { - Assert.Equal(data2[i], (byte)0); + Assert.Equal((byte)0, data2[i]); } } }); diff --git a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs index 9a523ca701417..5407a6095cd0a 100644 --- a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs @@ -86,6 +86,17 @@ public void Close() CloseWebSocket(); } + public async Task WaitForCloseAsync(CancellationToken cancellationToken) + { + while (_websocket != null + ? _websocket.State != WebSocketState.Closed + : !(_socket.Poll(1, SelectMode.SelectRead) && _socket.Available == 0)) + { + cancellationToken.ThrowIfCancellationRequested(); + await Task.Delay(100); + } + } + public void Shutdown(SocketShutdown how) { _socket?.Shutdown(how); @@ -138,6 +149,9 @@ public abstract class GenericLoopbackConnection : IDisposable /// Waits for the client to signal cancellation. public abstract Task WaitForCancellationAsync(bool ignoreIncomingData = true); + /// Waits for the client to signal cancellation. + public abstract Task WaitForCloseAsync(CancellationToken cancellationToken); + /// Helper function to make it easier to convert old test with strings. public async Task SendResponseBodyAsync(string content, bool isFinal = true) { diff --git a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs index b3bb701e540f3..2329475728c67 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs @@ -984,5 +984,10 @@ public override async Task WaitForCancellationAsync(bool ignoreIncomingData = tr RstStreamFrame rstStreamFrame = Assert.IsType(frame); Assert.Equal((int)ProtocolErrors.CANCEL, rstStreamFrame.ErrorCode); } + + public override Task WaitForCloseAsync(CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs index ceb36e0bcbfb1..78c49a1aaee13 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Net.Http.Functional.Tests; using Xunit; +using System.Threading; namespace System.Net.Test.Common { @@ -305,6 +306,11 @@ public override async Task WaitForCancellationAsync(bool ignoreIncomingData = tr { await GetOpenRequest().WaitForCancellationAsync(ignoreIncomingData).ConfigureAwait(false); } + + public override Task WaitForCloseAsync(CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs index 7ae59fe98e54d..a363553ba598e 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs @@ -28,6 +28,7 @@ public HttpClientHandler_Cancellation_Test(ITestOutputHelper output) : base(outp [Theory] [InlineData(false, CancellationMode.Token)] [InlineData(true, CancellationMode.Token)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/36634", TestPlatforms.Browser)] // out of memory public async Task PostAsync_CancelDuringRequestContentSend_TaskCanceledQuickly(bool chunkedTransfer, CancellationMode mode) { if (LoopbackServerFactory.Version >= HttpVersion20.Value && chunkedTransfer) @@ -228,10 +229,21 @@ await LoopbackServerFactory.CreateServerAsync(async (server, url) => await connection.ReadRequestDataAsync(); await connection.SendResponseAsync(HttpStatusCode.OK, headers: headers, isFinal: false); await clientFinished.Task; + +#if TARGET_BROWSER + // make sure that the browser closed the connection + await connection.WaitForCloseAsync(CancellationToken.None); +#endif }); var req = new HttpRequestMessage(HttpMethod.Get, url) { Version = UseVersion }; req.Headers.ConnectionClose = connectionClose; + +#if TARGET_BROWSER + var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); + req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); +#endif + Task getResponse = client.SendAsync(TestAsync, req, HttpCompletionOption.ResponseHeadersRead, cts.Token); await ValidateClientCancellationAsync(async () => { @@ -247,7 +259,6 @@ await ValidateClientCancellationAsync(async () => cts.Cancel(); await readTask; }); - try { clientFinished.SetResult(true); @@ -256,11 +267,13 @@ await ValidateClientCancellationAsync(async () => }); } } + [Theory] [InlineData(CancellationMode.CancelPendingRequests, false)] [InlineData(CancellationMode.DisposeHttpClient, false)] [InlineData(CancellationMode.CancelPendingRequests, true)] [InlineData(CancellationMode.DisposeHttpClient, true)] + [SkipOnPlatform(TestPlatforms.Browser, "Browser doesn't have blocking synchronous Stream.ReadByte and so it waits for whole body")] public async Task GetAsync_CancelPendingRequests_DoesntCancelReadAsyncOnResponseStream(CancellationMode mode, bool copyToAsync) { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) diff --git a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs index 30cb5d4a3f043..70ddfcf1f5aaf 100644 --- a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs @@ -1065,6 +1065,11 @@ public override async Task WaitForCancellationAsync(bool ignoreIncomingData = tr } } } + + public override Task WaitForCloseAsync(CancellationToken cancellationToken) + { + return _socket.WaitForCloseAsync(cancellationToken); + } } public override async Task HandleRequestAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null, string content = "") diff --git a/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs b/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs new file mode 100644 index 0000000000000..a37fb304bb9a1 --- /dev/null +++ b/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs @@ -0,0 +1,103 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Test.Common +{ + // Wrapper stream to manually chop writes. This can be useful for simulating partial network transfers + public class ManualChunkingStream : Stream + { + private readonly Stream _innerStream; + private readonly StreamBuffer _writeBuffer = new StreamBuffer(); + private bool _chunkWrite; + + public ManualChunkingStream(Stream stream, bool chunkWrite) + { + _innerStream = stream; + _chunkWrite = chunkWrite; + } + + public int PendingWriteLength => _writeBuffer.ReadBytesAvailable; + + public async ValueTask CommitWriteAsync(int length) + { + Debug.Assert(length <= PendingWriteLength && length > 0, "length <= PendingWriteLength && length > 0"); + byte[] buffer = ArrayPool.Shared.Rent(length); + + int read = await _writeBuffer.ReadAsync(buffer.AsMemory(0, length)); + Debug.Assert(read == length, "read == length"); + await _innerStream.WriteAsync(buffer, 0, read); + await _innerStream.FlushAsync(); + + ArrayPool.Shared.Return(buffer); + } + + public void SetWriteChunking(bool chunking) + { + _chunkWrite = chunking; + if (!_chunkWrite && PendingWriteLength > 0) + { + // flush pending writes + byte[] buffer = ArrayPool.Shared.Rent(PendingWriteLength); + + int read = _writeBuffer.Read(buffer.AsSpan(0, PendingWriteLength)); + Debug.Assert(PendingWriteLength == 0, "PendingWriteLength == 0"); + _innerStream.Write(buffer, 0, read); + _innerStream.Flush(); + + ArrayPool.Shared.Return(buffer); + } + } + + public override bool CanSeek => _innerStream.CanSeek; + + public override bool CanRead => _innerStream.CanRead; + + public override bool CanTimeout => _innerStream.CanTimeout; + + public override bool CanWrite => _innerStream.CanWrite; + + public override long Position + { + get => _innerStream.Position; + set => _innerStream.Position = value; + } + + public override void SetLength(long value) => _innerStream.SetLength(value); + + public override long Length => _innerStream.Length; + + public override void Flush() => _innerStream.Flush(); + + public override Task FlushAsync(CancellationToken cancellationToken) => _innerStream.FlushAsync(cancellationToken); + + public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin); + + public override int Read(byte[] buffer, int offset, int count) => Read(new Span(buffer, offset, count)); + + public override int Read(Span buffer) => _innerStream.Read(buffer); + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => ReadAsync(new Memory(buffer, offset, count)).AsTask(); + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) => _innerStream.ReadAsync(buffer, cancellationToken); + + public override void Write(byte[] buffer, int offset, int count) => Write(new ReadOnlySpan(buffer, offset, count)); + + public override void Write(ReadOnlySpan buffer) + { + if (_chunkWrite) + _writeBuffer.Write(buffer); + else + _innerStream.Write(buffer); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => WriteAsync(new ReadOnlyMemory(buffer, offset, count)).AsTask(); + + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => _chunkWrite ? _writeBuffer.WriteAsync(buffer, cancellationToken) : _innerStream.WriteAsync(buffer, cancellationToken); + } +} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props b/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props index f70812e39b685..3df500bdb8e3e 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props +++ b/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props @@ -1,9 +1,5 @@ - WasmTestOnBrowser - $(TestArchiveRoot)browseronly/ - $(TestArchiveTestsRoot)$(OSPlatformConfig)/ - <_TestEchoMiddleware Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(OS)' == 'Windows_NT'">%HELIX_CORRELATION_PAYLOAD%/xharness/TestEchoMiddleware <_TestEchoMiddleware Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(OS)' != 'Windows_NT'">$HELIX_CORRELATION_PAYLOAD/xharness/TestEchoMiddleware diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/RemoteLoopServer/Handlers/RemoteLoopHandler.cs b/src/libraries/Common/tests/System/Net/Prerequisites/RemoteLoopServer/Handlers/RemoteLoopHandler.cs index 4f83c67b0b30f..557eaa494f7c7 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/RemoteLoopServer/Handlers/RemoteLoopHandler.cs +++ b/src/libraries/Common/tests/System/Net/Prerequisites/RemoteLoopServer/Handlers/RemoteLoopHandler.cs @@ -100,6 +100,11 @@ private static async Task ProcessWebSocketRequest(HttpContext context, WebSocket var slice = new ArraySegment(testedBuffer, 0, testedNext.Result); await control.SendAsync(slice, WebSocketMessageType.Binary, true, cts.Token).ConfigureAwait(false); } + // did we get TCP FIN? + if (!close && (tested.Poll(1, SelectMode.SelectRead) && tested.Available == 0)) + { + close = true; + } if (!close) { testedNext = tested.ReceiveAsync(new Memory(testedBuffer), SocketFlags.None, cts.Token).AsTask(); @@ -142,14 +147,14 @@ private static async Task ProcessWebSocketRequest(HttpContext context, WebSocket } catch (WebSocketException ex) { - logger.LogWarning("ProcessWebSocketRequest closing failed", ex); + logger.LogWarning("RemoteLoopHandler.ProcessWebSocketRequest closing failed", ex); } } cts.Cancel(); } catch (Exception ex) { - logger.LogError("ProcessWebSocketRequest failed", ex); + logger.LogError("RemoteLoopHandler.ProcessWebSocketRequest failed", ex); } finally { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs index b311193948a3a..e214765dd4713 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs @@ -337,13 +337,21 @@ public void EmptyHashAlgorithm() foreach (DSASignatureFormat format in Enum.GetValues(typeof(DSASignatureFormat))) { - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", () => SignData(key, empty, default, format)); - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", () => VerifyData(key, empty, empty, default, format)); + + AssertExtensions.Throws( + "hashAlgorithm", + () => SignData(key, empty, new HashAlgorithmName(""), format)); + + AssertExtensions.Throws( + "hashAlgorithm", + () => VerifyData(key, empty, empty, new HashAlgorithmName(""), format)); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs index af64f2fc031eb..ff6f0c99d193c 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDhKeyFileTests : ECKeyFileTests { protected override ECDiffieHellman CreateKey() => ECDiffieHellmanFactory.Create(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs index 35bed6e724785..51bb3d34182aa 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDsa.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDsaKeyFileTests : ECKeyFileTests { protected override ECDsa CreateKey() => ECDsaFactory.Create(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs index d747aec14e551..187c76ad351a9 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs @@ -40,9 +40,9 @@ public void SignData_InvalidArguments_Throws(ECDsa ecdsa) AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[0], 0, -1, default(HashAlgorithmName))); AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[0], 0, 1, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[10], 0, 10, new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.SignData(new byte[0], new HashAlgorithmName(Guid.NewGuid().ToString("N")))); @@ -64,8 +64,8 @@ public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[0], 0, -1, null, default(HashAlgorithmName))); AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[0], 0, 1, null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], new byte[0], default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], 0, 0, new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], 0, 0, new byte[0], default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[10], new byte[0], new HashAlgorithmName(""))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[10], 0, 10, new byte[0], new HashAlgorithmName(""))); @@ -110,7 +110,8 @@ protected override byte[] SignData(ECDsa ecdsa, byte[] data, int offset, int cou public void SignData_InvalidArguments_Throws(ECDsa ecdsa) { AssertExtensions.Throws("data", () => ecdsa.SignData((Stream)null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.SignData(new MemoryStream(), new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } @@ -119,7 +120,7 @@ public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) { AssertExtensions.Throws("data", () => ecdsa.VerifyData((Stream)null, null, default(HashAlgorithmName))); AssertExtensions.Throws("signature", () => ecdsa.VerifyData(new MemoryStream(), null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.VerifyData(new MemoryStream(), new byte[0], new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs index eb12b87acba73..0f6a191e31dd0 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs @@ -28,7 +28,7 @@ protected override void UseAfterDispose(ECDsa ecdsa, byte[] data, byte[] sig) [Theory, MemberData(nameof(RealImplementations))] public void SignData_InvalidArguments_Throws(ECDsa ecdsa) { - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(null), out int bytesWritten)); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(null), out int bytesWritten)); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(""), out int bytesWritten)); Assert.ThrowsAny(() => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(Guid.NewGuid().ToString("N")), out int bytesWritten)); } @@ -36,7 +36,7 @@ public void SignData_InvalidArguments_Throws(ECDsa ecdsa) [Theory, MemberData(nameof(RealImplementations))] public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) { - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.VerifyData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs index 4a7dace269520..e78cea374bac5 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs @@ -48,14 +48,18 @@ public abstract class SignVerify protected abstract bool VerifyData(RSA rsa, byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding); protected abstract bool VerifyHash(RSA rsa, byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding); - [Theory] - [InlineData(null)] - [InlineData("")] - public void InvalidHashAlgorithmName_Throws(string name) + [Fact] + public void InvalidHashAlgorithmName_Throws() { using (RSA rsa = RSAFactory.Create()) { - var invalidName = new HashAlgorithmName(name); + var invalidName = new HashAlgorithmName(null); + AssertExtensions.Throws("hashAlgorithm", () => SignData(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => SignHash(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => VerifyData(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => VerifyHash(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + + invalidName = new HashAlgorithmName(""); AssertExtensions.Throws("hashAlgorithm", () => SignData(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hashAlgorithm", () => SignHash(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hashAlgorithm", () => VerifyData(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index 8f97aa5ea31ce..c56fdae2d8979 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -209,7 +209,7 @@ private static void ThrowsAnyInternal(Action action, params Type[] exceptionType if (exceptionTypes.Any(t => t.Equals(exceptionType))) return; - throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: ({exceptionType})"); + throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: ({exceptionType}): {e}"); // Log message and callstack to help diagnosis } throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: No exception thrown"); diff --git a/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs b/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs index 4f9b32add6f0d..8f14f24f97f93 100644 --- a/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs +++ b/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; +using System.Text; namespace System.IO { @@ -134,6 +135,38 @@ protected string GetTestFileName(int? index = null, [CallerMemberName] string me return testFileName; } + protected static string GetNamedPipeServerStreamName() + { + if (PlatformDetection.IsInAppContainer) + { + return @"LOCAL\" + Guid.NewGuid().ToString("N"); + } + + if (PlatformDetection.IsWindows) + { + return Guid.NewGuid().ToString("N"); + } + + if (!PlatformDetection.IsCaseSensitiveOS) + { + return $"/tmp/{Guid.NewGuid().ToString("N")}"; + } + + const int MinUdsPathLength = 104; // required min is 92, but every platform we currently target is at least 104 + const int MinAvailableForSufficientRandomness = 5; // we want enough randomness in the name to avoid conflicts between concurrent tests + string prefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_"); + int availableLength = MinUdsPathLength - prefix.Length - 1; // 1 - for possible null terminator + Assert.True(availableLength >= MinAvailableForSufficientRandomness, $"UDS prefix {prefix} length {prefix.Length} is too long"); + + StringBuilder sb = new(availableLength); + Random random = new Random(); + for (int i = 0; i < availableLength; i++) + { + sb.Append((char)('a' + random.Next(0, 26))); + } + return sb.ToString(); + } + private string GenerateTestFileName(int? index, string memberName, int lineNumber) => string.Format( index.HasValue ? "{0}_{1}_{2}_{3}" : "{0}_{1}_{3}", diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index ac167ec7cecaf..207cd17f3b538 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -57,6 +57,11 @@ public static partial class PlatformDetection GetOpenSslVersion() : throw new PlatformNotSupportedException(); + private static readonly Version s_openssl3Version = new Version(3, 0, 0); + public static bool IsOpenSsl3 => !IsOSXLike && !IsWindows && !IsAndroid && !IsBrowser ? + GetOpenSslVersion() >= s_openssl3Version : + false; + /// /// If gnulibc is available, returns the release, such as "stable". /// Otherwise returns "glibc_not_found". diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index bdab9c979cc49..db1af4f4fba6d 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -60,8 +60,14 @@ public static partial class PlatformDetection public static bool IsNotWindows => !IsWindows; public static bool IsCaseInsensitiveOS => IsWindows || IsOSX || IsMacCatalyst; - public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; +#if NETCOREAPP + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS && !RuntimeInformation.RuntimeIdentifier.StartsWith("iossimulator") + && !RuntimeInformation.RuntimeIdentifier.StartsWith("tvossimulator"); +#else + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; +#endif + public static bool IsThreadingSupported => !IsBrowser; public static bool IsBinaryFormatterSupported => IsNotMobile && !IsNativeAot; public static bool IsSymLinkSupported => !IsiOS && !IstvOS; @@ -69,9 +75,10 @@ public static partial class PlatformDetection public static bool IsSpeedOptimized => !IsSizeOptimized; public static bool IsSizeOptimized => IsBrowser || IsAndroid || IsAppleMobile; - public static bool IsBrowserDomSupported => GetIsBrowserDomSupported(); - public static bool IsBrowserDomSupportedOrNotBrowser => IsNotBrowser || GetIsBrowserDomSupported(); + public static bool IsBrowserDomSupported => IsEnvironmentVariableTrue("IsBrowserDomSupported"); + public static bool IsBrowserDomSupportedOrNotBrowser => IsNotBrowser || IsBrowserDomSupported; public static bool IsNotBrowserDomSupported => !IsBrowserDomSupported; + public static bool IsWebSocketSupported => IsEnvironmentVariableTrue("IsWebSocketSupported"); public static bool LocalEchoServerIsNotAvailable => !LocalEchoServerIsAvailable; public static bool LocalEchoServerIsAvailable => IsBrowser; @@ -86,34 +93,8 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() return !(bool)typeof(LambdaExpression).GetMethod("get_CanCompileToIL").Invoke(null, Array.Empty()); } - // Please make sure that you have the libgdiplus dependency installed. - // For details, see https://docs.microsoft.com/dotnet/core/install/dependencies?pivots=os-macos&tabs=netcore31#libgdiplus - public static bool IsDrawingSupported - { - get - { -#if NETCOREAPP - if (!IsWindows) - { - if (IsMobile) - { - return false; - } - else if (IsOSX) - { - return NativeLibrary.TryLoad("libgdiplus.dylib", out _); - } - else - { - return NativeLibrary.TryLoad("libgdiplus.so", out _) || NativeLibrary.TryLoad("libgdiplus.so.0", out _); - } - } -#endif - - return IsNotWindowsNanoServer && IsNotWindowsServerCore; - - } - } + // Drawing is not supported on non windows platforms in .NET 7.0+. + public static bool IsDrawingSupported => IsWindows && IsNotWindowsNanoServer && IsNotWindowsServerCore; public static bool IsAsyncFileIOSupported => !IsBrowser && !(IsWindows && IsMonoRuntime); // https://github.com/dotnet/runtime/issues/34582 @@ -201,6 +182,7 @@ public static bool IsMetadataTokenSupported // Changed to `true` when linking public static bool IsBuiltWithAggressiveTrimming => false; + public static bool IsNotBuiltWithAggressiveTrimming => !IsBuiltWithAggressiveTrimming; // Windows - Schannel supports alpn from win8.1/2012 R2 and higher. // Linux - OpenSsl supports alpn from openssl 1.0.2 and higher. @@ -216,7 +198,12 @@ private static bool GetAlpnSupport() if (IsOpenSslSupported) { - return OpenSslVersion.Major >= 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2); + if (OpenSslVersion.Major >= 3) + { + return true; + } + + return OpenSslVersion.Major == 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2); } if (IsAndroid) @@ -494,12 +481,12 @@ private static bool GetIsRunningOnMonoInterpreter() #endif } - private static bool GetIsBrowserDomSupported() + private static bool IsEnvironmentVariableTrue(string variableName) { if (!IsBrowser) return false; - var val = Environment.GetEnvironmentVariable("IsBrowserDomSupported"); + var val = Environment.GetEnvironmentVariable(variableName); return (val != null && val == "true"); } } diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 49c6d278ee1d2..a5cc7f6825008 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -87,8 +87,6 @@ - - false true false diff --git a/src/libraries/Microsoft.CSharp/tests/RuntimeBinderExceptionTests.cs b/src/libraries/Microsoft.CSharp/tests/RuntimeBinderExceptionTests.cs index d4fddedacc674..4db799a324b95 100644 --- a/src/libraries/Microsoft.CSharp/tests/RuntimeBinderExceptionTests.cs +++ b/src/libraries/Microsoft.CSharp/tests/RuntimeBinderExceptionTests.cs @@ -57,7 +57,7 @@ public void InstanceArgumentInsteadOfTypeForStaticCall() CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); Func target = site.Target; - Assert.Throws(null, () => target.Invoke(site, "Ceci n'est pas un type", 2, 2)); + AssertExtensions.Throws(null, () => target.Invoke(site, "Ceci n'est pas un type", 2, 2)); } [Fact] diff --git a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx index bf2f61e56bdc2..0e3913b9ba776 100644 --- a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx @@ -272,9 +272,6 @@ Recursive type definition is not supported. - - Bit position in AllKeywords ({0}) must equal the command argument named "EtwSessionKeyword" ({1}). - An event with stop suffix must follow a corresponding event with a start suffix. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index bec1c6d44e34e..09d4f271aba72 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -461,24 +461,30 @@ private static void BindDictionary( PropertyInfo setter = dictionaryType.GetProperty("Item", DeclaredOnlyLookup)!; foreach (IConfigurationSection child in config.GetChildren()) { - object? item = BindInstance( - type: valueType, - instance: null, - config: child, - options: options); - if (item != null) + try { - if (keyType == typeof(string)) - { - string key = child.Key; - setter.SetValue(dictionary, item, new object[] { key }); - } - else if (keyTypeIsEnum) + object? item = BindInstance( + type: valueType, + instance: null, + config: child, + options: options); + if (item != null) { - object key = Enum.Parse(keyType, child.Key); - setter.SetValue(dictionary, item, new object[] { key }); + if (keyType == typeof(string)) + { + string key = child.Key; + setter.SetValue(dictionary, item, new object[] { key }); + } + else if (keyTypeIsEnum) + { + object key = Enum.Parse(keyType, child.Key); + setter.SetValue(dictionary, item, new object[] { key }); + } } } + catch + { + } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index 140aedc7eee35..38ab7766d391d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs @@ -74,6 +74,23 @@ public void GetListInvalidValues() Assert.True(list[0]); } + [Fact] + public void GetDictionaryInvalidValues() + { + var input = new Dictionary + { + {"InvalidDictionary:0", "true"}, + {"InvalidDictionary:1", "invalid"}, + }; + var config = new ConfigurationBuilder().AddInMemoryCollection(input).Build(); + var dict = new Dictionary(); + + config.Bind("InvalidDictionary", dict); + + Assert.Single(dict); + Assert.True(dict["0"]); + } + [Fact] public void BindList() { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.cs b/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.cs index b844fec6f2f7a..556870c199dcf 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.cs @@ -8,8 +8,8 @@ namespace Microsoft.Extensions.Configuration { public static partial class JsonConfigurationExtensions { - public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, Microsoft.Extensions.FileProviders.IFileProvider provider, string path, bool optional, bool reloadOnChange) { throw null; } - public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) { throw null; } + public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, Microsoft.Extensions.FileProviders.IFileProvider? provider, string path, bool optional, bool reloadOnChange) { throw null; } + public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action? configureSource) { throw null; } public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path) { throw null; } public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional) { throw null; } public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.csproj b/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.csproj index 195538be004ea..d6c79dcac206b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/ref/Microsoft.Extensions.Configuration.Json.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + enable diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationExtensions.cs index e5cc31af1289e..bf3a83cbad455 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationExtensions.cs @@ -62,7 +62,7 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build /// Whether the file is optional. /// Whether the configuration should be reloaded if the file changes. /// The . - public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange) + public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, IFileProvider? provider, string path, bool optional, bool reloadOnChange) { if (builder == null) { @@ -89,7 +89,7 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build /// The to add to. /// Configures the source. /// The . - public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, Action configureSource) + public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, Action? configureSource) => builder.Add(configureSource); /// diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs b/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs index 2104b66ea66c4..077ead2b51108 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs @@ -13,13 +13,13 @@ internal sealed class JsonConfigurationFileParser { private JsonConfigurationFileParser() { } - private readonly Dictionary _data = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _data = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Stack _paths = new Stack(); - public static IDictionary Parse(Stream input) + public static IDictionary Parse(Stream input) => new JsonConfigurationFileParser().ParseStream(input); - private IDictionary ParseStream(Stream input) + private IDictionary ParseStream(Stream input) { var jsonDocumentOptions = new JsonDocumentOptions { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj b/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj index ad2b4ea3c1f82..61be4beedfb22 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) + enable true true diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/ref/Microsoft.Extensions.Configuration.UserSecrets.csproj b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/ref/Microsoft.Extensions.Configuration.UserSecrets.csproj index 32f367d46a125..db24c060dc924 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/ref/Microsoft.Extensions.Configuration.UserSecrets.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/ref/Microsoft.Extensions.Configuration.UserSecrets.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + enable diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj index d3b36b403a0b7..880f1a2d35f6d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + enable true false diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/PathHelper.cs b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/PathHelper.cs index 3bf8ab8c9cafb..e22840114fd53 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/PathHelper.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/PathHelper.cs @@ -43,8 +43,8 @@ public static string GetSecretsPathFromSecretsId(string userSecretsId) const string userSecretsFallbackDir = "DOTNET_USER_SECRETS_FALLBACK_DIR"; // For backwards compat, this checks env vars first before using Env.GetFolderPath - string appData = Environment.GetEnvironmentVariable("APPDATA"); - string root = appData // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ + string? appData = Environment.GetEnvironmentVariable("APPDATA"); + string? root = appData // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ ?? Environment.GetEnvironmentVariable("HOME") // On Mac/Linux it goes to ~/.microsoft/usersecrets/ ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs index 963ac77a30eea..0b683da9140fa 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs @@ -128,7 +128,7 @@ public static IConfigurationBuilder AddUserSecrets(this IConfigurationBuilder co throw new ArgumentNullException(nameof(assembly)); } - UserSecretsIdAttribute attribute = assembly.GetCustomAttribute(); + UserSecretsIdAttribute? attribute = assembly.GetCustomAttribute(); if (attribute != null) { return AddUserSecretsInternal(configuration, attribute.UserSecretsId, optional, reloadOnChange); @@ -188,8 +188,8 @@ private static IConfigurationBuilder AddUserSecretsInternal(IConfigurationBuilde private static IConfigurationBuilder AddSecretsFile(IConfigurationBuilder configuration, string secretPath, bool optional, bool reloadOnChange) { - string directoryPath = Path.GetDirectoryName(secretPath); - PhysicalFileProvider fileProvider = Directory.Exists(directoryPath) + string? directoryPath = Path.GetDirectoryName(secretPath); + PhysicalFileProvider? fileProvider = Directory.Exists(directoryPath) ? new PhysicalFileProvider(directoryPath) : null; return configuration.AddJsonFile(fileProvider, PathHelper.SecretsFileName, optional, reloadOnChange); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx index 9f74883c8e8ec..f6d5587b1d723 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx @@ -121,10 +121,6 @@ Multiple constructors accepting all given argument types have been found in type '{0}'. There should only be one applicable constructor. {0} = service type - - Unable to locate implementation '{0}' for service '{1}'. - {0} = implementation type, {1} = service type - Unable to resolve service for type '{0}' while attempting to activate '{1}'. {0} = service which cannot be resolved, {1} = service being activated diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index d2161d8905150..0b85156d60885 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -24,7 +24,7 @@ public sealed partial class ServiceProvider : System.IAsyncDisposable, System.ID internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public object GetService(System.Type serviceType) { throw null; } + public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.csproj index 71e3f9dcb84d2..bcd739c9f5f1a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) + enable diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs index eb26ebb7cfa7f..79a93d3052acb 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.DependencyInjection { - internal sealed class CallSiteJsonFormatter: CallSiteVisitor + internal sealed class CallSiteJsonFormatter: CallSiteVisitor { internal static CallSiteJsonFormatter Instance = new CallSiteJsonFormatter(); @@ -25,7 +25,7 @@ public string Format(ServiceCallSite callSite) return stringBuilder.ToString(); } - protected override object VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteFormatterContext argument) + protected override object? VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("implementationType", constructorCallSite.ImplementationType); @@ -45,7 +45,7 @@ protected override object VisitConstructor(ConstructorCallSite constructorCallSi return null; } - protected override object VisitCallSiteMain(ServiceCallSite callSite, CallSiteFormatterContext argument) + protected override object? VisitCallSiteMain(ServiceCallSite callSite, CallSiteFormatterContext argument) { if (argument.ShouldFormat(callSite)) { @@ -69,19 +69,19 @@ protected override object VisitCallSiteMain(ServiceCallSite callSite, CallSiteFo return null; } - protected override object VisitConstant(ConstantCallSite constantCallSite, CallSiteFormatterContext argument) + protected override object? VisitConstant(ConstantCallSite constantCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("value", constantCallSite.DefaultValue ?? ""); return null; } - protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteFormatterContext argument) + protected override object? VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteFormatterContext argument) { return null; } - protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteFormatterContext argument) + protected override object? VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("itemType", enumerableCallSite.ItemType); argument.WriteProperty("size", enumerableCallSite.ServiceCallSites.Length); @@ -101,7 +101,7 @@ protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSit return null; } - protected override object VisitFactory(FactoryCallSite factoryCallSite, CallSiteFormatterContext argument) + protected override object? VisitFactory(FactoryCallSite factoryCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("method", factoryCallSite.Factory.Method); @@ -174,7 +174,7 @@ public void StartArrayItem() } } - public void WriteProperty(string name, object value) + public void WriteProperty(string name, object? value) { StartProperty(name); if (value != null) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 03b245224d8bb..b77679cc4e857 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -158,7 +158,7 @@ public void ServiceProviderDisposed(ServiceProvider provider) { // remove the provider, along with any stale references WeakReference reference = _providers[i]; - if (!reference.TryGetTarget(out ServiceProvider target) || target == provider) + if (!reference.TryGetTarget(out ServiceProvider? target) || target == provider) { _providers.RemoveAt(i); } @@ -279,7 +279,7 @@ protected override void OnEventCommand(EventCommandEventArgs command) { foreach (WeakReference reference in _providers) { - if (reference.TryGetTarget(out ServiceProvider provider)) + if (reference.TryGetTarget(out ServiceProvider? provider)) { WriteServiceProviderBuilt(provider); } @@ -308,7 +308,8 @@ private sealed class NodeCountingVisitor : ExpressionVisitor { public int NodeCount { get; private set; } - public override Expression Visit(Expression e) + [return: NotNullIfNotNull("e")] + public override Expression? Visit(Expression? e) { base.Visit(e); NodeCount++; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index 38174f12577d0..23c3a776251f3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -1,10 +1,10 @@ - + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) + enable false - Annotations $(NoWarn);CP0001 true diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs index ca65e64ca557b..c8279dc0879e2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs @@ -31,7 +31,7 @@ public void Remove(Type serviceType) _callSiteChain.Remove(serviceType); } - public void Add(Type serviceType, Type implementationType = null) + public void Add(Type serviceType, Type? implementationType = null) { _callSiteChain[serviceType] = new ChainItemInfo(_callSiteChain.Count, implementationType); } @@ -55,7 +55,7 @@ private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving foreach (KeyValuePair pair in ordered) { Type serviceType = pair.Key; - Type implementationType = pair.Value.ImplementationType; + Type? implementationType = pair.Value.ImplementationType; if (implementationType == null || serviceType == implementationType) { builder.Append(TypeNameHelper.GetTypeDisplayName(serviceType)); @@ -76,9 +76,9 @@ private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving private readonly struct ChainItemInfo { public int Order { get; } - public Type ImplementationType { get; } + public Type? ImplementationType { get; } - public ChainItemInfo(int order, Type implementationType) + public ChainItemInfo(int order, Type? implementationType) { Order = order; ImplementationType = implementationType; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 36e0ab4473822..a4092ca70c83a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -39,7 +39,7 @@ private void Populate() Type serviceType = descriptor.ServiceType; if (serviceType.IsGenericTypeDefinition) { - Type implementationType = descriptor.ImplementationType; + Type? implementationType = descriptor.ImplementationType; if (implementationType == null || !implementationType.IsGenericTypeDefinition) { @@ -135,7 +135,7 @@ private static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypes( attributeData.ConstructorArguments.Count == 1 && attributeData.ConstructorArguments[0].ArgumentType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes") { - return (DynamicallyAccessedMemberTypes)(int)attributeData.ConstructorArguments[0].Value; + return (DynamicallyAccessedMemberTypes)(int)attributeData.ConstructorArguments[0].Value!; } } @@ -160,11 +160,11 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica return null; } - internal ServiceCallSite GetCallSite(Type serviceType, CallSiteChain callSiteChain) => - _callSiteCache.TryGetValue(new ServiceCacheKey(serviceType, DefaultSlot), out ServiceCallSite site) ? site : + internal ServiceCallSite? GetCallSite(Type serviceType, CallSiteChain callSiteChain) => + _callSiteCache.TryGetValue(new ServiceCacheKey(serviceType, DefaultSlot), out ServiceCallSite? site) ? site : CreateCallSite(serviceType, callSiteChain); - internal ServiceCallSite GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) + internal ServiceCallSite? GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) { if (_descriptorLookup.TryGetValue(serviceDescriptor.ServiceType, out ServiceDescriptorCacheItem descriptor)) { @@ -175,7 +175,7 @@ internal ServiceCallSite GetCallSite(ServiceDescriptor serviceDescriptor, CallSi return null; } - private ServiceCallSite CreateCallSite(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? CreateCallSite(Type serviceType, CallSiteChain callSiteChain) { if (!_stackGuard.TryEnterOnCurrentStack()) { @@ -198,7 +198,7 @@ private ServiceCallSite CreateCallSite(Type serviceType, CallSiteChain callSiteC { callSiteChain.CheckCircularDependency(serviceType); - ServiceCallSite callSite = TryCreateExact(serviceType, callSiteChain) ?? + ServiceCallSite? callSite = TryCreateExact(serviceType, callSiteChain) ?? TryCreateOpenGeneric(serviceType, callSiteChain) ?? TryCreateEnumerable(serviceType, callSiteChain); @@ -206,7 +206,7 @@ private ServiceCallSite CreateCallSite(Type serviceType, CallSiteChain callSiteC } } - private ServiceCallSite TryCreateExact(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateExact(Type serviceType, CallSiteChain callSiteChain) { if (_descriptorLookup.TryGetValue(serviceType, out ServiceDescriptorCacheItem descriptor)) { @@ -216,7 +216,7 @@ private ServiceCallSite TryCreateExact(Type serviceType, CallSiteChain callSiteC return null; } - private ServiceCallSite TryCreateOpenGeneric(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateOpenGeneric(Type serviceType, CallSiteChain callSiteChain) { if (serviceType.IsConstructedGenericType && _descriptorLookup.TryGetValue(serviceType.GetGenericTypeDefinition(), out ServiceDescriptorCacheItem descriptor)) @@ -227,10 +227,10 @@ private ServiceCallSite TryCreateOpenGeneric(Type serviceType, CallSiteChain cal return null; } - private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, DefaultSlot); - if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) + if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; } @@ -258,7 +258,7 @@ private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain call // Last service should get slot 0 int slot = descriptors.Count - i - 1; // There may not be any open generics here - ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot); + ServiceCallSite? callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot); Debug.Assert(callSite != null); cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); @@ -272,7 +272,7 @@ private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain call for (int i = _descriptors.Length - 1; i >= 0; i--) { ServiceDescriptor descriptor = _descriptors[i]; - ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot) ?? + ServiceCallSite? callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot) ?? TryCreateOpenGeneric(descriptor, itemType, callSiteChain, slot, false); if (callSite != null) @@ -310,12 +310,12 @@ private CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResultCacheLo return (CallSiteResultCacheLocation)Math.Max((int)locationA, (int)locationB); } - private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) + private ServiceCallSite? TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { if (serviceType == descriptor.ServiceType) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); - if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) + if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; } @@ -349,13 +349,13 @@ private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type servic Justification = "MakeGenericType here is used to create a closed generic implementation type given the closed service type. " + "Trimming annotations on the generic types are verified when 'Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability' is set, which is set by default when PublishTrimmed=true. " + "That check informs developers when these generic types don't have compatible trimming annotations.")] - private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) + private ServiceCallSite? TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); - if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) + if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; } @@ -394,7 +394,7 @@ private ServiceCallSite CreateConstructorCallSite( callSiteChain.Add(serviceType, implementationType); ConstructorInfo[] constructors = implementationType.GetConstructors(); - ServiceCallSite[] parameterCallSites = null; + ServiceCallSite[]? parameterCallSites = null; if (constructors.Length == 0) { @@ -413,7 +413,7 @@ private ServiceCallSite CreateConstructorCallSite( implementationType, callSiteChain, parameters, - throwIfCallSiteNotFound: true); + throwIfCallSiteNotFound: true)!; return new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites); } @@ -421,13 +421,13 @@ private ServiceCallSite CreateConstructorCallSite( Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); - ConstructorInfo bestConstructor = null; - HashSet bestConstructorParameterTypes = null; + ConstructorInfo? bestConstructor = null; + HashSet? bestConstructorParameterTypes = null; for (int i = 0; i < constructors.Length; i++) { ParameterInfo[] parameters = constructors[i].GetParameters(); - ServiceCallSite[] currentParameterCallSites = CreateArgumentCallSites( + ServiceCallSite[]? currentParameterCallSites = CreateArgumentCallSites( implementationType, callSiteChain, parameters, @@ -487,7 +487,8 @@ private ServiceCallSite CreateConstructorCallSite( } } - private ServiceCallSite[] CreateArgumentCallSites( + /// Not null if throwIfCallSiteNotFound is true + private ServiceCallSite[]? CreateArgumentCallSites( Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, @@ -497,9 +498,9 @@ private ServiceCallSite[] CreateArgumentCallSites( for (int index = 0; index < parameters.Length; index++) { Type parameterType = parameters[index].ParameterType; - ServiceCallSite callSite = GetCallSite(parameterType, callSiteChain); + ServiceCallSite? callSite = GetCallSite(parameterType, callSiteChain); - if (callSite == null && ParameterDefaultValue.TryGetDefaultValue(parameters[index], out object defaultValue)) + if (callSite == null && ParameterDefaultValue.TryGetDefaultValue(parameters[index], out object? defaultValue)) { callSite = new ConstantCallSite(parameterType, defaultValue); } @@ -562,9 +563,11 @@ public bool IsService(Type serviceType) private struct ServiceDescriptorCacheItem { - private ServiceDescriptor _item; + [DisallowNull] + private ServiceDescriptor? _item; - private List _items; + [DisallowNull] + private List? _items; public ServiceDescriptor Last { @@ -605,10 +608,10 @@ public ServiceDescriptor this[int index] if (index == 0) { - return _item; + return _item!; } - return _items[index - 1]; + return _items![index - 1]; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs index 1e330624aeb81..96fcd070295cf 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteRuntimeResolver : CallSiteVisitor + internal sealed class CallSiteRuntimeResolver : CallSiteVisitor { public static CallSiteRuntimeResolver Instance { get; } = new(); @@ -18,7 +18,7 @@ private CallSiteRuntimeResolver() { } - public object Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) + public object? Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) { // Fast path to avoid virtual calls if we already have the cached value in the root scope if (scope.IsRootScope && callSite.Value is object cached) @@ -32,21 +32,21 @@ public object Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope }); } - protected override object VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context) + protected override object? VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context) { return context.Scope.CaptureDisposable(VisitCallSiteMain(transientCallSite, context)); } protected override object VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) { - object[] parameterValues; + object?[] parameterValues; if (constructorCallSite.ParameterCallSites.Length == 0) { parameterValues = Array.Empty(); } else { - parameterValues = new object[constructorCallSite.ParameterCallSites.Length]; + parameterValues = new object?[constructorCallSite.ParameterCallSites.Length]; for (int index = 0; index < parameterValues.Length; index++) { parameterValues[index] = VisitCallSite(constructorCallSite.ParameterCallSites[index], context); @@ -69,7 +69,7 @@ protected override object VisitConstructor(ConstructorCallSite constructorCallSi #endif } - protected override object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) + protected override object? VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) { if (callSite.Value is object value) { @@ -83,12 +83,12 @@ protected override object VisitRootCache(ServiceCallSite callSite, RuntimeResolv lock (callSite) { // Lock the callsite and check if another thread already cached the value - if (callSite.Value is object resolved) + if (callSite.Value is object callSiteValue) { - return resolved; + return callSiteValue; } - resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext + object? resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext { Scope = serviceProviderEngine, AcquiredLocks = context.AcquiredLocks | lockType @@ -99,7 +99,7 @@ protected override object VisitRootCache(ServiceCallSite callSite, RuntimeResolv } } - protected override object VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context) + protected override object? VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context) { // Check if we are in the situation where scoped service was promoted to singleton // and we need to lock the root @@ -108,11 +108,11 @@ protected override object VisitScopeCache(ServiceCallSite callSite, RuntimeResol VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope); } - private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) + private object? VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) { bool lockTaken = false; object sync = serviceProviderEngine.Sync; - Dictionary resolvedServices = serviceProviderEngine.ResolvedServices; + Dictionary resolvedServices = serviceProviderEngine.ResolvedServices; // Taking locks only once allows us to fork resolution process // on another thread without causing the deadlock because we // always know that we are going to wait the other thread to finish before @@ -126,7 +126,7 @@ private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext conte { // Note: This method has already taken lock by the caller for resolution and access synchronization. // For scoped: takes a dictionary as both a resolution lock and a dictionary access lock. - if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved)) + if (resolvedServices.TryGetValue(callSite.Cache.Key, out object? resolved)) { return resolved; } @@ -149,7 +149,7 @@ private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext conte } } - protected override object VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context) + protected override object? VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context) { return constantCallSite.DefaultValue; } @@ -167,7 +167,7 @@ protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSit for (int index = 0; index < enumerableCallSite.ServiceCallSites.Length; index++) { - object value = VisitCallSite(enumerableCallSite.ServiceCallSites[index], context); + object? value = VisitCallSite(enumerableCallSite.ServiceCallSites[index], context); array.SetValue(value, index); } return array; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs index 29a95f507d357..9e0b4e3c5b999 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs @@ -3,17 +3,18 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteValidator: CallSiteVisitor + internal sealed class CallSiteValidator: CallSiteVisitor { // Keys are services being resolved via GetService, values - first scoped service in their call site tree private readonly ConcurrentDictionary _scopedServices = new ConcurrentDictionary(); public void ValidateCallSite(ServiceCallSite callSite) { - Type scoped = VisitCallSite(callSite, default); + Type? scoped = VisitCallSite(callSite, default); if (scoped != null) { _scopedServices[callSite.ServiceType] = scoped; @@ -23,7 +24,7 @@ public void ValidateCallSite(ServiceCallSite callSite) public void ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope) { if (ReferenceEquals(scope, rootScope) - && _scopedServices.TryGetValue(serviceType, out Type scopedService)) + && _scopedServices.TryGetValue(serviceType, out Type? scopedService)) { if (serviceType == scopedService) { @@ -40,12 +41,12 @@ public void ValidateResolution(Type serviceType, IServiceScope scope, IServiceSc } } - protected override Type VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state) + protected override Type? VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state) { - Type result = null; + Type? result = null; foreach (ServiceCallSite parameterCallSite in constructorCallSite.ParameterCallSites) { - Type scoped = VisitCallSite(parameterCallSite, state); + Type? scoped = VisitCallSite(parameterCallSite, state); if (result == null) { result = scoped; @@ -54,13 +55,13 @@ protected override Type VisitConstructor(ConstructorCallSite constructorCallSite return result; } - protected override Type VisitIEnumerable(IEnumerableCallSite enumerableCallSite, + protected override Type? VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state) { - Type result = null; + Type? result = null; foreach (ServiceCallSite serviceCallSite in enumerableCallSite.ServiceCallSites) { - Type scoped = VisitCallSite(serviceCallSite, state); + Type? scoped = VisitCallSite(serviceCallSite, state); if (result == null) { result = scoped; @@ -69,13 +70,13 @@ protected override Type VisitIEnumerable(IEnumerableCallSite enumerableCallSite, return result; } - protected override Type VisitRootCache(ServiceCallSite singletonCallSite, CallSiteValidatorState state) + protected override Type? VisitRootCache(ServiceCallSite singletonCallSite, CallSiteValidatorState state) { state.Singleton = singletonCallSite; return VisitCallSiteMain(singletonCallSite, state); } - protected override Type VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state) + protected override Type? VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state) { // We are fine with having ServiceScopeService requested by singletons if (scopedCallSite.ServiceType == typeof(IServiceScopeFactory)) @@ -96,15 +97,16 @@ protected override Type VisitScopeCache(ServiceCallSite scopedCallSite, CallSite return scopedCallSite.ServiceType; } - protected override Type VisitConstant(ConstantCallSite constantCallSite, CallSiteValidatorState state) => null; + protected override Type? VisitConstant(ConstantCallSite constantCallSite, CallSiteValidatorState state) => null; - protected override Type VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteValidatorState state) => null; + protected override Type? VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteValidatorState state) => null; - protected override Type VisitFactory(FactoryCallSite factoryCallSite, CallSiteValidatorState state) => null; + protected override Type? VisitFactory(FactoryCallSite factoryCallSite, CallSiteValidatorState state) => null; internal struct CallSiteValidatorState { - public ServiceCallSite Singleton { get; set; } + [DisallowNull] + public ServiceCallSite? Singleton { get; set; } } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CompiledServiceProviderEngine.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CompiledServiceProviderEngine.cs index b51b879c54395..eef3e1fe70214 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CompiledServiceProviderEngine.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CompiledServiceProviderEngine.cs @@ -18,6 +18,6 @@ public CompiledServiceProviderEngine(ServiceProvider provider) ResolverBuilder = new(provider); } - public override Func RealizeService(ServiceCallSite callSite) => ResolverBuilder.Build(callSite); + public override Func RealizeService(ServiceCallSite callSite) => ResolverBuilder.Build(callSite); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs index bb822437a0e36..8071c67013352 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs @@ -8,9 +8,9 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup internal sealed class ConstantCallSite : ServiceCallSite { private readonly Type _serviceType; - internal object DefaultValue => Value; + internal object? DefaultValue => Value; - public ConstantCallSite(Type serviceType, object defaultValue): base(ResultCache.None) + public ConstantCallSite(Type serviceType, object? defaultValue): base(ResultCache.None) { _serviceType = serviceType ?? throw new ArgumentNullException(nameof(serviceType)); if (defaultValue != null && !serviceType.IsInstanceOfType(defaultValue)) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs index b44608c0841b5..1dbd77cb45171 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs @@ -29,7 +29,7 @@ public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo public override Type ServiceType { get; } - public override Type ImplementationType => ConstructorInfo.DeclaringType; + public override Type? ImplementationType => ConstructorInfo.DeclaringType; public override CallSiteKind Kind { get; } = CallSiteKind.Constructor; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/DynamicServiceProviderEngine.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/DynamicServiceProviderEngine.cs index 09abe625a658c..5c52efcc4f181 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/DynamicServiceProviderEngine.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/DynamicServiceProviderEngine.cs @@ -16,7 +16,7 @@ public DynamicServiceProviderEngine(ServiceProvider serviceProvider): base(servi _serviceProvider = serviceProvider; } - public override Func RealizeService(ServiceCallSite callSite) + public override Func RealizeService(ServiceCallSite callSite) { int callCount = 0; return scope => diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs index 001a3d7e07207..3d7f40834ad3f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class ExpressionResolverBuilder : CallSiteVisitor + internal sealed class ExpressionResolverBuilder : CallSiteVisitor { private static readonly ParameterExpression ScopeParameter = Expression.Parameter(typeof(ServiceProviderEngineScope)); @@ -20,13 +20,13 @@ internal sealed class ExpressionResolverBuilder : CallSiteVisitor> BuildExpression(Ser ScopeParameter); } - protected override Expression VisitRootCache(ServiceCallSite singletonCallSite, object context) + protected override Expression VisitRootCache(ServiceCallSite singletonCallSite, object? context) { return Expression.Constant(CallSiteRuntimeResolver.Instance.Resolve(singletonCallSite, _rootScope)); } - protected override Expression VisitConstant(ConstantCallSite constantCallSite, object context) + protected override Expression VisitConstant(ConstantCallSite constantCallSite, object? context) { return Expression.Constant(constantCallSite.DefaultValue); } - protected override Expression VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, object context) + protected override Expression VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, object? context) { return ScopeParameter; } - protected override Expression VisitFactory(FactoryCallSite factoryCallSite, object context) + protected override Expression VisitFactory(FactoryCallSite factoryCallSite, object? context) { return Expression.Invoke(Expression.Constant(factoryCallSite.Factory), ScopeParameter); } - protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, object context) + protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, object? context) { if (callSite.ServiceCallSites.Length == 0) { @@ -127,7 +127,7 @@ protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, obj callSite.ItemType))); } - protected override Expression VisitDisposeCache(ServiceCallSite callSite, object context) + protected override Expression VisitDisposeCache(ServiceCallSite callSite, object? context) { // Elide calls to GetCaptureDisposable if the implementation type isn't disposable return TryCaptureDisposable( @@ -146,7 +146,7 @@ private Expression TryCaptureDisposable(ServiceCallSite callSite, ParameterExpre return Expression.Invoke(GetCaptureDisposable(scope), service); } - protected override Expression VisitConstructor(ConstructorCallSite callSite, object context) + protected override Expression VisitConstructor(ConstructorCallSite callSite, object? context) { ParameterInfo[] parameters = callSite.ConstructorInfo.GetParameters(); Expression[] parameterExpressions; @@ -164,7 +164,7 @@ protected override Expression VisitConstructor(ConstructorCallSite callSite, obj } Expression expression = Expression.New(callSite.ConstructorInfo, parameterExpressions); - if (callSite.ImplementationType.IsValueType) + if (callSite.ImplementationType!.IsValueType) { expression = Expression.Convert(expression, typeof(object)); } @@ -183,7 +183,7 @@ private static Expression Convert(Expression expression, Type type, bool forceVa return Expression.Convert(expression, type); } - protected override Expression VisitScopeCache(ServiceCallSite callSite, object context) + protected override Expression VisitScopeCache(ServiceCallSite callSite, object? context) { Func lambda = Build(callSite); return Expression.Invoke(Expression.Constant(lambda), ScopeParameter); @@ -260,7 +260,7 @@ private Expression BuildScopedExpression(ServiceCallSite callSite) Expression.Property( ScopeParameter, typeof(ServiceProviderEngineScope) - .GetProperty(nameof(ServiceProviderEngineScope.IsRootScope), BindingFlags.Instance | BindingFlags.Public)), + .GetProperty(nameof(ServiceProviderEngineScope.IsRootScope), BindingFlags.Instance | BindingFlags.Public)!), resolveRootScopeExpression, Expression.Block( typeof(object), diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs index 59e5267974ac5..3386987b077e7 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs @@ -16,7 +16,7 @@ public FactoryCallSite(ResultCache cache, Type serviceType, Func null; + public override Type? ImplementationType => null; public override CallSiteKind Kind { get; } = CallSiteKind.Factory; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs index e5370ca652957..e46e459ce9d50 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs @@ -4,43 +4,44 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class ILEmitResolverBuilder : CallSiteVisitor + internal sealed class ILEmitResolverBuilder : CallSiteVisitor { private static readonly MethodInfo ResolvedServicesGetter = typeof(ServiceProviderEngineScope).GetProperty( - nameof(ServiceProviderEngineScope.ResolvedServices), BindingFlags.Instance | BindingFlags.NonPublic).GetMethod; + nameof(ServiceProviderEngineScope.ResolvedServices), BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; private static readonly MethodInfo ScopeLockGetter = typeof(ServiceProviderEngineScope).GetProperty( - nameof(ServiceProviderEngineScope.Sync), BindingFlags.Instance | BindingFlags.NonPublic).GetMethod; + nameof(ServiceProviderEngineScope.Sync), BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; private static readonly MethodInfo ScopeIsRootScope = typeof(ServiceProviderEngineScope).GetProperty( - nameof(ServiceProviderEngineScope.IsRootScope), BindingFlags.Instance | BindingFlags.Public).GetMethod; + nameof(ServiceProviderEngineScope.IsRootScope), BindingFlags.Instance | BindingFlags.Public)!.GetMethod!; private static readonly MethodInfo CallSiteRuntimeResolverResolveMethod = typeof(CallSiteRuntimeResolver).GetMethod( - nameof(CallSiteRuntimeResolver.Resolve), BindingFlags.Public | BindingFlags.Instance); + nameof(CallSiteRuntimeResolver.Resolve), BindingFlags.Public | BindingFlags.Instance)!; private static readonly MethodInfo CallSiteRuntimeResolverInstanceField = typeof(CallSiteRuntimeResolver).GetProperty( - nameof(CallSiteRuntimeResolver.Instance), BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance).GetMethod; + nameof(CallSiteRuntimeResolver.Instance), BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance)!.GetMethod!; - private static readonly FieldInfo FactoriesField = typeof(ILEmitResolverBuilderRuntimeContext).GetField(nameof(ILEmitResolverBuilderRuntimeContext.Factories)); - private static readonly FieldInfo ConstantsField = typeof(ILEmitResolverBuilderRuntimeContext).GetField(nameof(ILEmitResolverBuilderRuntimeContext.Constants)); - private static readonly MethodInfo GetTypeFromHandleMethod = typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)); + private static readonly FieldInfo FactoriesField = typeof(ILEmitResolverBuilderRuntimeContext).GetField(nameof(ILEmitResolverBuilderRuntimeContext.Factories))!; + private static readonly FieldInfo ConstantsField = typeof(ILEmitResolverBuilderRuntimeContext).GetField(nameof(ILEmitResolverBuilderRuntimeContext.Constants))!; + private static readonly MethodInfo GetTypeFromHandleMethod = typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle))!; private static readonly ConstructorInfo CacheKeyCtor = typeof(ServiceCacheKey).GetConstructors()[0]; private sealed class ILEmitResolverBuilderRuntimeContext { - public object[] Constants; - public Func[] Factories; + public object?[]? Constants; + public Func[]? Factories; } private struct GeneratedMethod { - public Func Lambda; + public Func Lambda; public ILEmitResolverBuilderRuntimeContext Context; public DynamicMethod DynamicMethod; @@ -59,7 +60,7 @@ public ILEmitResolverBuilder(ServiceProvider serviceProvider) _buildTypeDelegate = (key, cs) => BuildTypeNoCache(cs); } - public Func Build(ServiceCallSite callSite) + public Func Build(ServiceCallSite callSite) { return BuildType(callSite).Lambda; } @@ -117,14 +118,14 @@ private GeneratedMethod BuildTypeNoCache(ServiceCallSite callSite) return new GeneratedMethod() { - Lambda = (Func)dynamicMethod.CreateDelegate(typeof(Func), runtimeContext), + Lambda = (Func)dynamicMethod.CreateDelegate(typeof(Func), runtimeContext), Context = runtimeContext, DynamicMethod = dynamicMethod }; } - protected override object VisitDisposeCache(ServiceCallSite transientCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitDisposeCache(ServiceCallSite transientCallSite, ILEmitResolverBuilderContext argument) { if (transientCallSite.CaptureDisposable) { @@ -139,7 +140,7 @@ protected override object VisitDisposeCache(ServiceCallSite transientCallSite, I return null; } - protected override object VisitConstructor(ConstructorCallSite constructorCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitConstructor(ConstructorCallSite constructorCallSite, ILEmitResolverBuilderContext argument) { // new T([create arguments]) foreach (ServiceCallSite parameterCallSite in constructorCallSite.ParameterCallSites) @@ -152,7 +153,7 @@ protected override object VisitConstructor(ConstructorCallSite constructorCallSi } argument.Generator.Emit(OpCodes.Newobj, constructorCallSite.ConstructorInfo); - if (constructorCallSite.ImplementationType.IsValueType) + if (constructorCallSite.ImplementationType!.IsValueType) { argument.Generator.Emit(OpCodes.Box, constructorCallSite.ImplementationType); } @@ -160,13 +161,13 @@ protected override object VisitConstructor(ConstructorCallSite constructorCallSi return null; } - protected override object VisitRootCache(ServiceCallSite callSite, ILEmitResolverBuilderContext argument) + protected override object? VisitRootCache(ServiceCallSite callSite, ILEmitResolverBuilderContext argument) { AddConstant(argument, CallSiteRuntimeResolver.Instance.Resolve(callSite, _rootScope)); return null; } - protected override object VisitScopeCache(ServiceCallSite scopedCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitScopeCache(ServiceCallSite scopedCallSite, ILEmitResolverBuilderContext argument) { GeneratedMethod generatedMethod = BuildType(scopedCallSite); @@ -186,20 +187,20 @@ protected override object VisitScopeCache(ServiceCallSite scopedCallSite, ILEmit return null; } - protected override object VisitConstant(ConstantCallSite constantCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitConstant(ConstantCallSite constantCallSite, ILEmitResolverBuilderContext argument) { AddConstant(argument, constantCallSite.DefaultValue); return null; } - protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, ILEmitResolverBuilderContext argument) { // [return] ProviderScope argument.Generator.Emit(OpCodes.Ldarg_1); return null; } - protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ILEmitResolverBuilderContext argument) { if (enumerableCallSite.ServiceCallSites.Length == 0) { @@ -235,7 +236,7 @@ protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSit return null; } - protected override object VisitFactory(FactoryCallSite factoryCallSite, ILEmitResolverBuilderContext argument) + protected override object? VisitFactory(FactoryCallSite factoryCallSite, ILEmitResolverBuilderContext argument) { if (argument.Factories == null) { @@ -256,11 +257,11 @@ protected override object VisitFactory(FactoryCallSite factoryCallSite, ILEmitRe return null; } - private void AddConstant(ILEmitResolverBuilderContext argument, object value) + private void AddConstant(ILEmitResolverBuilderContext argument, object? value) { if (argument.Constants == null) { - argument.Constants = new List(); + argument.Constants = new List(); } // this.Constants[i] @@ -274,6 +275,8 @@ private void AddConstant(ILEmitResolverBuilderContext argument, object value) private void AddCacheKey(ILEmitResolverBuilderContext argument, ServiceCacheKey key) { + Debug.Assert(key.Type != null); + // new ServiceCacheKey(typeof(key.Type), key.Slot) argument.Generator.Emit(OpCodes.Ldtoken, key.Type); argument.Generator.Emit(OpCodes.Call, GetTypeFromHandleMethod); @@ -283,9 +286,8 @@ private void AddCacheKey(ILEmitResolverBuilderContext argument, ServiceCacheKey private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite callSite, ILGenerator generator) { - var context = new ILEmitResolverBuilderContext() + var context = new ILEmitResolverBuilderContext(generator) { - Generator = generator, Constants = null, Factories = null }; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilderContext.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilderContext.cs index 33cde16bb0091..f32d60fe12f32 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilderContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilderContext.cs @@ -9,8 +9,9 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal sealed class ILEmitResolverBuilderContext { - public ILGenerator Generator { get; set; } - public List Constants { get; set; } - public List> Factories { get; set; } + public ILEmitResolverBuilderContext(ILGenerator generator) => Generator = generator; + public ILGenerator Generator { get; } + public List? Constants { get; set; } + public List>? Factories { get; set; } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitServiceProviderEngine.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitServiceProviderEngine.cs index f0bcebf5df782..5facb1a8ab95d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitServiceProviderEngine.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitServiceProviderEngine.cs @@ -13,7 +13,7 @@ public ILEmitServiceProviderEngine(ServiceProvider serviceProvider) _expressionResolverBuilder = new ILEmitResolverBuilder(serviceProvider); } - public override Func RealizeService(ServiceCallSite callSite) + public override Func RealizeService(ServiceCallSite callSite) { return _expressionResolverBuilder.Build(callSite); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs index 4a87b7be3675f..65b1c799b6f3a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs @@ -16,7 +16,7 @@ internal ResultCache(CallSiteResultCacheLocation lifetime, ServiceCacheKey cache Key = cacheKey; } - public ResultCache(ServiceLifetime lifetime, Type type, int slot) + public ResultCache(ServiceLifetime lifetime, Type? type, int slot) { Debug.Assert(lifetime == ServiceLifetime.Transient || type != null); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/RuntimeServiceProviderEngine.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/RuntimeServiceProviderEngine.cs index c656092efff96..52c1afbafcbd0 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/RuntimeServiceProviderEngine.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/RuntimeServiceProviderEngine.cs @@ -11,7 +11,7 @@ internal sealed class RuntimeServiceProviderEngine : ServiceProviderEngine private RuntimeServiceProviderEngine() { } - public override Func RealizeService(ServiceCallSite callSite) + public override Func RealizeService(ServiceCallSite callSite) { return scope => { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs index e1f7cd2bae3a4..737c23d7f4445 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { @@ -12,7 +13,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup /// /// Type of service being cached /// - public Type Type { get; } + public Type? Type { get; } /// /// Reverse index of the service when resolved in IEnumerable<Type> where default instance gets slot 0. @@ -27,16 +28,20 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup /// public int Slot { get; } - public ServiceCacheKey(Type type, int slot) + public ServiceCacheKey(Type? type, int slot) { Type = type; Slot = slot; } - public bool Equals(ServiceCacheKey other) - { - return Type == other.Type && Slot == other.Slot; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(ServiceCacheKey other) => + Type == other.Type && Slot == other.Slot; + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is ServiceCacheKey other && Equals(other); public override int GetHashCode() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs index 626ecce4f2548..1ede82e09c914 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs @@ -16,10 +16,10 @@ protected ServiceCallSite(ResultCache cache) } public abstract Type ServiceType { get; } - public abstract Type ImplementationType { get; } + public abstract Type? ImplementationType { get; } public abstract CallSiteKind Kind { get; } public ResultCache Cache { get; } - public object Value { get; set; } + public object? Value { get; set; } public bool CaptureDisposable => ImplementationType == null || diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceLookupHelpers.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceLookupHelpers.cs index c17b501ef4b78..d41f9cb7cec4f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceLookupHelpers.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceLookupHelpers.cs @@ -12,27 +12,27 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup internal static class ServiceLookupHelpers { private const BindingFlags LookupFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - private static readonly MethodInfo ArrayEmptyMethodInfo = typeof(Array).GetMethod(nameof(Array.Empty)); + private static readonly MethodInfo ArrayEmptyMethodInfo = typeof(Array).GetMethod(nameof(Array.Empty))!; internal static readonly MethodInfo InvokeFactoryMethodInfo = typeof(Func) - .GetMethod(nameof(Func.Invoke), LookupFlags); + .GetMethod(nameof(Func.Invoke), LookupFlags)!; internal static readonly MethodInfo CaptureDisposableMethodInfo = typeof(ServiceProviderEngineScope) - .GetMethod(nameof(ServiceProviderEngineScope.CaptureDisposable), LookupFlags); + .GetMethod(nameof(ServiceProviderEngineScope.CaptureDisposable), LookupFlags)!; internal static readonly MethodInfo TryGetValueMethodInfo = typeof(IDictionary) - .GetMethod(nameof(IDictionary.TryGetValue), LookupFlags); + .GetMethod(nameof(IDictionary.TryGetValue), LookupFlags)!; internal static readonly MethodInfo ResolveCallSiteAndScopeMethodInfo = typeof(CallSiteRuntimeResolver) - .GetMethod(nameof(CallSiteRuntimeResolver.Resolve), LookupFlags); + .GetMethod(nameof(CallSiteRuntimeResolver.Resolve), LookupFlags)!; internal static readonly MethodInfo AddMethodInfo = typeof(IDictionary) - .GetMethod(nameof(IDictionary.Add), LookupFlags); + .GetMethod(nameof(IDictionary.Add), LookupFlags)!; internal static readonly MethodInfo MonitorEnterMethodInfo = typeof(Monitor) - .GetMethod(nameof(Monitor.Enter), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object), typeof(bool).MakeByRefType() }, null); + .GetMethod(nameof(Monitor.Enter), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object), typeof(bool).MakeByRefType() }, null)!; internal static readonly MethodInfo MonitorExitMethodInfo = typeof(Monitor) - .GetMethod(nameof(Monitor.Exit), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object) }, null); + .GetMethod(nameof(Monitor.Exit), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object) }, null)!; [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "Calling Array.Empty() is safe since the T doesn't have trimming annotations.")] diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngine.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngine.cs index 77cd2533759d9..978170fa995e2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngine.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngine.cs @@ -7,6 +7,6 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal abstract class ServiceProviderEngine { - public abstract Func RealizeService(ServiceCallSite callSite); + public abstract Func RealizeService(ServiceCallSite callSite); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs index 4ad8b1579a029..7f4598fecfc5e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.Extensions.Internal; @@ -14,16 +15,16 @@ internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvid internal IList Disposables => _disposables ?? (IList)Array.Empty(); private bool _disposed; - private List _disposables; + private List? _disposables; public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope) { - ResolvedServices = new Dictionary(); + ResolvedServices = new Dictionary(); RootProvider = provider; IsRootScope = isRootScope; } - internal Dictionary ResolvedServices { get; } + internal Dictionary ResolvedServices { get; } // This lock protects state on the scope, in particular, for the root scope, it protects // the list of disposable entries only, since ResolvedServices are cached on CallSites @@ -34,7 +35,7 @@ public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope) internal ServiceProvider RootProvider { get; } - public object GetService(Type serviceType) + public object? GetService(Type serviceType) { if (_disposed) { @@ -48,7 +49,8 @@ public object GetService(Type serviceType) public IServiceScope CreateScope() => RootProvider.CreateScope(); - internal object CaptureDisposable(object service) + [return: NotNullIfNotNull("service")] + internal object? CaptureDisposable(object? service) { if (ReferenceEquals(this, service) || !(service is IDisposable || service is IAsyncDisposable)) { @@ -91,7 +93,7 @@ internal object CaptureDisposable(object service) public void Dispose() { - List toDispose = BeginDispose(); + List? toDispose = BeginDispose(); if (toDispose != null) { @@ -111,7 +113,7 @@ public void Dispose() public ValueTask DisposeAsync() { - List toDispose = BeginDispose(); + List? toDispose = BeginDispose(); if (toDispose != null) { @@ -168,7 +170,7 @@ static async ValueTask Await(int i, ValueTask vt, List toDispose) } } - private List BeginDispose() + private List? BeginDispose() { lock (Sync) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/StackGuard.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/StackGuard.cs index a11c36192529b..fe58ab651bf97 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/StackGuard.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/StackGuard.cs @@ -65,7 +65,7 @@ private R RunOnEmptyStackCore(Func action, object state) try { // Using default scheduler rather than picking up the current scheduler. - Task task = Task.Factory.StartNew(action, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + Task task = Task.Factory.StartNew((Func)action, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // Avoid AsyncWaitHandle lazy allocation of ManualResetEvent in the rare case we finish quickly. if (!task.IsCompleted) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs index 9ed91ff5148c4..ffacbf9bbc052 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs @@ -2,12 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal static class ThrowHelper { + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowObjectDisposedException() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index db1c1e72e9349..1b22c43223519 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -15,16 +15,16 @@ namespace Microsoft.Extensions.DependencyInjection /// public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDisposable { - private readonly CallSiteValidator _callSiteValidator; + private readonly CallSiteValidator? _callSiteValidator; - private readonly Func> _createServiceAccessor; + private readonly Func> _createServiceAccessor; // Internal for testing internal ServiceProviderEngine _engine; private bool _disposed; - private ConcurrentDictionary> _realizedServices; + private ConcurrentDictionary> _realizedServices; internal CallSiteFactory CallSiteFactory { get; } @@ -39,7 +39,7 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv Root = new ServiceProviderEngineScope(this, isRootScope: true); _engine = GetEngine(); _createServiceAccessor = CreateServiceAccessor; - _realizedServices = new ConcurrentDictionary>(); + _realizedServices = new ConcurrentDictionary>(); CallSiteFactory = new CallSiteFactory(serviceDescriptors); // The list of built in services that aren't part of the list of service descriptors @@ -55,7 +55,7 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv if (options.ValidateOnBuild) { - List exceptions = null; + List? exceptions = null; foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors) { try @@ -83,7 +83,7 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// /// The type of the service to get. /// The service that was produced. - public object GetService(Type serviceType) => GetService(serviceType, Root); + public object? GetService(Type serviceType) => GetService(serviceType, Root); /// public void Dispose() @@ -115,14 +115,14 @@ private void OnResolve(Type serviceType, IServiceScope scope) _callSiteValidator?.ValidateResolution(serviceType, scope, Root); } - internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) + internal object? GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) { if (_disposed) { ThrowHelper.ThrowObjectDisposedException(); } - Func realizedService = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor); + Func realizedService = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor); OnResolve(serviceType, serviceProviderEngineScope); DependencyInjectionEventSource.Log.ServiceResolved(this, serviceType); var result = realizedService.Invoke(serviceProviderEngineScope); @@ -139,7 +139,7 @@ private void ValidateService(ServiceDescriptor descriptor) try { - ServiceCallSite callSite = CallSiteFactory.GetCallSite(descriptor, new CallSiteChain()); + ServiceCallSite? callSite = CallSiteFactory.GetCallSite(descriptor, new CallSiteChain()); if (callSite != null) { OnCreate(callSite); @@ -151,9 +151,9 @@ private void ValidateService(ServiceDescriptor descriptor) } } - private Func CreateServiceAccessor(Type serviceType) + private Func CreateServiceAccessor(Type serviceType) { - ServiceCallSite callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain()); + ServiceCallSite? callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain()); if (callSite != null) { DependencyInjectionEventSource.Log.CallSiteBuilt(this, serviceType, callSite); @@ -162,7 +162,7 @@ private Func CreateServiceAccessor(Type serv // Optimize singleton case if (callSite.Cache.Location == CallSiteResultCacheLocation.Root) { - object value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root); + object? value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root); return scope => value; } @@ -172,7 +172,7 @@ private Func CreateServiceAccessor(Type serv return _ => null; } - internal void ReplaceServiceAccessor(ServiceCallSite callSite, Func accessor) + internal void ReplaceServiceAccessor(ServiceCallSite callSite, Func accessor) { _realizedServices[callSite.ServiceType] = accessor; } diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs index 55902bd8a3a9b..5c8159051c66c 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs @@ -105,11 +105,7 @@ await Host.CreateDefaultBuilder() services.AddHostedService(); }) .RunConsoleAsync(); - }); - - remoteHandle.Process.WaitForExit(); - - Assert.Equal(124, remoteHandle.Process.ExitCode); + }, new RemoteInvokeOptions() { ExpectedExitCode = 124 }); } private class EnsureEnvironmentExitCodeWorker : BackgroundService @@ -130,6 +126,9 @@ await Task.Run(() => [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] public void EnsureEnvironmentExitDoesntHang() { + // SIGTERM is only handled on net6.0+, so the workaround to "clobber" the exit code is still in place on .NET Framework + int expectedExitCode = PlatformDetection.IsNetFramework ? 0 : 125; + using var remoteHandle = RemoteExecutor.Invoke(async () => { await Host.CreateDefaultBuilder() @@ -139,13 +138,7 @@ await Host.CreateDefaultBuilder() services.AddHostedService(); }) .RunConsoleAsync(); - }, new RemoteInvokeOptions() { TimeOut = 30_000 }); // give a 30 second time out, so if this does hang, it doesn't hang for the full timeout - - Assert.True(remoteHandle.Process.WaitForExit(30_000), "The hosted process should have exited within 30 seconds"); - - // SIGTERM is only handled on net6.0+, so the workaround to "clobber" the exit code is still in place on NetFramework - int expectedExitCode = PlatformDetection.IsNetFramework ? 0 : 125; - Assert.Equal(expectedExitCode, remoteHandle.Process.ExitCode); + }, new RemoteInvokeOptions() { TimeOut = 30_000, ExpectedExitCode = expectedExitCode }); // give a 30 second time out, so if this does hang, it doesn't hang for the full timeout } private class EnsureEnvironmentExitDoesntHangWorker : BackgroundService diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln index bf9829d652330..6f3c58066d303 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln @@ -1,9 +1,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32111.311 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{79CE8C7E-A4AF-413C-A54D-86F17073559C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{1491B9C9-955D-4DB0-B1D5-70137A78EAAE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn3.11", "gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{1491B9C9-955D-4DB0-B1D5-70137A78EAAE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{A5439E79-96D6-4F02-8DD0-23DFF979851D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.0", "gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{A5439E79-96D6-4F02-8DD0-23DFF979851D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{7F536552-0E2A-4642-B7CF-863727C2F9CD}" EndProject @@ -23,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{548DF5F7-790 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{7631380A-FB73-4241-9987-0891A21E9769}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{03F31CEE-D63E-4E7F-949F-139B33DC3385}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,14 +76,14 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {79CE8C7E-A4AF-413C-A54D-86F17073559C} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE} = {03F31CEE-D63E-4E7F-949F-139B33DC3385} + {A5439E79-96D6-4F02-8DD0-23DFF979851D} = {03F31CEE-D63E-4E7F-949F-139B33DC3385} + {7F536552-0E2A-4642-B7CF-863727C2F9CD} = {7631380A-FB73-4241-9987-0891A21E9769} + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} {C333EC5A-F386-4A01-AE20-12D499551304} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} - {1491B9C9-955D-4DB0-B1D5-70137A78EAAE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {A5439E79-96D6-4F02-8DD0-23DFF979851D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {F8CF3192-B902-4631-972A-C405FDECC48D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {7F536552-0E2A-4642-B7CF-863727C2F9CD} = {7631380A-FB73-4241-9987-0891A21E9769} {DAA1349E-960E-49EB-81F3-FF4F99D8A325} = {7631380A-FB73-4241-9987-0891A21E9769} + {F8CF3192-B902-4631-972A-C405FDECC48D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {450DA749-CBDC-4BDC-950F-8A491CF59D49} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs index 53dd062b5d4b4..69f87fdcd48f6 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs @@ -16,10 +16,18 @@ internal class Emitter private const int MaxLoggerMessageDefineArguments = 6; private const int DefaultStringBuilderCapacity = 1024; + private static readonly string s_generatedTypeSummary = + " " + + "This API supports the logging infrastructure and is not intended to be used directly from your code. " + + "It is subject to change in the future. " + + ""; private static readonly string s_generatedCodeAttribute = $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" + $"\"{typeof(Emitter).Assembly.GetName().Name}\", " + $"\"{typeof(Emitter).Assembly.GetName().Version}\")"; + private static readonly string s_editorBrowsableAttribute = + "global::System.ComponentModel.EditorBrowsableAttribute(" + + "global::System.ComponentModel.EditorBrowsableState.Never)"; private readonly StringBuilder _builder = new StringBuilder(DefaultStringBuilderCapacity); private bool _needEnumerationHelper; @@ -127,7 +135,9 @@ namespace {lc.Namespace} private void GenStruct(LoggerMethod lm, string nestedIndentation) { _builder.AppendLine($@" + {nestedIndentation}/// {s_generatedTypeSummary} {nestedIndentation}[{s_generatedCodeAttribute}] + {nestedIndentation}[{s_editorBrowsableAttribute}] {nestedIndentation}private readonly struct __{lm.Name}Struct : global::System.Collections.Generic.IReadOnlyList> {nestedIndentation}{{"); GenFields(lm, nestedIndentation); @@ -156,7 +166,7 @@ private void GenStruct(LoggerMethod lm, string nestedIndentation) {nestedIndentation}}} "); _builder.Append($@" - {nestedIndentation}public static string Format(__{lm.Name}Struct state, global::System.Exception? ex) => state.ToString(); + {nestedIndentation}public static readonly global::System.Func<__{lm.Name}Struct, global::System.Exception?, string> Format = (state, ex) => state.ToString(); {nestedIndentation}public int Count => {lm.TemplateParameters.Count + 1}; @@ -489,7 +499,9 @@ private void GenEnumerationHelper() if (_needEnumerationHelper) { _builder.Append($@" +/// {s_generatedTypeSummary} [{s_generatedCodeAttribute}] +[{s_editorBrowsableAttribute}] internal static class __LoggerMessageGenerator {{ public static string Enumerate(global::System.Collections.IEnumerable? enumerable) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index ad8a524b0fc8c..2f624f6cec974 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -339,17 +339,21 @@ public IReadOnlyList GetLogClasses(IEnumerable GetLogClasses(IEnumerable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs index 972fb1ec0488c..1cb4775b275b9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs @@ -1,6 +1,7 @@ // 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.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.Logging @@ -8,7 +9,7 @@ namespace Microsoft.Extensions.Logging /// /// Identifies a logging event. The primary identifier is the "Id" property, with the "Name" property providing a short description of this type of event. /// - public readonly struct EventId + public readonly struct EventId : IEquatable { /// /// Implicitly creates an EventId from the given . diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 8ca2bab854730..eb95f66e4f5a3 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -18,6 +18,7 @@ Microsoft.Extensions.Logging.LogLevel Microsoft.Extensions.Logging.Logger<T> Microsoft.Extensions.Logging.LoggerMessage Microsoft.Extensions.Logging.Abstractions.NullLogger + DisableMicrosoftExtensionsLoggingSourceGenerator diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/.editorconfig b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/.editorconfig new file mode 100644 index 0000000000000..e9356fee5e6d2 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/.editorconfig @@ -0,0 +1,4 @@ +# editorconfig.org + +[*.generated.txt] +insert_final_newline = false diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt index f4747ef679f83..5292db82ac8c8 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt @@ -5,7 +5,9 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithDefaultValues { + /// This API supports the logging infrastructure and is not intended to be used directly from your code. It is subject to change in the future. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] private readonly struct __M0Struct : global::System.Collections.Generic.IReadOnlyList> { @@ -15,7 +17,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses return $""; } - public static string Format(__M0Struct state, global::System.Exception? ex) => state.ToString(); + public static readonly global::System.Func<__M0Struct, global::System.Exception?, string> Format = (state, ex) => state.ToString(); public int Count => 1; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt index 1d1af4719fe40..6326923544aa9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt @@ -5,7 +5,9 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithDynamicLogLevel { + /// This API supports the logging infrastructure and is not intended to be used directly from your code. It is subject to change in the future. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] private readonly struct __M9Struct : global::System.Collections.Generic.IReadOnlyList> { @@ -15,7 +17,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses return $"M9"; } - public static string Format(__M9Struct state, global::System.Exception? ex) => state.ToString(); + public static readonly global::System.Func<__M9Struct, global::System.Exception?, string> Format = (state, ex) => state.ToString(); public int Count => 1; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt index 3387ec2da1a32..84611c6766f72 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt @@ -5,7 +5,9 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithMoreThan6Params { + /// This API supports the logging infrastructure and is not intended to be used directly from your code. It is subject to change in the future. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] private readonly struct __Method9Struct : global::System.Collections.Generic.IReadOnlyList> { private readonly global::System.Int32 _p1; @@ -41,7 +43,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses return $"M9 {p1} {p2} {p3} {p4} {p5} {p6} {p7}"; } - public static string Format(__Method9Struct state, global::System.Exception? ex) => state.ToString(); + public static readonly global::System.Func<__Method9Struct, global::System.Exception?, string> Format = (state, ex) => state.ToString(); public int Count => 8; @@ -88,7 +90,9 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses } } } +/// This API supports the logging infrastructure and is not intended to be used directly from your code. It is subject to change in the future. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] +[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] internal static class __LoggerMessageGenerator { public static string Enumerate(global::System.Collections.IEnumerable? enumerable) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index d55bf4a8028d5..eda529fade4ef 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -8,7 +8,6 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] public class LoggerMessageGeneratedCodeTests { [Fact] @@ -341,6 +340,20 @@ public void LevelTests() Assert.Equal(LogLevel.Warning, logger.LastLogLevel); Assert.Equal(1, logger.CallCount); Assert.Equal(11, logger.LastEventId.Id); + + logger.Reset(); + LevelTestExtensions.M12(logger, LogLevel.Trace); + Assert.Null(logger.LastException); + Assert.Equal("M12 Trace", logger.LastFormattedString); + Assert.Equal(LogLevel.Trace, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + LevelTestExtensions.M13(logger, LogLevel.Trace); + Assert.Null(logger.LastException); + Assert.Equal("M13 Microsoft.Extensions.Logging.Generators.Tests.MockLogger", logger.LastFormattedString); + Assert.Equal(LogLevel.Trace, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); } [Fact] @@ -361,6 +374,13 @@ public void ExceptionTests() Assert.Equal("M1 System.ArgumentException: Bar", logger.LastFormattedString); Assert.Equal(LogLevel.Debug, logger.LastLogLevel); Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ExceptionTestExtensions.M2(logger, "One", new ArgumentException("Foo")); + Assert.Equal("Foo", logger.LastException!.Message); + Assert.Equal("M2 One: System.ArgumentException: Foo", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs index cc0b8ba1adfe3..8ebb2ab8c0aa2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs @@ -10,7 +10,8 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", typeof(PlatformDetection), nameof(PlatformDetection.IsWindows), nameof(PlatformDetection.IsMonoRuntime))] public class LoggerMessageGeneratorEmitterTests { [Fact] @@ -27,7 +28,7 @@ public async Task TestEmitter() new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly }, new[] { testSourceCode }).ConfigureAwait(false); - Assert.Empty(d); + Assert.True(src.Contains("WithDiagnostics") ? !d.IsEmpty : d.IsEmpty); Assert.Single(r); } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index 3c3ce17ef0b18..4697e5603cd0f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] public class LoggerMessageGeneratorParserTests { [Fact] @@ -204,11 +204,15 @@ partial class C { [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {ex} {ex2}"")] static partial void M1(ILogger logger, System.Exception ex, System.Exception ex2); + + [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2 {arg1}: {ex}"")] + static partial void M2(ILogger logger, string arg1, System.Exception ex); } "); - Assert.Single(diagnostics); + Assert.Equal(2, diagnostics.Count); Assert.Equal(DiagnosticDescriptors.ShouldntMentionExceptionInMessage.Id, diagnostics[0].Id); + Assert.Equal(DiagnosticDescriptors.ShouldntMentionExceptionInMessage.Id, diagnostics[1].Id); } [Fact] @@ -234,11 +238,15 @@ partial class C { [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {logger}"")] static partial void M1(ILogger logger); + + [LoggerMessage(EventId = 2, Message = ""M2 {logger}"")] + static partial void M2(ILogger logger, LogLevel level); } "); - Assert.Single(diagnostics); + Assert.Equal(2, diagnostics.Count); Assert.Equal(DiagnosticDescriptors.ShouldntMentionLoggerInMessage.Id, diagnostics[0].Id); + Assert.Equal(DiagnosticDescriptors.ShouldntMentionLoggerInMessage.Id, diagnostics[1].Id); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs new file mode 100644 index 0000000000000..8a2299cf864cd --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs @@ -0,0 +1,15 @@ +// 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 Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class ExceptionTestExtensions + { +#pragma warning disable SYSLIB1013 + [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = "M2 {arg1}: {ex}")] + public static partial void M2(ILogger logger, string arg1, Exception ex); +#pragma warning disable SYSLIB1013 + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs new file mode 100644 index 0000000000000..aabcb67ae4bd0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class LevelTestExtensions + { +#pragma warning disable SYSLIB1002 + [LoggerMessage(EventId = 12, Message = "M12 {level}")] + public static partial void M12(ILogger logger, LogLevel level); +#pragma warning restore SYSLIB1002 + +#pragma warning disable SYSLIB1018 + [LoggerMessage(EventId = 13, Message = "M13 {logger}")] + public static partial void M13(ILogger logger, LogLevel level); +#pragma warning restore SYSLIB1018 + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs index 8cac9db32a976..c315783ab58c0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs @@ -41,6 +41,7 @@ public partial class ConsoleFormatterOptions { public ConsoleFormatterOptions() { } public bool IncludeScopes { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] public string TimestampFormat { get { throw null; } set { } } public bool UseUtcTimestamp { get { throw null; } set { } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj index ba0bf1821d39d..71aeb235fd3b0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj @@ -14,6 +14,10 @@ + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs index 0fcdd2f038ef9..e4a9800ad6e3e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace Microsoft.Extensions.Logging.Console @@ -21,6 +22,7 @@ public ConsoleFormatterOptions() { } /// /// Gets or sets format string used to format timestamp in logging messages. Defaults to null. /// + [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] public string TimestampFormat { get; set; } /// diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj index 9256474085a47..e3bc7f50b436b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) @@ -38,6 +38,10 @@ + + + + @@ -63,4 +67,4 @@ - \ No newline at end of file + diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index cbc3d322a87a9..fc0fb68ac6e7e 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -3760,6 +3760,14 @@ "any", "base" ], + "linux-armv6": [ + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "linux-mips64": [ "linux-mips64", "linux", @@ -4328,6 +4336,26 @@ "any", "base" ], + "manjaro": [ + "manjaro", + "arch", + "linux", + "unix", + "any", + "base" + ], + "manjaro-x64": [ + "manjaro-x64", + "manjaro", + "arch-x64", + "arch", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "ol": [ "ol", "rhel", @@ -8228,6 +8256,12 @@ "any", "base" ], + "unix-armv6": [ + "unix-armv6", + "unix", + "any", + "base" + ], "unix-mips64": [ "unix-mips64", "unix", @@ -8882,4 +8916,4 @@ "any", "base" ] -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index b2070efde5b7c..0b71f880e893d 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -1504,6 +1504,12 @@ "unix-loongarch64" ] }, + "linux-armv6": { + "#import": [ + "linux", + "unix-armv6" + ] + }, "linux-mips64": { "#import": [ "linux", @@ -1758,6 +1764,17 @@ "maccatalyst.14-x64" ] }, + "manjaro": { + "#import": [ + "arch" + ] + }, + "manjaro-x64": { + "#import": [ + "manjaro", + "arch-x64" + ] + }, "ol": { "#import": [ "rhel" @@ -3433,6 +3450,11 @@ "unix" ] }, + "unix-armv6": { + "#import": [ + "unix" + ] + }, "unix-mips64": { "#import": [ "unix" @@ -3777,4 +3799,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index b66931b24edf8..da7960a1f5785 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -3,11 +3,11 @@ any - x64;x86;arm;armel;arm64;loongarch64;mips64;s390x + x64;x86;arm;armv6;armel;arm64;loongarch64;mips64;s390x unix - x64;x86;arm;armel;arm64;loongarch64;mips64;s390x + x64;x86;arm;armv6;armel;arm64;loongarch64;mips64;s390x linux @@ -31,6 +31,11 @@ x64 + + arch + x64 + + any wasm diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb index 77219110807c4..d97358dcd5a5b 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb @@ -375,7 +375,7 @@ Namespace Microsoft.VisualBasic.FileIO Public Function PeekChars(ByVal numberOfChars As Integer) As String If numberOfChars <= 0 Then - Throw GetArgumentExceptionWithArgName("numberOfChars", SR.TextFieldParser_NumberOfCharsMustBePositive, "numberOfChars") + Throw GetArgumentExceptionWithArgName("numberOfChars", SR.TextFieldParser_NumberOfCharsMustBePositive) End If If m_Reader Is Nothing Or m_Buffer Is Nothing Then @@ -1151,7 +1151,7 @@ Namespace Microsoft.VisualBasic.FileIO Dim Bound As Integer = Widths.Length - 1 For i As Integer = 0 To Bound - 1 If Widths(i) < 1 Then - Throw GetArgumentExceptionWithArgName("FieldWidths", SR.TextFieldParser_FieldWidthsMustPositive, "FieldWidths") + Throw GetArgumentExceptionWithArgName("FieldWidths", SR.TextFieldParser_FieldWidthsMustPositive) End If Next End Sub @@ -1163,11 +1163,11 @@ Namespace Microsoft.VisualBasic.FileIO ''' Private Sub ValidateAndEscapeDelimiters() If m_Delimiters Is Nothing Then - Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing, "Delimiters") + Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing) End If If m_Delimiters.Length = 0 Then - Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing, "Delimiters") + Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing) End If Dim Length As Integer = m_Delimiters.Length diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs b/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs index d9f981b242598..a2a8e28e8d17b 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs @@ -620,8 +620,7 @@ static void remoteWrite(string fileName, string text) } }, fileName, - text, - new RemoteInvokeOptions() { ExpectedExitCode = 0 }).Dispose(); + text).Dispose(); } } diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs index 56cbc26afe977..49eeecff31ab0 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs @@ -64,7 +64,7 @@ private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subK return baseKey; } - throw new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(keyName)), nameof(keyName)); + throw new ArgumentException(SR.Arg_RegInvalidKeyName, nameof(keyName)); } public static object? GetValue(string keyName, string? valueName, object? defaultValue) diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index ea5a83315216d..c82feafee9f0c 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -728,16 +728,16 @@ private static void ValidateKeyName(string name) throw new ArgumentNullException(nameof(name)); } - int nextSlash = name.IndexOf("\\", StringComparison.OrdinalIgnoreCase); + int nextSlash = name.IndexOf('\\'); int current = 0; - while (nextSlash != -1) + while (nextSlash >= 0) { if ((nextSlash - current) > MaxKeyLength) { throw new ArgumentException(SR.Arg_RegKeyStrLenBug, nameof(name)); } current = nextSlash + 1; - nextSlash = name.IndexOf("\\", current, StringComparison.OrdinalIgnoreCase); + nextSlash = name.IndexOf('\\', current); } if ((name.Length - current) > MaxKeyLength) diff --git a/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs index f5ff293848ffa..f16e03965ed18 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs @@ -19,7 +19,7 @@ public sealed partial class RegistrySecurity : NativeObjectSecurity break; case Interop.Errors.ERROR_INVALID_NAME: - exception = new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(name))); + exception = new ArgumentException(SR.Arg_RegInvalidKeyName, nameof(name)); break; case Interop.Errors.ERROR_INVALID_HANDLE: diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj index 007fd6f60fa58..0ccd62c3f8c3a 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj @@ -35,6 +35,8 @@ Microsoft.Win32.SystemEvents Link="Common\Interop\Windows\User32\Interop.DispatchMessage.cs" /> + Link="Common\Interop\Windows\User32\Interop.MSG.cs" /> - + ? s_threadCallbackList; // list of Delegates private static volatile int s_threadCallbackMessage; - private static volatile ManualResetEvent? s_eventThreadTerminated; // Per-instance data that is isolated to the window thread. private volatile IntPtr _windowHandle; @@ -1071,7 +1070,7 @@ private static void RemoveEventHandler(object key, Delegate? value) private static void Shutdown() { - if (s_systemEvents != null && s_systemEvents._windowHandle != IntPtr.Zero) + if (s_systemEvents != null) { lock (s_procLockObject) { @@ -1080,17 +1079,22 @@ private static void Shutdown() // If we are using system events from another thread, request that it terminate if (s_windowThread != null) { - s_eventThreadTerminated = new ManualResetEvent(false); - #if DEBUG int pid; int thread = Interop.User32.GetWindowThreadProcessId(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), out pid); Debug.Assert(thread != Interop.Kernel32.GetCurrentThreadId(), "Don't call Shutdown on the system events thread"); #endif - Interop.User32.PostMessageW(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), Interop.User32.WM_QUIT, IntPtr.Zero, IntPtr.Zero); - s_eventThreadTerminated.WaitOne(); - s_windowThread.Join(); // avoids an AppDomainUnloaded exception on our background thread. + // The handle could be valid, Zero or invalid depending on the state of the thread + // that is processing the messages. We optimistically expect it to be valid to + // notify the thread to shutdown. The Zero or invalid values should be present + // only when the thread is already shutting down due to external factors. + if (s_systemEvents._windowHandle != IntPtr.Zero) + { + Interop.User32.PostMessageW(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), Interop.User32.WM_QUIT, IntPtr.Zero, IntPtr.Zero); + } + + s_windowThread.Join(); } else { @@ -1218,6 +1222,11 @@ private IntPtr WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) OnTimerElapsed(wParam); break; + case Interop.User32.WM_DESTROY: + Interop.User32.PostQuitMessage(0); + _windowHandle = IntPtr.Zero; + break; + default: // If we received a thread execute message, then execute it. if (msg == s_threadCallbackMessage && msg != 0) @@ -1248,33 +1257,10 @@ private void WindowThreadProc() { Interop.User32.MSG msg = default(Interop.User32.MSG); - bool keepRunning = true; - - // Blocking on a GetMessage() call prevents the EE from being able to unwind - // this thread properly (e.g. during AppDomainUnload). So, we use PeekMessage() - // and sleep so we always block in managed code instead. - while (keepRunning) + while (Interop.User32.GetMessageW(ref msg, _windowHandle, 0, 0) > 0) { - int ret = Interop.User32.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, Interop.User32.QS_ALLINPUT, Interop.User32.MWMO_INPUTAVAILABLE); - - if (ret == Interop.User32.WAIT_TIMEOUT) - { - Thread.Sleep(1); - } - else - { - while (Interop.User32.PeekMessageW(ref msg, IntPtr.Zero, 0, 0, Interop.User32.PM_REMOVE)) - { - if (msg.message == Interop.User32.WM_QUIT) - { - keepRunning = false; - break; - } - - Interop.User32.TranslateMessage(ref msg); - Interop.User32.DispatchMessageW(ref msg); - } - } + Interop.User32.TranslateMessage(ref msg); + Interop.User32.DispatchMessageW(ref msg); } } @@ -1293,10 +1279,6 @@ private void WindowThreadProc() } Dispose(); - if (s_eventThreadTerminated != null) - { - s_eventThreadTerminated.Set(); - } } // A class that helps fire events on the right thread. diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx b/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx index 96464aac30db8..bb14b9a2d94d6 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx @@ -122,15 +122,9 @@ Cannot create timer. - - Cannot get temporary file name - Cannot end timer. - - System event notifications are not supported under the current context. Server processes, for example, may not support global system event notifications. - '{1}' is not a valid value for '{0}'. '{0}' must be greater than {2}. diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj index b74ffd4352b8b..79b0db6d25a9a 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj @@ -25,6 +25,7 @@ + diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs b/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs new file mode 100644 index 0000000000000..d8012da78db70 --- /dev/null +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs @@ -0,0 +1,33 @@ +// 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.Threading; +using Microsoft.DotNet.RemoteExecutor; +using Xunit; +using static Interop; + +namespace Microsoft.Win32.SystemEventsTests +{ + public abstract class ShutdownTest : SystemEventsTest + { + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore))] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] + public void ShutdownThroughRestartManager() + { + RemoteExecutor.Invoke(() => + { + // Register any event to ensure that SystemEvents get initialized + SystemEvents.TimeChanged += (o, e) => { }; + + // Fake Restart Manager behavior by sending external WM_CLOSE message + SendMessage(Interop.User32.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + + // Emulate calling the Shutdown event + var shutdownMethod = typeof(SystemEvents).GetMethod("Shutdown", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type[0], null); + Assert.NotNull(shutdownMethod); + shutdownMethod.Invoke(null, null); + }).Dispose(); + } + } +} diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets index 6a402a0cfeb09..74fd8ebb92b2c 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets @@ -10,7 +10,9 @@ Pack="true" /> - + <Project> @@ -25,4 +27,4 @@ Lines="$(PropsFileContents)" Overwrite="true" /> - \ No newline at end of file + diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets index 31fe16ae8c6f1..aa5b94b12c7a6 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets @@ -4,6 +4,8 @@ @@ -44,6 +46,6 @@ namespace Microsoft.XmlSerializer.Generator File="$(IntermediateOutputPath)ThisAssembly.cs" Lines="$(ThisAssemblyCsContents)" Overwrite="true" - Encoding="Unicode"/> + Encoding="Unicode" /> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs index aa8d7636cfbca..2562372c666b4 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs @@ -15,7 +15,9 @@ public partial class ImmutableDictionary /// /// Contains all the key/values in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket : IEnumerable> +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs index 82fd48fbc62e5..04ca794da7808 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs @@ -30,7 +30,9 @@ internal enum OperationResult /// /// Contains all the keys in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.NonGeneric/tests/ReadOnlyCollectionBaseTests.cs b/src/libraries/System.Collections.NonGeneric/tests/ReadOnlyCollectionBaseTests.cs index 426a0bad6f565..f4f0820f18725 100644 --- a/src/libraries/System.Collections.NonGeneric/tests/ReadOnlyCollectionBaseTests.cs +++ b/src/libraries/System.Collections.NonGeneric/tests/ReadOnlyCollectionBaseTests.cs @@ -139,7 +139,7 @@ public static void IListProperties() public static void VirtualMethods() { VirtualTestReadOnlyCollection collectionBase = new VirtualTestReadOnlyCollection(); - Assert.Equal(collectionBase.Count, int.MinValue); + Assert.Equal(int.MinValue, collectionBase.Count); Assert.Null(collectionBase.GetEnumerator()); } diff --git a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs index 1864717141ca4..00fc77efe910c 100644 --- a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs +++ b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs @@ -6,7 +6,7 @@ namespace System.Collections.Specialized { - public partial struct BitVector32 + public partial struct BitVector32 : System.IEquatable { private int _dummyPrimitive; public BitVector32(System.Collections.Specialized.BitVector32 value) { throw null; } @@ -18,11 +18,12 @@ public partial struct BitVector32 public static int CreateMask(int previous) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue, System.Collections.Specialized.BitVector32.Section previous) { throw null; } + public bool Equals(System.Collections.Specialized.BitVector32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } public static string ToString(System.Collections.Specialized.BitVector32 value) { throw null; } - public readonly partial struct Section + public readonly partial struct Section : System.IEquatable { private readonly int _dummyPrimitive; public short Mask { get { throw null; } } diff --git a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs index ce4ba761ab7af..60a2580cfb6fd 100644 --- a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs +++ b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs @@ -10,7 +10,7 @@ namespace System.Collections.Specialized /// Provides a simple light bit vector with easy integer or Boolean access to /// a 32 bit storage. /// - public struct BitVector32 + public struct BitVector32 : IEquatable { private uint _data; @@ -151,7 +151,12 @@ private static Section CreateSectionHelper(short maxValue, short priorMask, shor return new Section(mask, offset); } - public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && _data == other._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(BitVector32 other) => _data == other._data; public override int GetHashCode() => _data.GetHashCode(); @@ -182,7 +187,7 @@ public override string ToString() /// /// Represents an section of the vector that can contain a integer number. /// - public readonly struct Section + public readonly struct Section : IEquatable
{ private readonly short _mask; private readonly short _offset; diff --git a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs index 61734a09b741f..69453b6c574d5 100644 --- a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs +++ b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs @@ -518,17 +518,32 @@ public static void EqualsTest() Assert.True(new BitVector32(0).Equals(original)); Assert.True(original.Equals(new BitVector32(0))); + Assert.True(original.Equals((object)original)); + Assert.True(new BitVector32().Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32())); + Assert.True(new BitVector32(0).Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32(0))); + BitVector32 other = new BitVector32(int.MaxValue / 2 - 1); Assert.True(other.Equals(other)); Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals(other)); Assert.True(other.Equals(new BitVector32(int.MaxValue / 2 - 1))); + Assert.True(other.Equals((object)other)); + Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals((object)other)); + Assert.True(other.Equals((object)new BitVector32(int.MaxValue / 2 - 1))); + Assert.False(other.Equals(original)); Assert.False(original.Equals(other)); Assert.False(other.Equals(null)); Assert.False(original.Equals(null)); Assert.False(other.Equals(int.MaxValue / 2 - 1)); Assert.False(original.Equals(0)); + + Assert.False(other.Equals((object)original)); + Assert.False(original.Equals((object)other)); + Assert.False(other.Equals(int.MaxValue / 2 - 1)); + Assert.False(original.Equals(0)); } [Fact] diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs index c78333ddf6433..cc7dfb6120ef1 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs @@ -235,7 +235,7 @@ public RangeAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMember [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)] public partial class RegularExpressionAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { - public RegularExpressionAttribute(string pattern) { } + public RegularExpressionAttribute([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { } public int MatchTimeoutInMilliseconds { get { throw null; } set { } } public string Pattern { get { throw null; } } public override string FormatErrorMessage(string name) { throw null; } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs index e7f4eb1db432e..cf2ec8a7697c2 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs @@ -1,6 +1,7 @@ // 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.CodeAnalysis; using System.Globalization; using System.Text.RegularExpressions; @@ -17,7 +18,7 @@ public class RegularExpressionAttribute : ValidationAttribute /// Constructor that accepts the regular expression pattern ///
/// The regular expression to use. It cannot be null. - public RegularExpressionAttribute(string pattern) + public RegularExpressionAttribute([StringSyntax(StringSyntaxAttribute.Regex)] string pattern) : base(() => SR.RegexAttribute_ValidationError) { Pattern = pattern; diff --git a/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs b/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs index f095d38c04546..ab5b9a5ac0076 100644 --- a/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs +++ b/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs @@ -44,8 +44,7 @@ public DiscoveredCatalog() : base("") { } } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ShouldSucceed() { var rb = new RegistrationBuilder(); @@ -174,8 +173,7 @@ private interface IGenericInterface { } [Export(typeof(IGenericInterface<>))] private class ClassExportingInterface : IGenericInterface { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void GenericInterfaceExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ClassExportingInterface<>)); @@ -188,8 +186,7 @@ private class GenericBaseClass { } [Export(typeof(GenericBaseClass<>))] private class ClassExportingBaseClass : GenericBaseClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void GenericBaseClassExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ClassExportingBaseClass<>)); @@ -211,8 +208,7 @@ public void GenericExportInRegistrationBuilder() [Export(typeof(ExplicitGenericClass<>))] private class ExplicitGenericClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ExplicitGenericExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ExplicitGenericClass<>)); @@ -223,8 +219,7 @@ public void ExplicitGenericExportInRegistrationBuilder() [Export(typeof(ExplicitGenericClass<,>))] private class ExplicitGenericClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ExplicitGenericArity2ExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ExplicitGenericClass<,>)); diff --git a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs index f55f6b216d37f..60accaee91e87 100644 --- a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs +++ b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs @@ -608,7 +608,7 @@ public ImportDefinition(System.Linq.Expressions.Expression { private object _dummy; private int _dummyPrimitive; @@ -616,6 +616,7 @@ public partial struct LazyMemberInfo public LazyMemberInfo(System.Reflection.MemberTypes memberType, System.Func accessorsCreator) { throw null; } public LazyMemberInfo(System.Reflection.MemberTypes memberType, params System.Reflection.MemberInfo[] accessors) { throw null; } public System.Reflection.MemberTypes MemberType { get { throw null; } } + public bool Equals(System.ComponentModel.Composition.ReflectionModel.LazyMemberInfo other) { throw null; } public override bool Equals(object? obj) { throw null; } public System.Reflection.MemberInfo[] GetAccessors() { throw null; } public override int GetHashCode() { throw null; } diff --git a/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx index 8899ffb3aab23..683d709992edb 100644 --- a/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx @@ -72,9 +72,6 @@ '{0}' cannot contain a null (Nothing in Visual Basic) element. - - Assembly file {0} is either not found or not a dll or exe file. - No exports were found that match the constraint: {0} @@ -129,12 +126,6 @@ The Type '{0}' supplied is not a valid Metadata View. - - A call to Compose occurred during a call to Compose on the same CompositionContainer object. Use the IsComposing property on CompositionContainer to ensure a composition is not already in progress before calling Compose. - - - This export does not support the metadata item '{0}'. - Interface '{0}' is not a valid MetadataView; MetadataViews do not support non-public interfaces, and interfaces that contain members that are not properties. @@ -144,9 +135,6 @@ The {0} member must be overridden by a derived class. - - The underlying dictionary is read-only. - This property cannot be set after the object's public surface has been accessed. @@ -357,9 +345,6 @@ The composable part definition '{0}' was ignored because the export '{1}' has different generic parameters than the part type. - - 'reflectionContext' must be a type that is assignable from System.Reflection.ReflectionContext. - '{0}' returns a mapped type that is a reflection-only type which is not supported. @@ -369,15 +354,9 @@ The implementation type for the MetadataView '{0} can not be null. - - A CreationPolicy of '(0)' can not be applied to an Import that is not an ExportFactory. - ExportFactory subclass '{0}' can not have more than two generic parameters. - - ScopingPolicyCatalog does not support catalog mutation. - This CompositionService does not support catalog changes. diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs index 480e339c4080f..02d1f811e71b7 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs @@ -8,7 +8,7 @@ namespace System.ComponentModel.Composition.ReflectionModel { - public struct LazyMemberInfo + public struct LazyMemberInfo : IEquatable { private readonly MemberTypes _memberType; private MemberInfo?[]? _accessors; @@ -106,31 +106,32 @@ public override int GetHashCode() throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - public override bool Equals(object? obj) - { - if (obj is not LazyMemberInfo that) - { - return false; - } + public override bool Equals(object? obj) => + obj is LazyMemberInfo other && Equals(other); + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(LazyMemberInfo other) + { // Different member types mean different members - if (_memberType != that._memberType) + if (_memberType != other._memberType) { return false; } // if any of the lazy memebers create accessors in a delay-loaded fashion, we simply compare the creators - if ((_accessorsCreator != null) || (that._accessorsCreator != null)) + if ((_accessorsCreator != null) || (other._accessorsCreator != null)) { - return object.Equals(_accessorsCreator, that._accessorsCreator); + return object.Equals(_accessorsCreator, other._accessorsCreator); } // we are dealing with explicitly passed accessors in both cases - if (_accessors == null || that._accessors == null) + if (_accessors == null || other._accessors == null) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - return _accessors.SequenceEqual(that._accessors); + return _accessors.SequenceEqual(other._accessors); } public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right) diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs index 333dd8e473bb6..712637375d096 100644 --- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs +++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs @@ -84,19 +84,12 @@ internal static void Constructor_ValueAsCodebaseArgument_ShouldSetAssemblyProper } } - internal static void Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad(Func catalogCreator) + internal static void Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException(Func catalogCreator) { string filename = Path.GetTempFileName(); using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None)) { - if (PlatformDetection.IsWindows) // File locking is Windows specific. - { - Assert.Throws(() => catalogCreator(filename)); - } - else - { - Assert.Throws(() => catalogCreator(filename)); - } + Assert.Throws(() => catalogCreator(filename)); } } @@ -184,7 +177,7 @@ public void Constructor1_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor1_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s); }); @@ -294,7 +287,7 @@ public void Constructor2_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor2_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, new AssemblyCatalogTestsReflectionContext()); }); @@ -403,7 +396,7 @@ public void Constructor3_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor3_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, (ICompositionElement)new AssemblyCatalog(s)); }); @@ -511,7 +504,7 @@ public void Constructor4_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor4_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, new AssemblyCatalogTestsReflectionContext(), (ICompositionElement)new AssemblyCatalog(s)); }); diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index 510fffca71406..8fe3c9a37f821 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -2164,7 +2164,7 @@ public InstanceDescriptor(System.Reflection.MemberInfo? member, System.Collectio public object? Invoke() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct MemberRelationship + public readonly partial struct MemberRelationship : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -2173,6 +2173,7 @@ public readonly partial struct MemberRelationship public bool IsEmpty { get { throw null; } } public System.ComponentModel.MemberDescriptor Member { get { throw null; } } public object? Owner { get { throw null; } } + public bool Equals(System.ComponentModel.Design.Serialization.MemberRelationship other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.ComponentModel.Design.Serialization.MemberRelationship left, System.ComponentModel.Design.Serialization.MemberRelationship right) { throw null; } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx index e9dd12b50616d..f607a8a2fe91c 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx @@ -193,9 +193,6 @@ The specified character value is not allowed for this property. - - The Mask value cannot be null or empty. - The specified mask contains invalid characters. @@ -253,4 +250,4 @@ BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information. - \ No newline at end of file + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs index 6691792d7fcfe..090fa91accbf7 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs @@ -153,7 +153,7 @@ private static void ThrowRelationshipNotSupported(MemberRelationship source, Mem /// /// Used as storage in our relationship table /// - private struct RelationshipEntry + private struct RelationshipEntry : IEquatable { internal WeakReference _owner; internal MemberDescriptor _member; @@ -169,20 +169,19 @@ internal RelationshipEntry(MemberRelationship rel) public override bool Equals([NotNullWhen(true)] object? o) { Debug.Assert(o is RelationshipEntry, "This is only called indirectly from a dictionary only containing RelationshipEntry structs."); - return this == (RelationshipEntry)o; + return Equals((RelationshipEntry)o); } - public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) + public bool Equals(RelationshipEntry other) { - object? owner1 = (re1._owner.IsAlive ? re1._owner.Target : null); - object? owner2 = (re2._owner.IsAlive ? re2._owner.Target : null); - return owner1 == owner2 && re1._member.Equals(re2._member); + object? owner1 = (_owner.IsAlive ? _owner.Target : null); + object? owner2 = (other._owner.IsAlive ? other._owner.Target : null); + return owner1 == owner2 && _member.Equals(other._member); } - public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) - { - return !(re1 == re2); - } + public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) => re1.Equals(re2); + + public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) => !re1.Equals(re2); public override int GetHashCode() => _hashCode; } @@ -191,7 +190,7 @@ public override bool Equals([NotNullWhen(true)] object? o) /// /// This class represents a single relationship between an object and a member. /// - public readonly struct MemberRelationship + public readonly struct MemberRelationship : IEquatable { public static readonly MemberRelationship Empty; @@ -222,37 +221,26 @@ public MemberRelationship(object owner, MemberDescriptor member) /// /// Infrastructure support to make this a first class struct /// - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is MemberRelationship rel && rel.Owner == Owner && rel.Member == Member; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is MemberRelationship rel && Equals(rel); /// /// Infrastructure support to make this a first class struct /// - public override int GetHashCode() - { - if (Owner == null) - { - return base.GetHashCode(); - } + public bool Equals(MemberRelationship other) => other.Owner == Owner && other.Member == Member; - return Owner.GetHashCode() ^ Member.GetHashCode(); - } /// /// Infrastructure support to make this a first class struct /// - public static bool operator ==(MemberRelationship left, MemberRelationship right) - { - return left.Owner == right.Owner && left.Member == right.Member; - } + public override int GetHashCode() => Owner is null ? base.GetHashCode() : Owner.GetHashCode() ^ Member.GetHashCode(); /// /// Infrastructure support to make this a first class struct /// - public static bool operator !=(MemberRelationship left, MemberRelationship right) - { - return !(left == right); - } + public static bool operator ==(MemberRelationship left, MemberRelationship right) => left.Equals(right); + + /// + /// Infrastructure support to make this a first class struct + /// + public static bool operator !=(MemberRelationship left, MemberRelationship right) => !left.Equals(right); } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs index 2190f32299fbb..7aa25ce5bdf63 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs @@ -11,7 +11,7 @@ namespace System.ComponentModel /// Provides a subset of the surface area, using volatile /// operations for reads and interlocked operations for writes. ///
- internal struct InterlockedBitVector32 + internal struct InterlockedBitVector32 : IEquatable { private int _data; @@ -44,7 +44,9 @@ public static int CreateMask(int previous) return previous == 0 ? 1 : previous << 1; } - public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 vector && _data == vector._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 other && Equals(other); + + public bool Equals(InterlockedBitVector32 other) => _data == other._data; public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs index 16ebdaf6ab300..5810df7258e5f 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs @@ -227,10 +227,7 @@ public MaskedTextProvider(string mask, CultureInfo? culture, char passwordChar, ///
public MaskedTextProvider(string mask, CultureInfo? culture, bool allowPromptAsInput, char promptChar, char passwordChar, bool restrictToAscii) { - if (string.IsNullOrEmpty(mask)) - { - throw new ArgumentException(SR.MaskedTextProviderMaskNullOrEmpty, nameof(mask)); - } + ArgumentException.ThrowIfNullOrEmpty(mask); foreach (char c in mask) { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs index 9037db5175274..9c0393da53ab3 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs @@ -50,7 +50,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destina if (values.Length != 4) { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, "text", text, "x, y, width, height")); + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "x, y, width, height")); } return new Rectangle(values[0], values[1], values[2], values[3]); diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/ContainerTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/ContainerTests.cs index 418d0c1c270d7..f1f331994a934 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/ContainerTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/ContainerTests.cs @@ -400,7 +400,7 @@ public void Add_SetSiteNameDuplicate_ThrowsArgumentException() container.Add(component1, "Name1"); container.Add(component2, "Name2"); - Assert.Throws(null, () => component1.Site.Name = "Name2"); + AssertExtensions.Throws(null, () => component1.Site.Name = "Name2"); } [Fact] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs index 9519d2f8b3918..2ef721735a12a 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs @@ -84,7 +84,7 @@ public void Indexer_SetNotSupported_ThrowsArgumentException(object owner) MemberRelationship source = new MemberRelationship(owner, member); var service = new NotSupportingMemberRelationshipService(); - Assert.Throws(null, () => service[source] = source); + AssertExtensions.Throws(null, () => service[source] = source); } private class TestClass diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/ServiceContainerTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/ServiceContainerTests.cs index 3fa5aa15c50b9..001abff49fa2d 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/ServiceContainerTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/ServiceContainerTests.cs @@ -224,9 +224,9 @@ public void AddService_NullServiceInstance_ThrowsArgumentNullException() public void AddService_ServiceInstanceNotInstanceOfType_ThrowsArgumentException() { var container = new ServiceContainer(); - Assert.Throws(null, () => container.AddService(typeof(int), new object())); - Assert.Throws(null, () => container.AddService(typeof(int), new object(), true)); - Assert.Throws(null, () => container.AddService(typeof(int), new object(), false)); + AssertExtensions.Throws(null, () => container.AddService(typeof(int), new object())); + AssertExtensions.Throws(null, () => container.AddService(typeof(int), new object(), true)); + AssertExtensions.Throws(null, () => container.AddService(typeof(int), new object(), false)); } [Fact] diff --git a/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx b/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx index 31887609b0acf..168e714ca191e 100644 --- a/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx +++ b/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx @@ -57,9 +57,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Sharing lock is required - No export was found for the contract '{0}' @@ -73,9 +70,6 @@ '{0}' on contract '{1}' supplied by {2} - - Export descriptor fulfillment function returned null. - {0} supplied by {1} @@ -103,9 +97,6 @@ The component (unknown) cannot be created outside the {0} sharing boundary. - - Metadata View Provider - The type '{0}' cannot be used as a metadata view. A metadata view must be a concrete class with a parameterless or dictionary constructor. diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx index 2dd95efcdbe2f..29f880277d133 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx +++ b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx @@ -93,7 +93,7 @@ + --> Cannot add a ConfigurationSection that already belongs to the Configuration. @@ -364,9 +364,6 @@ The configSource attribute must be a relative physical path. - - The configSource attribute must be a relative physical path, so the '/' character is not allowed. - The 'configSource' property may not be set in a configuration that has no associated file. diff --git a/src/libraries/System.Console/src/System/IO/SyncTextReader.cs b/src/libraries/System.Console/src/System/IO/SyncTextReader.cs index 7a2661691e624..33ef898edb688 100644 --- a/src/libraries/System.Console/src/System/IO/SyncTextReader.cs +++ b/src/libraries/System.Console/src/System/IO/SyncTextReader.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; namespace System.IO @@ -95,11 +96,25 @@ public override string ReadToEnd() return Task.FromResult(ReadLine()); } + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) + { + return cancellationToken.IsCancellationRequested ? + ValueTask.FromCanceled(cancellationToken) : + new ValueTask(ReadLine()); + } + public override Task ReadToEndAsync() { return Task.FromResult(ReadToEnd()); } + public override Task ReadToEndAsync(CancellationToken cancellationToken) + { + return cancellationToken.IsCancellationRequested ? + Task.FromCanceled(cancellationToken) : + Task.FromResult(ReadToEnd()); + } + public override Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer == null) diff --git a/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs b/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs index e72522bafc58b..2a8bc01fcf2b4 100644 --- a/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs +++ b/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs @@ -76,9 +76,10 @@ public void ExitDetectionNotBlockedByHandler() Assert.Equal(RemoteExecutor.SuccessExitCode, handle.ExitCode); } - // Release CancelKeyPress + // Release CancelKeyPress, and give it time to return and tear down the app mre.Set(); - }).Dispose(); + Thread.Sleep(WaitFailTestTimeoutSeconds * 1000); + }, new RemoteInvokeOptions() { ExpectedExitCode = 130 }).Dispose(); } private void HandlerInvokedForSignal(int signalOuter, bool redirectStandardInput) diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs index 569f83d8ac777..5e664573d5ea6 100644 --- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs +++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs @@ -2737,7 +2737,7 @@ public SqlAlreadyFilledException(string? message) { } public SqlAlreadyFilledException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -2752,6 +2752,7 @@ public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBinary Concat(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBinary other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2777,7 +2778,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlBoolean False; @@ -2796,6 +2797,7 @@ public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.ICompa public int CompareTo(System.Data.SqlTypes.SqlBoolean value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBoolean other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2847,7 +2849,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlBoolean Xor(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlByte MaxValue; @@ -2864,6 +2866,7 @@ public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlByte Divide(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlByte other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2987,7 +2990,7 @@ public enum SqlCompareOptions BinarySort = 32768, } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDateTime MaxValue; @@ -3010,6 +3013,7 @@ public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComp public int CompareTo(System.Data.SqlTypes.SqlDateTime value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDateTime x, System.Data.SqlTypes.SqlDateTime y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDateTime other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3038,7 +3042,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly byte MaxPrecision; @@ -3068,6 +3072,7 @@ public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.ICompa public static System.Data.SqlTypes.SqlDecimal ConvertToPrecScale(System.Data.SqlTypes.SqlDecimal n, int precision, int scale) { throw null; } public static System.Data.SqlTypes.SqlDecimal Divide(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDecimal other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public static System.Data.SqlTypes.SqlDecimal Floor(System.Data.SqlTypes.SqlDecimal n) { throw null; } public override int GetHashCode() { throw null; } @@ -3124,7 +3129,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlDecimal Truncate(System.Data.SqlTypes.SqlDecimal n, int position) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDouble MaxValue; @@ -3139,6 +3144,7 @@ public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlDouble Divide(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDouble other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3187,7 +3193,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3201,6 +3207,7 @@ public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(System.Data.SqlTypes.SqlGuid value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlGuid other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3229,7 +3236,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt16 MaxValue; @@ -3246,6 +3253,7 @@ public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt16 Divide(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt16 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3303,7 +3311,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt16 Xor(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt32 MaxValue; @@ -3320,6 +3328,7 @@ public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt32 Divide(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3377,7 +3386,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt32 Xor(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt64 MaxValue; @@ -3394,6 +3403,7 @@ public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt64 Divide(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt64 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3451,7 +3461,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt64 Xor(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlMoney MaxValue; @@ -3469,6 +3479,7 @@ public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlMoney Divide(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlMoney other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3535,7 +3546,7 @@ public SqlNullValueException(string? message) { } public SqlNullValueException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlSingle MaxValue; @@ -3551,6 +3562,7 @@ public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlSingle Divide(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlSingle other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3599,7 +3611,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3630,6 +3642,7 @@ public partial struct SqlString : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlString Concat(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlString other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public byte[]? GetNonUnicodeBytes() { throw null; } diff --git a/src/libraries/System.Data.Common/src/Resources/Strings.resx b/src/libraries/System.Data.Common/src/Resources/Strings.resx index 671bf490bc135..c1a4dee0c36b0 100644 --- a/src/libraries/System.Data.Common/src/Resources/Strings.resx +++ b/src/libraries/System.Data.Common/src/Resources/Strings.resx @@ -97,7 +97,6 @@ An error occurred with the multiple target converter while writing an Xml Schema. See the inner exception for details. An error occurred with the multiple target converter while writing an Xml Schema. A null or empty string was returned. Duplicated declaration '{0}'. - Cannot load diffGram. Table '{0}' is missing in the destination dataset. Cannot load diffGram. The 'sql' node is missing. Column name '{0}' is defined for different mapping types. Prefix '{0}' is not valid, because it contains special characters. diff --git a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs index 379035bb75d6b..7f1a15f75f51b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs @@ -5,7 +5,7 @@ namespace System.Data { - internal readonly struct DataKey + internal readonly struct DataKey : IEquatable { private const int maxColumns = 32; @@ -154,7 +154,7 @@ public override bool Equals(object? value) return Equals((DataKey)value); } - internal bool Equals(DataKey value) + public bool Equals(DataKey value) { //check to see if this.columns && key2's columns are equal... DataColumn[] column1 = _columns; diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs index a757be446e73a..f6a45dbba5f2c 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs @@ -12,7 +12,7 @@ namespace System.Data.SqlTypes { [XmlSchemaProvider("GetXsdType")] - public struct SqlBinary : INullable, IComparable, IXmlSerializable + public struct SqlBinary : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private byte[]? _value; @@ -362,20 +362,15 @@ public int CompareTo(SqlBinary value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBinary)) - { - return false; - } - - SqlBinary i = (SqlBinary)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBinary other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBinary other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // Hash a byte array. // Trailing zeroes/spaces would affect the hash value, so caller needs to diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs index 1efff18021e52..d7b723f9f05f0 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlBoolean : INullable, IComparable, IXmlSerializable + public struct SqlBoolean : INullable, IComparable, IXmlSerializable, IEquatable { // m_value: 2 (true), 1 (false), 0 (unknown/Null) private byte m_value; // Do not rename (binary serialization) @@ -465,26 +465,18 @@ public int CompareTo(SqlBoolean value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBoolean)) - { - return false; - } - - SqlBoolean i = (SqlBoolean)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBoolean other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBoolean other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs index f7c1cdde43226..3dc5548ffed7a 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlByte : INullable, IComparable, IXmlSerializable + public struct SqlByte : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private byte m_value; // Do not rename (binary serialization) @@ -474,26 +474,18 @@ public int CompareTo(SqlByte value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlByte)) - { - return false; - } - - SqlByte i = (SqlByte)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlByte other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlByte other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs index 195ca26628ea4..1edd44bedf338 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDateTime : INullable, IComparable, IXmlSerializable + public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private int m_day; // Day from 1900/1/1, could be negative. Range: Jan 1 1753 - Dec 31 9999. Do not rename (binary serialization) @@ -621,26 +621,18 @@ public int CompareTo(SqlDateTime value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDateTime)) - { - return false; - } - - SqlDateTime i = (SqlDateTime)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDateTime other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDateTime other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs index 784d50d2bb1cf..336639fbf0e5b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes ///
[StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlDecimal : INullable, IComparable, IXmlSerializable + public struct SqlDecimal : INullable, IComparable, IXmlSerializable, IEquatable { // data in CSsNumeric in SQL Server // BYTE m_cbLen; // # of DWORDs + 1 (1 is for sign) @@ -3278,20 +3278,15 @@ public int CompareTo(SqlDecimal value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDecimal)) - { - return false; - } - - SqlDecimal i = (SqlDecimal)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDecimal other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDecimal other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs index 3f10f94312400..4cc9ac4e321e0 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs @@ -19,7 +19,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDouble : INullable, IComparable, IXmlSerializable + public struct SqlDouble : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private double m_value; // Do not rename (binary serialization) @@ -390,26 +390,18 @@ public int CompareTo(SqlDouble value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDouble)) - { - return false; - } - - SqlDouble i = (SqlDouble)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDouble other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDouble other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs index 8e3c58dff3dad..2742c25d53b53 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs @@ -16,7 +16,7 @@ namespace System.Data.SqlTypes [Serializable] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlGuid : INullable, IComparable, IXmlSerializable + public struct SqlGuid : INullable, IComparable, IXmlSerializable, IEquatable { private const int SizeOfGuid = 16; @@ -281,26 +281,18 @@ public int CompareTo(SqlGuid value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlGuid)) - { - return false; - } - - SqlGuid i = (SqlGuid)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlGuid other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlGuid other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs index 5833a00938561..d3879a06cf91b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt16 : INullable, IComparable, IXmlSerializable + public struct SqlInt16 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private short m_value; // Do not rename (binary serialization) @@ -475,26 +475,18 @@ public int CompareTo(SqlInt16 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt16)) - { - return false; - } - - SqlInt16 i = (SqlInt16)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt16 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt16 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs index 271d6509e71f5..8ce08e74e4403 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt32 : INullable, IComparable, IXmlSerializable + public struct SqlInt32 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null, the default ctor (plain 0) will make it Null. Do not rename (binary serialization) private int m_value; // Do not rename (binary serialization) @@ -490,26 +490,18 @@ public int CompareTo(SqlInt32 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt32)) - { - return false; - } - - SqlInt32 i = (SqlInt32)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt32 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt32 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs index b7f33674ce03a..393945b030395 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt64 : INullable, IComparable, IXmlSerializable + public struct SqlInt64 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private long m_value; // Do not rename (binary serialization) @@ -549,26 +549,18 @@ public int CompareTo(SqlInt64 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt64)) - { - return false; - } - - SqlInt64 i = (SqlInt64)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt64 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt64 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs index 5431c8737d4af..64c0d168631c8 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes /// [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlMoney : INullable, IComparable, IXmlSerializable + public struct SqlMoney : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private bool _fNotNull; // false if null @@ -539,27 +539,20 @@ public int CompareTo(SqlMoney value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlMoney)) - { - return false; - } - - SqlMoney i = (SqlMoney)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlMoney other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlMoney other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { + public override int GetHashCode() => // Don't use Value property, because Value will convert to Decimal, which is not necessary. - return IsNull ? 0 : _value.GetHashCode(); - } + IsNull ? 0 : _value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs index 59f29dcc89cbc..5fa7562824e13 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes /// [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlSingle : INullable, IComparable, IXmlSerializable + public struct SqlSingle : INullable, IComparable, IXmlSerializable, IEquatable { private bool _fNotNull; // false if null private float _value; @@ -400,26 +400,18 @@ public int CompareTo(SqlSingle value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlSingle)) - { - return false; - } - - SqlSingle i = (SqlSingle)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlSingle other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlSingle other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs index cac4122feba68..0c22570d2462d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs @@ -34,7 +34,7 @@ public enum SqlCompareOptions [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlString : INullable, IComparable, IXmlSerializable + public struct SqlString : INullable, IComparable, IXmlSerializable, IEquatable { private string? m_value; // Do not rename (binary serialization) private CompareInfo? m_cmpInfo; // Do not rename (binary serialization) @@ -871,20 +871,15 @@ public int CompareTo(SqlString value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlString)) - { - return false; - } - - SqlString i = (SqlString)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlString other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlString other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/Selection.cs b/src/libraries/System.Data.Common/src/System/Data/Selection.cs index 21a6d951393c1..fd76acfda7c36 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Selection.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Selection.cs @@ -9,7 +9,7 @@ namespace System.Data { - internal readonly struct IndexField + internal readonly struct IndexField : IEquatable { public readonly DataColumn Column; public readonly bool IsDescending; // false = Asc; true = Desc what is default value for this? @@ -22,15 +22,15 @@ internal IndexField(DataColumn column, bool isDescending) IsDescending = isDescending; } - public static bool operator ==(IndexField if1, IndexField if2) => - if1.Column == if2.Column && if1.IsDescending == if2.IsDescending; + public static bool operator ==(IndexField if1, IndexField if2) => if1.Equals(if2); - public static bool operator !=(IndexField if1, IndexField if2) => !(if1 == if2); + public static bool operator !=(IndexField if1, IndexField if2) => !if1.Equals(if2); // must override Equals if == operator is defined - public override bool Equals([NotNullWhen(true)] object? obj) => obj is IndexField ? - this == (IndexField)obj : - false; + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IndexField other && Equals(other); + + public bool Equals(IndexField other) => Column == other.Column && IsDescending == other.IsDescending; // must override GetHashCode if Equals is redefined public override int GetHashCode() => diff --git a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs index 54644b678a5bc..d42609fed6b5c 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.SqlTypes; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Numerics; @@ -433,7 +434,7 @@ public void ReadXml(XmlReader reader) string tempPath = Path.GetTempFileName(); File.WriteAllText(tempPath, "This better not be written..."); File.Delete(tempPath); - throw new XunitException("Unreachable code (SerializationGuard should have kicked in)"); + throw new UnreachableException("Unreachable code (SerializationGuard should have kicked in)"); } public void WriteXml(XmlWriter writer) diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs index 6a631b392bea9..8655d3feea003 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs @@ -122,8 +122,11 @@ public void ComparisonMethods() // Equals Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test2)); + Assert.False(_test3.Equals((object)_test2)); Assert.True(_test3.Equals(_test1)); + Assert.True(_test3.Equals((object)_test1)); // NotEquals Assert.True(SqlBinary.NotEquals(_test1, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs index 4da63a4bcdcf8..b52f671dad2d4 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs @@ -242,10 +242,14 @@ public void EqualsTest() SqlBoolean sqlFalse2 = new SqlBoolean(false); Assert.True(_sqlTrue.Equals(sqlTrue2)); + Assert.True(_sqlTrue.Equals((object)sqlTrue2)); Assert.True(_sqlFalse.Equals(sqlFalse2)); + Assert.True(_sqlFalse.Equals((object)sqlFalse2)); Assert.False(_sqlTrue.Equals(_sqlFalse)); + Assert.False(_sqlTrue.Equals((object)_sqlFalse)); Assert.False(_sqlFalse.Equals(_sqlTrue)); + Assert.False(_sqlFalse.Equals((object)_sqlTrue)); Assert.False(_sqlTrue.Equals(SqlBoolean.Null)); Assert.False(_sqlFalse.Equals(SqlBoolean.Null)); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs index 2ae5976e9f1a9..9af75f4f46997 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs @@ -155,9 +155,12 @@ public void EqualsMethod() SqlByte testByte180II = new SqlByte(180); Assert.False(testByte0.Equals(testByte158)); + Assert.False(testByte0.Equals((object)testByte158)); Assert.False(testByte158.Equals(testByte180)); + Assert.False(testByte158.Equals((object)testByte180)); Assert.False(testByte180.Equals(new SqlString("TEST"))); Assert.True(testByte180.Equals(testByte180II)); + Assert.True(testByte180.Equals((object)testByte180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBytesTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBytesTest.cs index b0f498c276676..4b65884b86c74 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBytesTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBytesTest.cs @@ -66,9 +66,9 @@ public void SqlBytesMaxLength() { byte[] b = null; SqlBytes bytes = new SqlBytes(); - Assert.Equal(bytes.MaxLength, -1); + Assert.Equal(-1, bytes.MaxLength); bytes = new SqlBytes(b); - Assert.Equal(bytes.MaxLength, -1); + Assert.Equal(-1, bytes.MaxLength); b = new byte[10]; bytes = new SqlBytes(b); Assert.Equal(10, bytes.MaxLength); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlCharsTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlCharsTest.cs index cdfe5988dc494..dfc9e95769a3e 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlCharsTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlCharsTest.cs @@ -72,9 +72,9 @@ public void SqlCharsMaxLength() { char[] b = null; SqlChars chars = new SqlChars(); - Assert.Equal(chars.MaxLength, -1); + Assert.Equal(-1, chars.MaxLength); chars = new SqlChars(b); - Assert.Equal(chars.MaxLength, -1); + Assert.Equal(-1, chars.MaxLength); b = new char[10]; chars = new SqlChars(b); Assert.Equal(10, chars.MaxLength); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs index 6d3287ed49b0f..0c835ff00c540 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs @@ -175,8 +175,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDateTime.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs index 6fd72ba4157aa..b9807ebcc102e 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs @@ -225,8 +225,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDecimal.Equals(_test2, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs index 4f0856e2ba226..db913271dc020 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs @@ -134,9 +134,12 @@ public void EqualsMethods() SqlDouble test22 = new SqlDouble(1.8e180); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlDouble.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs index 84dcb3a3f5373..4c21e38d07ef2 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs @@ -126,9 +126,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(_test4)); + Assert.False(_test2.Equals((object)_test4)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlGuid.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs index 3c240d6d9ed0f..7c00f4845884d 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs @@ -157,9 +157,12 @@ public void EqualsMethod() SqlInt16 test180II = new SqlInt16(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt32Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt32Test.cs index 6198c3a7ac9bc..e3466d60e63e9 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt32Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt32Test.cs @@ -56,9 +56,9 @@ public void Add() x = new SqlInt32(a); y = new SqlInt32(b); z = x + y; - Assert.Equal(z.Value, a + b); + Assert.Equal(a + b, z.Value); z = SqlInt32.Add(x, y); - Assert.Equal(z.Value, a + b); + Assert.Equal(a + b, z.Value); } [Fact] @@ -70,9 +70,9 @@ public void BitwiseAnd() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x & y; - Assert.Equal(z.Value, a & b); + Assert.Equal(a & b, z.Value); z = SqlInt32.BitwiseAnd(x, y); - Assert.Equal(z.Value, a & b); + Assert.Equal(a & b, z.Value); } [Fact] @@ -84,9 +84,9 @@ public void BitwiseOr() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x | y; - Assert.Equal(z.Value, a | b); + Assert.Equal(a | b, z.Value); z = SqlInt32.BitwiseOr(x, y); - Assert.Equal(z.Value, a | b); + Assert.Equal(a | b, z.Value); } [Fact] @@ -98,9 +98,9 @@ public void Divide() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x / y; - Assert.Equal(z.Value, a / b); + Assert.Equal(a / b, z.Value); z = SqlInt32.Divide(x, y); - Assert.Equal(z.Value, a / b); + Assert.Equal(a / b, z.Value); } [Fact] @@ -112,25 +112,25 @@ public void EqualsTest() // Case 1: either is SqlInt32.Null x = SqlInt32.Null; y = new SqlInt32(5); - Assert.Equal(x == y, SqlBoolean.Null); - Assert.Equal(SqlInt32.Equals(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x == y); + Assert.Equal(SqlBoolean.Null, SqlInt32.Equals(x, y)); // Case 2: both are SqlInt32.Null y = SqlInt32.Null; - Assert.Equal(x == y, SqlBoolean.Null); - Assert.Equal(SqlInt32.Equals(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x == y); + Assert.Equal(SqlBoolean.Null, SqlInt32.Equals(x, y)); // Case 3: both are equal x = new SqlInt32(5); y = new SqlInt32(5); - Assert.Equal(x == y, SqlBoolean.True); - Assert.Equal(SqlInt32.Equals(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x == y); + Assert.Equal(SqlBoolean.True, SqlInt32.Equals(x, y)); // Case 4: inequality x = new SqlInt32(5); y = new SqlInt32(6); - Assert.Equal(x == y, SqlBoolean.False); - Assert.Equal(SqlInt32.Equals(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x == y); + Assert.Equal(SqlBoolean.False, SqlInt32.Equals(x, y)); } [Fact] @@ -142,25 +142,25 @@ public void GreaterThan() // Case 1: either is SqlInt32.Null x = SqlInt32.Null; y = new SqlInt32(5); - Assert.Equal(x > y, SqlBoolean.Null); - Assert.Equal(SqlInt32.GreaterThan(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x > y); + Assert.Equal(SqlBoolean.Null, SqlInt32.GreaterThan(x, y)); // Case 2: both are SqlInt32.Null y = SqlInt32.Null; - Assert.Equal(x > y, SqlBoolean.Null); - Assert.Equal(SqlInt32.GreaterThan(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x > y); + Assert.Equal(SqlBoolean.Null, SqlInt32.GreaterThan(x, y)); // Case 3: x > y x = new SqlInt32(5); y = new SqlInt32(4); - Assert.Equal(x > y, SqlBoolean.True); - Assert.Equal(SqlInt32.GreaterThan(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x > y); + Assert.Equal(SqlBoolean.True, SqlInt32.GreaterThan(x, y)); // Case 4: x < y x = new SqlInt32(5); y = new SqlInt32(6); - Assert.Equal(x > y, SqlBoolean.False); - Assert.Equal(SqlInt32.GreaterThan(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x > y); + Assert.Equal(SqlBoolean.False, SqlInt32.GreaterThan(x, y)); } [Fact] @@ -172,31 +172,31 @@ public void GreaterThanOrEqual() // Case 1: either is SqlInt32.Null x = SqlInt32.Null; y = new SqlInt32(5); - Assert.Equal(x >= y, SqlBoolean.Null); - Assert.Equal(SqlInt32.GreaterThanOrEqual(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x >= y); + Assert.Equal(SqlBoolean.Null, SqlInt32.GreaterThanOrEqual(x, y)); // Case 2: both are SqlInt32.Null y = SqlInt32.Null; - Assert.Equal(x >= y, SqlBoolean.Null); - Assert.Equal(SqlInt32.GreaterThanOrEqual(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x >= y); + Assert.Equal(SqlBoolean.Null, SqlInt32.GreaterThanOrEqual(x, y)); // Case 3: x > y x = new SqlInt32(5); y = new SqlInt32(4); - Assert.Equal(x >= y, SqlBoolean.True); - Assert.Equal(SqlInt32.GreaterThanOrEqual(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x >= y); + Assert.Equal(SqlBoolean.True, SqlInt32.GreaterThanOrEqual(x, y)); // Case 4: x < y x = new SqlInt32(5); y = new SqlInt32(6); - Assert.Equal(x >= y, SqlBoolean.False); - Assert.Equal(SqlInt32.GreaterThanOrEqual(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x >= y); + Assert.Equal(SqlBoolean.False, SqlInt32.GreaterThanOrEqual(x, y)); // Case 5: x == y x = new SqlInt32(5); y = new SqlInt32(5); - Assert.Equal(x >= y, SqlBoolean.True); - Assert.Equal(SqlInt32.GreaterThanOrEqual(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x >= y); + Assert.Equal(SqlBoolean.True, SqlInt32.GreaterThanOrEqual(x, y)); } [Fact] @@ -208,25 +208,25 @@ public void LessThan() // Case 1: either is SqlInt32.Null x = SqlInt32.Null; y = new SqlInt32(5); - Assert.Equal(x < y, SqlBoolean.Null); - Assert.Equal(SqlInt32.LessThan(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x < y); + Assert.Equal(SqlBoolean.Null, SqlInt32.LessThan(x, y)); // Case 2: both are SqlInt32.Null y = SqlInt32.Null; - Assert.Equal(x < y, SqlBoolean.Null); - Assert.Equal(SqlInt32.LessThan(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x < y); + Assert.Equal(SqlBoolean.Null, SqlInt32.LessThan(x, y)); // Case 3: x > y x = new SqlInt32(5); y = new SqlInt32(4); - Assert.Equal(x < y, SqlBoolean.False); - Assert.Equal(SqlInt32.LessThan(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x < y); + Assert.Equal(SqlBoolean.False, SqlInt32.LessThan(x, y)); // Case 4: x < y x = new SqlInt32(5); y = new SqlInt32(6); - Assert.Equal(x < y, SqlBoolean.True); - Assert.Equal(SqlInt32.LessThan(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x < y); + Assert.Equal(SqlBoolean.True, SqlInt32.LessThan(x, y)); } [Fact] @@ -238,31 +238,31 @@ public void LessThanOrEqual() // Case 1: either is SqlInt32.Null x = SqlInt32.Null; y = new SqlInt32(5); - Assert.Equal(x <= y, SqlBoolean.Null); - Assert.Equal(SqlInt32.LessThanOrEqual(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x <= y); + Assert.Equal(SqlBoolean.Null, SqlInt32.LessThanOrEqual(x, y)); // Case 2: both are SqlInt32.Null y = SqlInt32.Null; - Assert.Equal(x <= y, SqlBoolean.Null); - Assert.Equal(SqlInt32.LessThanOrEqual(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x <= y); + Assert.Equal(SqlBoolean.Null, SqlInt32.LessThanOrEqual(x, y)); // Case 3: x > y x = new SqlInt32(5); y = new SqlInt32(4); - Assert.Equal(x <= y, SqlBoolean.False); - Assert.Equal(SqlInt32.LessThanOrEqual(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x <= y); + Assert.Equal(SqlBoolean.False, SqlInt32.LessThanOrEqual(x, y)); // Case 4: x < y x = new SqlInt32(5); y = new SqlInt32(6); - Assert.Equal(x <= y, SqlBoolean.True); - Assert.Equal(SqlInt32.LessThanOrEqual(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x <= y); + Assert.Equal(SqlBoolean.True, SqlInt32.LessThanOrEqual(x, y)); // Case 5: x == y x = new SqlInt32(5); y = new SqlInt32(5); - Assert.Equal(x <= y, SqlBoolean.True); - Assert.Equal(SqlInt32.LessThanOrEqual(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x <= y); + Assert.Equal(SqlBoolean.True, SqlInt32.LessThanOrEqual(x, y)); } [Fact] @@ -274,9 +274,9 @@ public void Mod() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x % y; - Assert.Equal(z.Value, a % b); + Assert.Equal(a % b, z.Value); z = SqlInt32.Mod(x, y); - Assert.Equal(z.Value, a % b); + Assert.Equal(a % b, z.Value); } [Fact] @@ -287,9 +287,9 @@ public void Modulus() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x % y; - Assert.Equal(z.Value, a % b); + Assert.Equal(a % b, z.Value); z = SqlInt32.Modulus(x, y); - Assert.Equal(z.Value, a % b); + Assert.Equal(a % b, z.Value); } [Fact] @@ -301,9 +301,9 @@ public void Multiply() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x * y; - Assert.Equal(z.Value, a * b); + Assert.Equal(a * b, z.Value); z = SqlInt32.Multiply(x, y); - Assert.Equal(z.Value, a * b); + Assert.Equal(a * b, z.Value); } [Fact] @@ -315,16 +315,16 @@ public void NotEquals() x = new SqlInt32(5); y = SqlInt32.Null; - Assert.Equal(x != y, SqlBoolean.Null); - Assert.Equal(SqlInt32.NotEquals(x, y), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x != y); + Assert.Equal(SqlBoolean.Null, SqlInt32.NotEquals(x, y)); y = new SqlInt32(5); - Assert.Equal(x != y, SqlBoolean.False); - Assert.Equal(SqlInt32.NotEquals(x, y), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x != y); + Assert.Equal(SqlBoolean.False, SqlInt32.NotEquals(x, y)); y = new SqlInt32(6); - Assert.Equal(x != y, SqlBoolean.True); - Assert.Equal(SqlInt32.NotEquals(x, y), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x != y); + Assert.Equal(SqlBoolean.True, SqlInt32.NotEquals(x, y)); } [Fact] @@ -334,9 +334,9 @@ public void OnesComplement() SqlInt32 x = new SqlInt32(a); SqlInt32 z = ~x; - Assert.Equal(z.Value, ~a); + Assert.Equal(~a, z.Value); z = SqlInt32.OnesComplement(x); - Assert.Equal(z.Value, ~a); + Assert.Equal(~a, z.Value); } [Fact] @@ -355,9 +355,9 @@ public void Subtract() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x - y; - Assert.Equal(z.Value, a - b); + Assert.Equal(a - b, z.Value); z = SqlInt32.Subtract(x, y); - Assert.Equal(z.Value, a - b); + Assert.Equal(a - b, z.Value); } [Fact] @@ -367,27 +367,27 @@ public void ConversionMethods() // Case 1: SqlInt32.Null -> SqlBoolean == SqlBoolean.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlBoolean(), SqlBoolean.Null); + Assert.Equal(SqlBoolean.Null, x.ToSqlBoolean()); // Case 2: SqlInt32.Zero -> SqlBoolean == False x = SqlInt32.Zero; - Assert.Equal(x.ToSqlBoolean(), SqlBoolean.False); + Assert.Equal(SqlBoolean.False, x.ToSqlBoolean()); // Case 3: SqlInt32(nonzero) -> SqlBoolean == True x = new SqlInt32(27); - Assert.Equal(x.ToSqlBoolean(), SqlBoolean.True); + Assert.Equal(SqlBoolean.True, x.ToSqlBoolean()); // Case 4: SqlInt32.Null -> SqlByte == SqlByte.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlByte(), SqlByte.Null); + Assert.Equal(SqlByte.Null, x.ToSqlByte()); // Case 5: Test non-null conversion to SqlByte x = new SqlInt32(27); - Assert.Equal(x.ToSqlByte().Value, (byte)27); + Assert.Equal((byte)27, x.ToSqlByte().Value); // Case 6: SqlInt32.Null -> SqlDecimal == SqlDecimal.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlDecimal(), SqlDecimal.Null); + Assert.Equal(SqlDecimal.Null, x.ToSqlDecimal()); // Case 7: Test non-null conversion to SqlDecimal x = new SqlInt32(27); @@ -395,7 +395,7 @@ public void ConversionMethods() // Case 8: SqlInt32.Null -> SqlDouble == SqlDouble.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlDouble(), SqlDouble.Null); + Assert.Equal(SqlDouble.Null, x.ToSqlDouble()); // Case 9: Test non-null conversion to SqlDouble x = new SqlInt32(27); @@ -403,15 +403,15 @@ public void ConversionMethods() // Case 10: SqlInt32.Null -> SqlInt16 == SqlInt16.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlInt16(), SqlInt16.Null); + Assert.Equal(SqlInt16.Null, x.ToSqlInt16()); // Case 11: Test non-null conversion to SqlInt16 x = new SqlInt32(27); - Assert.Equal(x.ToSqlInt16().Value, (short)27); + Assert.Equal((short)27, x.ToSqlInt16().Value); // Case 12: SqlInt32.Null -> SqlInt64 == SqlInt64.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlInt64(), SqlInt64.Null); + Assert.Equal(SqlInt64.Null, x.ToSqlInt64()); // Case 13: Test non-null conversion to SqlInt64 x = new SqlInt32(27); @@ -419,7 +419,7 @@ public void ConversionMethods() // Case 14: SqlInt32.Null -> SqlMoney == SqlMoney.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlMoney(), SqlMoney.Null); + Assert.Equal(SqlMoney.Null, x.ToSqlMoney()); // Case 15: Test non-null conversion to SqlMoney x = new SqlInt32(27); @@ -427,7 +427,7 @@ public void ConversionMethods() // Case 16: SqlInt32.Null -> SqlSingle == SqlSingle.Null x = SqlInt32.Null; - Assert.Equal(x.ToSqlSingle(), SqlSingle.Null); + Assert.Equal(SqlSingle.Null, x.ToSqlSingle()); // Case 17: Test non-null conversion to SqlSingle x = new SqlInt32(27); @@ -443,9 +443,9 @@ public void Xor() SqlInt32 x = new SqlInt32(a); SqlInt32 y = new SqlInt32(b); SqlInt32 z = x ^ y; - Assert.Equal(z.Value, a ^ b); + Assert.Equal(a ^ b, z.Value); z = SqlInt32.Xor(x, y); - Assert.Equal(z.Value, a ^ b); + Assert.Equal(a ^ b, z.Value); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs index 601b6a8bdb1bc..ed466fb50b277 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs @@ -159,9 +159,12 @@ public void EqualsMethod() SqlInt64 test180II = new SqlInt64(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs index 726302190b388..db99ba4de6691 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs @@ -131,7 +131,9 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); Assert.False(SqlMoney.Equals(_test1, _test2).Value); Assert.True(SqlMoney.Equals(_test3, _test2).Value); } diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs index 2c92e08226e49..3ff6c803aaef6 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs @@ -132,9 +132,12 @@ public void EqualsMethods() SqlSingle test22 = new SqlSingle(1.8e32); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlSingle.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs index 86a4b1683c4c9..56f8fa51b06ca 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs @@ -262,9 +262,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test1)); + Assert.False(_test3.Equals((object)_test1)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlString.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Odbc/src/Resources/Strings.resx b/src/libraries/System.Data.Odbc/src/Resources/Strings.resx index b6860f2dd50aa..2c6f3249f0804 100644 --- a/src/libraries/System.Data.Odbc/src/Resources/Strings.resx +++ b/src/libraries/System.Data.Odbc/src/Resources/Strings.resx @@ -128,9 +128,6 @@ The {0} is already contained by another {1}. - - The {0} with is already contained by this {1}. - The {0} only accepts non-null {1} type objects. @@ -377,9 +374,6 @@ This {0} has completed; it is no longer usable. - - '{0}' cannot be called when the record is read only. - Invalid {2} attempt at dataIndex '{0}'. With CommandBehavior.SequentialAccess, you may only read from dataIndex '{1}' or greater. diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 9cc4d09bf298b..2005ee7715654 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -176,7 +176,6 @@ System.Data.Odbc.OdbcTransaction - diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index a94fb9e380da8..3ab7c480affb7 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -307,15 +307,27 @@ namespace System.Diagnostics.Metrics { public sealed class Counter : Instrument where T : struct { - public void Add(T delta) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } - public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } + public void Add(T delta) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } + public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal Counter(Meter meter, string name, string? unit, string? description) : - base(meter, name, unit, description) { throw null; } + base(meter, name, unit, description) { throw null; } + } + public sealed class UpDownCounter : Instrument where T : struct + { + public void Add(T delta) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } + public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } + public void Add(T delta, in TagList tagList) { throw null; } + internal UpDownCounter(Meter meter, string name, string? unit, string? description) : + base(meter, name, unit, description) { throw null; } } public sealed class Histogram : Instrument where T : struct { @@ -362,6 +374,7 @@ public abstract class Instrument : Instrument where T : struct public class Meter : IDisposable { public Counter CreateCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } + public UpDownCounter CreateUpDownCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } public Histogram CreateHistogram(string name, string? unit = null, string? description = null) where T : struct { throw null; } public ObservableCounter CreateObservableCounter( string name, @@ -378,6 +391,21 @@ public ObservableCounter CreateObservableCounter( Func>> observeValues, string? unit = null, string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func observeValue, + string? unit = null, + string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func> observeValue, + string? unit = null, + string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func>> observeValues, + string? unit = null, + string? description = null) where T : struct { throw null; } public ObservableGauge CreateObservableGauge( string name, Func observeValue, @@ -416,6 +444,11 @@ public sealed class ObservableCounter : ObservableInstrument where T : str internal ObservableCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } protected override System.Collections.Generic.IEnumerable> Observe() { throw null;} } + public sealed class ObservableUpDownCounter : ObservableInstrument where T : struct + { + internal ObservableUpDownCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } + protected override System.Collections.Generic.IEnumerable> Observe() { throw null;} + } public sealed class ObservableGauge : ObservableInstrument where T : struct { internal ObservableGauge(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx index 0d9ad07a07e40..f57c9d3a7b872 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx @@ -144,9 +144,6 @@ "Can not change format for an activity that was already started" - - "Can not add link to activity after it has been started" - "Can not set ParentId on activity which has parent" diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 510487abedfd3..b2be804bdfbf1 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -72,11 +72,13 @@ System.Diagnostics.DiagnosticSource + + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs index 7aa624c68bed2..b16bbf08835af 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs @@ -82,6 +82,59 @@ public Meter(string name, string? version) /// public Histogram CreateHistogram(string name, string? unit = null, string? description = null) where T : struct => new Histogram(this, name, unit, description); + /// + /// Create a metrics UpDownCounter object. + /// + /// The instrument name. Cannot be null. + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// UpDownCounter is an Instrument which supports reporting positive or negative metric values. + /// Example uses for UpDownCounter: reporting the change in active requests or queue size. + /// + public UpDownCounter CreateUpDownCounter(string name, string? unit = null, string? description = null) where T : struct => new UpDownCounter(this, name, unit, description); + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by . + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func observeValue, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValue, unit, description); + + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func> observeValue, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValue, unit, description); + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by . + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValues, unit, description); + + /// /// ObservableCounter is an Instrument which reports monotonically increasing value(s) when the instrument is being observed. /// @@ -122,6 +175,7 @@ public ObservableCounter CreateObservableCounter(string name, Func CreateObservableCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct => new ObservableCounter(this, name, observeValues, unit, description); + /// /// ObservableGauge is an asynchronous Instrument which reports non-additive value(s) (e.g. the room temperature - it makes no sense to report the temperature value from multiple rooms and sum them up) when the instrument is being observed. /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs new file mode 100644 index 0000000000000..7751067ac55a3 --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Diagnostics.Metrics +{ + /// + /// ObservableUpDownCounter is a metrics observable Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// e.g. the process heap size or the approximate number of items in a lock-free circular buffer. + /// Use Meter.CreateObservableUpDownCounter methods to create an ObservableUpDownCounter object. + /// + /// + /// This class supports only the following generic parameter types: , , , , , , and + /// +#if ALLOW_PARTIALLY_TRUSTED_CALLERS + [System.Security.SecuritySafeCriticalAttribute] +#endif + public sealed class ObservableUpDownCounter : ObservableInstrument where T : struct + { + private object _callback; + + internal ObservableUpDownCounter(Meter meter, string name, Func observeValue, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValue is null) + { + throw new ArgumentNullException(nameof(observeValue)); + } + + _callback = observeValue; + Publish(); + } + + internal ObservableUpDownCounter(Meter meter, string name, Func> observeValue, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValue is null) + { + throw new ArgumentNullException(nameof(observeValue)); + } + + _callback = observeValue; + Publish(); + } + + internal ObservableUpDownCounter(Meter meter, string name, Func>> observeValues, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValues is null) + { + throw new ArgumentNullException(nameof(observeValues)); + } + + _callback = observeValues; + Publish(); + } + + /// + /// Observe() fetches the current measurements being tracked by this observable counter. + /// + protected override IEnumerable> Observe() => Observe(_callback); + } +} \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs new file mode 100644 index 0000000000000..cad80c52c57ee --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Diagnostics.Metrics +{ + /// + /// The UpDownCounter is an instrument that supports reporting positive or negative metric values. + /// UpDownCounter may be used in scenarios like reporting the change in active requests or queue size. + /// + /// + /// This class supports only the following generic parameter types: , , , , , , and + /// +#if ALLOW_PARTIALLY_TRUSTED_CALLERS + [System.Security.SecuritySafeCriticalAttribute] +#endif + public sealed class UpDownCounter : Instrument where T : struct + { + internal UpDownCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) + { + Publish(); + } + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + public void Add(T delta) => RecordMeasurement(delta); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag) => RecordMeasurement(delta, tag); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A first key-value pair tag associated with the measurement. + /// A second key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2) => RecordMeasurement(delta, tag1, tag2); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A first key-value pair tag associated with the measurement. + /// A second key-value pair tag associated with the measurement. + /// A third key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) => RecordMeasurement(delta, tag1, tag2, tag3); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A span of key-value pair tags associated with the measurement. + public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A list of key-value pair tags associated with the measurement. + public void Add(T delta, params KeyValuePair[] tags) => RecordMeasurement(delta, tags.AsSpan()); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A of tags associated with the measurement. + public void Add(T delta, in TagList tagList) => RecordMeasurement(delta, in tagList); + } +} \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs index c0da50f20431d..929a378dd7f78 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs @@ -37,12 +37,18 @@ public void InstrumentCreationTest() Counter counter = meter.CreateCounter("Counter", "seconds", "Seconds Counter"); ValidateInstrumentInfo(counter, "Counter", "seconds", "Seconds Counter", false, false); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter", "seconds", "Seconds UpDownCounter"); + ValidateInstrumentInfo(upDownCounter, "UpDownCounter", "seconds", "Seconds UpDownCounter", false, false); + Histogram histogram = meter.CreateHistogram("Histogram", "centimeters", "centimeters Histogram"); ValidateInstrumentInfo(histogram, "Histogram", "centimeters", "centimeters Histogram", false, false); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => 10, "millisecond", "millisecond ObservableCounter"); ValidateInstrumentInfo(observableCounter, "ObservableCounter", "millisecond", "millisecond ObservableCounter", false, true); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => -1, "request", "request ObservableUpDownCounter"); + ValidateInstrumentInfo(observableUpDownCounter, "ObservableUpDownCounter", "request", "request ObservableUpDownCounter", false, true); + ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => 10, "Fahrenheit", "Fahrenheit ObservableGauge"); ValidateInstrumentInfo(observableGauge, "ObservableGauge", "Fahrenheit", "Fahrenheit ObservableGauge", false, true); }).Dispose(); @@ -55,8 +61,10 @@ public void CreateInstrumentParametersTest() Meter meter = new Meter("CreateInstrumentParametersTest"); Assert.Throws(() => meter.CreateCounter(null, "seconds", "Seconds Counter")); + Assert.Throws(() => meter.CreateUpDownCounter(null, "items", "Items UpDownCounter")); Assert.Throws(() => meter.CreateHistogram(null, "seconds", "Seconds Counter")); Assert.Throws(() => meter.CreateObservableCounter(null, () => 0, "seconds", "Seconds ObservableCounter")); + Assert.Throws(() => meter.CreateObservableUpDownCounter(null, () => 0, "items", "Items ObservableUpDownCounter")); Assert.Throws(() => meter.CreateObservableGauge(null, () => 0, "seconds", "Seconds ObservableGauge")); }).Dispose(); @@ -76,6 +84,14 @@ public void SupportedGenericParameterTypesTest() Counter counter6 = meter.CreateCounter("Counter6", "seconds", "Seconds Counter"); Counter counter7 = meter.CreateCounter("Counter7", "seconds", "Seconds Counter"); + UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("UpDownCounter1", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("UpDownCounter2", "seconds", "Seconds Counter"); + UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("UpDownCounter3", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("UpDownCounter4", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("UpDownCounter5", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("UpDownCounter6", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter7 = meter.CreateUpDownCounter("UpDownCounter7", "seconds", "Seconds UpDownCounter"); + Histogram histogram1 = meter.CreateHistogram("histogram1", "seconds", "Seconds histogram"); Histogram histogram2 = meter.CreateHistogram("histogram2", "seconds", "Seconds histogram"); Histogram histogram3 = meter.CreateHistogram("histogram3", "seconds", "Seconds histogram"); @@ -92,6 +108,14 @@ public void SupportedGenericParameterTypesTest() ObservableCounter observableCounter6 = meter.CreateObservableCounter("observableCounter6", () => 0, "seconds", "Seconds ObservableCounter"); ObservableCounter observableCounter7 = meter.CreateObservableCounter("observableCounter7", () => 0, "seconds", "Seconds ObservableCounter"); + ObservableUpDownCounter observableUpDownCounter1 = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter2 = meter.CreateObservableUpDownCounter("observableUpDownCounter2", () => 0, "items", "Items ObservableCounter"); + ObservableUpDownCounter observableUpDownCounter3 = meter.CreateObservableUpDownCounter("observableUpDownCounter3", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter4 = meter.CreateObservableUpDownCounter("observableUpDownCounter4", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter5 = meter.CreateObservableUpDownCounter("observableUpDownCounter5", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter6 = meter.CreateObservableUpDownCounter("observableUpDownCounter6", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter7 = meter.CreateObservableUpDownCounter("observableUpDownCounter7", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableGauge observableGauge1 = meter.CreateObservableGauge("observableGauge1", () => 0, "seconds", "Seconds ObservableGauge"); ObservableGauge observableGauge2 = meter.CreateObservableGauge("observableGauge2", () => 0, "seconds", "Seconds ObservableGauge"); ObservableGauge observableGauge3 = meter.CreateObservableGauge("observableGauge3", () => 0, "seconds", "Seconds ObservableGauge"); @@ -101,6 +125,7 @@ public void SupportedGenericParameterTypesTest() ObservableGauge observableGauge7 = meter.CreateObservableGauge("observableGauge7", () => 0, "seconds", "Seconds ObservableGauge"); Assert.Throws(() => meter.CreateCounter("Counter", "seconds", "Seconds Counter")); + Assert.Throws(() => meter.CreateUpDownCounter("UpDownCounter", "items", "Items Counter")); Assert.Throws(() => meter.CreateHistogram("histogram1", "seconds", "Seconds histogram")); Assert.Throws(() => meter.CreateObservableCounter("observableCounter3", () => 0, "seconds", "Seconds ObservableCounter")); Assert.Throws(() => meter.CreateObservableGauge("observableGauge7", () => 0, "seconds", "Seconds ObservableGauge")); @@ -134,8 +159,10 @@ public void ListeningToInstrumentsPublishingTest() Histogram histogram = meter.CreateHistogram("histogram1", "seconds", "Seconds histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("observableCounter1", () => 0, "seconds", "Seconds ObservableCounter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter4", "request", "Requests UpDownCounter"); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => 0, "items", "Items ObservableCounter"); - Assert.Equal(4, instrumentsEncountered); + Assert.Equal(6, instrumentsEncountered); // Enable listening to the 4 instruments @@ -143,6 +170,8 @@ public void ListeningToInstrumentsPublishingTest() listener.EnableMeasurementEvents(observableGauge, observableGauge); listener.EnableMeasurementEvents(histogram, histogram); listener.EnableMeasurementEvents(observableCounter, observableCounter); + listener.EnableMeasurementEvents(upDownCounter, upDownCounter); + listener.EnableMeasurementEvents(observableUpDownCounter, observableUpDownCounter); // Enable listening to instruments unpublished event listener.MeasurementsCompleted = (instruments, state) => { instrumentsEncountered--; Assert.Same(state, instruments); }; @@ -169,15 +198,21 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() ObservableGauge gauge1 = meter.CreateObservableGauge("observableGauge1", (Func)(() => throw new ArgumentException())); ObservableCounter counter2 = meter.CreateObservableCounter("observableCounter2", (Func)(() => throw new PlatformNotSupportedException())); ObservableGauge gauge2 = meter.CreateObservableGauge("observableGauge2", (Func)(() => throw new NullReferenceException())); + ObservableUpDownCounter upDownCounterCounter1 = meter.CreateObservableUpDownCounter("upDownCounter1", (Func) (() => throw new ArgumentOutOfRangeException())); + ObservableUpDownCounter upDownCounterCounter2 = meter.CreateObservableUpDownCounter("upDownCounter2", (Func) (() => throw new PlatformNotSupportedException())); ObservableCounter counter3 = meter.CreateObservableCounter("observableCounter3", () => 5); ObservableGauge gauge3 = meter.CreateObservableGauge("observableGauge3", () => 7); + ObservableUpDownCounter upDownCounterCounter3 = meter.CreateObservableUpDownCounter("ObservableUpDownCounter3", () => -1); listener.EnableMeasurementEvents(counter1, null); listener.EnableMeasurementEvents(gauge1, null); listener.EnableMeasurementEvents(counter2, null); listener.EnableMeasurementEvents(gauge2, null); + listener.EnableMeasurementEvents(upDownCounterCounter1, null); + listener.EnableMeasurementEvents(upDownCounterCounter2, null); listener.EnableMeasurementEvents(counter3, null); listener.EnableMeasurementEvents(gauge3, null); + listener.EnableMeasurementEvents(upDownCounterCounter3, null); int accumulated = 0; @@ -187,15 +222,17 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() Assert.NotNull(exception); Assert.IsType(exception); AggregateException ae = exception as AggregateException; - Assert.Equal(4, ae.InnerExceptions.Count); + Assert.Equal(6, ae.InnerExceptions.Count); Assert.IsType(ae.InnerExceptions[0]); Assert.IsType(ae.InnerExceptions[1]); Assert.IsType(ae.InnerExceptions[2]); Assert.IsType(ae.InnerExceptions[3]); + Assert.IsType(ae.InnerExceptions[4]); + Assert.IsType(ae.InnerExceptions[5]); // Ensure the instruments which didn't throw reported correct measurements. - Assert.Equal(12, accumulated); + Assert.Equal(11, accumulated); } }).Dispose(); @@ -208,46 +245,67 @@ public void InstrumentMeasurementTest() Meter meter = new Meter("InstrumentMeasurementTest"); Counter counter = meter.CreateCounter("byteCounter"); - InstruementMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + + UpDownCounter upDownCounter = meter.CreateUpDownCounter("byteUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { upDownCounter.Add(value, tags); }); Counter counter1 = meter.CreateCounter("shortCounter"); - InstruementMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + + UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("shortUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { upDownCounter1.Add(value, tags); }, true); Counter counter2 = meter.CreateCounter("intCounter"); - InstruementMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + + UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("intUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { upDownCounter2.Add(value, tags); }, true); Counter counter3 = meter.CreateCounter("longCounter"); - InstruementMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + + UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("longUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { upDownCounter3.Add(value, tags); }, true); Counter counter4 = meter.CreateCounter("floatCounter"); - InstruementMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + + UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("floatUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { upDownCounter4.Add(value, tags); }, true); Counter counter5 = meter.CreateCounter("doubleCounter"); - InstruementMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + + UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("doubleUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { upDownCounter5.Add(value, tags); }, true); Counter counter6 = meter.CreateCounter("decimalCounter"); - InstruementMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + + UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("decimalUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { upDownCounter6.Add(value, tags); }, true); Histogram histogram = meter.CreateHistogram("byteHistogram"); - InstruementMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); Histogram histogram1 = meter.CreateHistogram("shortHistogram"); - InstruementMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); Histogram histogram2 = meter.CreateHistogram("intHistogram"); - InstruementMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); Histogram histogram3 = meter.CreateHistogram("longHistogram"); - InstruementMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); Histogram histogram4 = meter.CreateHistogram("floatHistogram"); - InstruementMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); Histogram histogram5 = meter.CreateHistogram("doubleHistogram"); - InstruementMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); Histogram histogram6 = meter.CreateHistogram("decimalHistogram"); - InstruementMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); }).Dispose(); } @@ -263,99 +321,148 @@ public void ObservableInstrumentMeasurementTest() // CreateObservableCounter using Func // ObservableCounter observableCounter = meter.CreateObservableCounter("ByteObservableCounter", () => 50); - ObservableInstruementMeasurementAggregationValidation(observableCounter, new Measurement[] { new Measurement(50)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter, new Measurement[] { new Measurement(50)}); ObservableCounter observableCounter1 = meter.CreateObservableCounter("ShortObservableCounter", () => 30_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter1, new Measurement[] { new Measurement(30_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter1, new Measurement[] { new Measurement(30_000)}); ObservableCounter observableCounter2 = meter.CreateObservableCounter("IntObservableCounter", () => 1_000_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter2, new Measurement[] { new Measurement(1_000_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter2, new Measurement[] { new Measurement(1_000_000)}); ObservableCounter observableCounter3 = meter.CreateObservableCounter("longObservableCounter", () => 1_000_000_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter3, new Measurement[] { new Measurement(1_000_000_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter3, new Measurement[] { new Measurement(1_000_000_000)}); ObservableCounter observableCounter4 = meter.CreateObservableCounter("floatObservableCounter", () => 3.14f); - ObservableInstruementMeasurementAggregationValidation(observableCounter4, new Measurement[] { new Measurement(3.14f)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter4, new Measurement[] { new Measurement(3.14f)}); ObservableCounter observableCounter5 = meter.CreateObservableCounter("doubleObservableCounter", () => 1e6); - ObservableInstruementMeasurementAggregationValidation(observableCounter5, new Measurement[] { new Measurement(1e6)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter5, new Measurement[] { new Measurement(1e6)}); ObservableCounter observableCounter6 = meter.CreateObservableCounter("decimalObservableCounter", () => 1.5E6m); - ObservableInstruementMeasurementAggregationValidation(observableCounter6, new Measurement[] { new Measurement(1.5E6m)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter6, new Measurement[] { new Measurement(1.5E6m)}); + + // + // CreateObservableUpDownCounter using Func + // + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => 10); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter, new Measurement[] { new Measurement(10)}); + ObservableUpDownCounter observableUpDownCounter1 = meter.CreateObservableUpDownCounter("shortObservableUpDownCounter", () => -10); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter1, new Measurement[] { new Measurement(-10)}); + ObservableUpDownCounter observableUpDownCounter2 = meter.CreateObservableUpDownCounter("intObservableUpDownCounter", () => -12); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter2, new Measurement[] { new Measurement(-12)}); + ObservableUpDownCounter observableUpDownCounter3 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => -100); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter3, new Measurement[] { new Measurement(-100)}); + ObservableUpDownCounter observableUpDownCounter4 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => -3.4f); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter4, new Measurement[] { new Measurement(-3.4f)}); + ObservableUpDownCounter observableUpDownCounter5 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => -3.14); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter5, new Measurement[] { new Measurement(-3.14)}); + ObservableUpDownCounter observableUpDownCounter6 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => -32222.14m); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter6, new Measurement[] { new Measurement(-32222.14m)}); // // CreateObservableGauge using Func // ObservableGauge observableGauge = meter.CreateObservableGauge("ByteObservableGauge", () => 100); - ObservableInstruementMeasurementAggregationValidation(observableGauge, new Measurement[] { new Measurement(100)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge, new Measurement[] { new Measurement(100)}); ObservableGauge observableGauge1 = meter.CreateObservableGauge("ShortObservableGauge", () => 30_123); - ObservableInstruementMeasurementAggregationValidation(observableGauge1, new Measurement[] { new Measurement(30_123)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge1, new Measurement[] { new Measurement(30_123)}); ObservableGauge observableGauge2 = meter.CreateObservableGauge("IntObservableGauge", () => 2_123_456); - ObservableInstruementMeasurementAggregationValidation(observableGauge2, new Measurement[] { new Measurement(2_123_456)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge2, new Measurement[] { new Measurement(2_123_456)}); ObservableGauge observableGauge3 = meter.CreateObservableGauge("longObservableGauge", () => 3_123_456_789); - ObservableInstruementMeasurementAggregationValidation(observableGauge3, new Measurement[] { new Measurement(3_123_456_789)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge3, new Measurement[] { new Measurement(3_123_456_789)}); ObservableGauge observableGauge4 = meter.CreateObservableGauge("floatObservableGauge", () => 1.6f); - ObservableInstruementMeasurementAggregationValidation(observableGauge4, new Measurement[] { new Measurement(1.6f)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge4, new Measurement[] { new Measurement(1.6f)}); ObservableGauge observableGauge5 = meter.CreateObservableGauge("doubleObservableGauge", () => 1e5); - ObservableInstruementMeasurementAggregationValidation(observableGauge5, new Measurement[] { new Measurement(1e5)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge5, new Measurement[] { new Measurement(1e5)}); ObservableGauge observableGauge6 = meter.CreateObservableGauge("decimalObservableGauge", () => 2.5E7m); - ObservableInstruementMeasurementAggregationValidation(observableGauge6, new Measurement[] { new Measurement(2.5E7m)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge6, new Measurement[] { new Measurement(2.5E7m)}); // // CreateObservableCounter using Func> // Measurement byteMeasurement = new Measurement(60, new KeyValuePair[] { new KeyValuePair("T1", "V1"), new KeyValuePair("T2", "V2") }); ObservableCounter observableCounter7 = meter.CreateObservableCounter("ByteObservableCounter", () => byteMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter7, new Measurement[] { byteMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter7, new Measurement[] { byteMeasurement }); Measurement shortMeasurement = new Measurement(20_000, new KeyValuePair[] { new KeyValuePair("T3", "V3"), new KeyValuePair("T4", "V4") }); ObservableCounter observableCounter8 = meter.CreateObservableCounter("ShortObservableCounter", () => shortMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter8, new Measurement[] { shortMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter8, new Measurement[] { shortMeasurement }); Measurement intMeasurement = new Measurement(2_000_000, new KeyValuePair[] { new KeyValuePair("T5", "V5"), new KeyValuePair("T6", "V6") }); ObservableCounter observableCounter9 = meter.CreateObservableCounter("IntObservableCounter", () => intMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter9, new Measurement[] { intMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter9, new Measurement[] { intMeasurement }); Measurement longMeasurement = new Measurement(20_000_000_000, new KeyValuePair[] { new KeyValuePair("T7", "V7"), new KeyValuePair("T8", "V8") }); ObservableCounter observableCounter10 = meter.CreateObservableCounter("longObservableCounter", () => longMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter10, new Measurement[] { longMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter10, new Measurement[] { longMeasurement }); Measurement floatMeasurement = new Measurement(1e2f, new KeyValuePair[] { new KeyValuePair("T9", "V10"), new KeyValuePair("T11", "V12") }); ObservableCounter observableCounter11 = meter.CreateObservableCounter("floatObservableCounter", () => 3.14f); - ObservableInstruementMeasurementAggregationValidation(observableCounter11, new Measurement[] { new Measurement(3.14f)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter11, new Measurement[] { new Measurement(3.14f)}); Measurement doubleMeasurement = new Measurement(2.5e7, new KeyValuePair[] { new KeyValuePair("T13", "V14"), new KeyValuePair("T15", "V16") }); ObservableCounter observableCounter12 = meter.CreateObservableCounter("doubleObservableCounter", () => doubleMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter12, new Measurement[] { doubleMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter12, new Measurement[] { doubleMeasurement }); Measurement decimalMeasurement = new Measurement(3.2e20m, new KeyValuePair[] { new KeyValuePair("T17", "V18"), new KeyValuePair("T19", "V20") }); ObservableCounter observableCounter13 = meter.CreateObservableCounter("decimalObservableCounter", () => decimalMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter13, new Measurement[] { decimalMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter13, new Measurement[] { decimalMeasurement }); + + // + // CreateObservableUpDownCounter using Func> + // + Measurement byteMeasurement1 = new Measurement(100, new KeyValuePair[] { new KeyValuePair("T1", "V1"), new KeyValuePair("T2", "V2") }); + ObservableUpDownCounter observableUpDownCounter7 = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => byteMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter7, new Measurement[] { byteMeasurement1 }); + + Measurement shortMeasurement1 = new Measurement(-20_000, new KeyValuePair[] { new KeyValuePair("T3", "V3"), new KeyValuePair("T4", "V4") }); + ObservableUpDownCounter observableUpDownCounter8 = meter.CreateObservableUpDownCounter("ShortObservableUpDownCounter", () => shortMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter8, new Measurement[] { shortMeasurement1 }); + + Measurement intMeasurement1 = new Measurement(-2_000_000, new KeyValuePair[] { new KeyValuePair("T5", "V5"), new KeyValuePair("T6", "V6") }); + ObservableUpDownCounter observableUpDownCounter9 = meter.CreateObservableUpDownCounter("IntObservableUpDownCounter", () => intMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter9, new Measurement[] { intMeasurement1 }); + + Measurement longMeasurement1 = new Measurement(-20_000_000_000, new KeyValuePair[] { new KeyValuePair("T7", "V7"), new KeyValuePair("T8", "V8") }); + ObservableUpDownCounter observableUpDownCounter10 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => longMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter10, new Measurement[] { longMeasurement1 }); + + Measurement floatMeasurement1 = new Measurement(-1e2f, new KeyValuePair[] { new KeyValuePair("T9", "V10"), new KeyValuePair("T11", "V12") }); + ObservableUpDownCounter observableUpDownCounter11 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => floatMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter11, new Measurement[] { floatMeasurement1 }); + + Measurement doubleMeasurement1 = new Measurement(-2.5e7, new KeyValuePair[] { new KeyValuePair("T13", "V14"), new KeyValuePair("T15", "V16") }); + ObservableUpDownCounter observableUpDownCounter12 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => doubleMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter12, new Measurement[] { doubleMeasurement1 }); + + Measurement decimalMeasurement1 = new Measurement(-3.2e20m, new KeyValuePair[] { new KeyValuePair("T17", "V18"), new KeyValuePair("T19", "V20") }); + ObservableUpDownCounter observableUpDownCounter13 = meter.CreateObservableUpDownCounter("decimalObservableUpDownCounter", () => decimalMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter13, new Measurement[] { decimalMeasurement1 }); // // CreateObservableGauge using Func> // Measurement byteGaugeMeasurement = new Measurement(35, new KeyValuePair[] { new KeyValuePair("T21", "V22"), new KeyValuePair("T23", "V24") }); ObservableGauge observableGauge7 = meter.CreateObservableGauge("ByteObservableGauge", () => byteGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge7, new Measurement[] { byteGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge7, new Measurement[] { byteGaugeMeasurement }); Measurement shortGaugeMeasurement = new Measurement(23_987, new KeyValuePair[] { new KeyValuePair("T25", "V26"), new KeyValuePair("T27", "V28") }); ObservableGauge observableGauge8 = meter.CreateObservableGauge("ShortObservableGauge", () => shortGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge8, new Measurement[] { shortGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge8, new Measurement[] { shortGaugeMeasurement }); Measurement intGaugeMeasurement = new Measurement(1_987_765, new KeyValuePair[] { new KeyValuePair("T29", "V30"), new KeyValuePair("T31", "V32") }); ObservableGauge observableGauge9 = meter.CreateObservableGauge("IntObservableGauge", () => intGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge9, new Measurement[] { intGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge9, new Measurement[] { intGaugeMeasurement }); Measurement longGaugeMeasurement = new Measurement(10_000_234_343, new KeyValuePair[] { new KeyValuePair("T33", "V342"), new KeyValuePair("T35", "V36") }); ObservableGauge observableGauge10 = meter.CreateObservableGauge("longObservableGauge", () => longGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge10, new Measurement[] { longGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge10, new Measurement[] { longGaugeMeasurement }); Measurement floatGaugeMeasurement = new Measurement(2.1f, new KeyValuePair[] { new KeyValuePair("T37", "V38"), new KeyValuePair("T39", "V40") }); ObservableGauge observableGauge11 = meter.CreateObservableGauge("floatObservableGauge", () => floatGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge11, new Measurement[] { floatGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge11, new Measurement[] { floatGaugeMeasurement }); Measurement doubleGaugeMeasurement = new Measurement(1.5e30, new KeyValuePair[] { new KeyValuePair("T41", "V42"), new KeyValuePair("T43", "V44") }); ObservableGauge observableGauge12 = meter.CreateObservableGauge("doubleObservableGauge", () => doubleGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge12, new Measurement[] { doubleGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge12, new Measurement[] { doubleGaugeMeasurement }); Measurement decimalGaugeMeasurement = new Measurement(2.5e20m, new KeyValuePair[] { new KeyValuePair("T45", "V46"), new KeyValuePair("T47", "V48") }); ObservableGauge observableGauge13 = meter.CreateObservableGauge("decimalObservableGauge", () => decimalGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge13, new Measurement[] { decimalGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge13, new Measurement[] { decimalGaugeMeasurement }); // // CreateObservableCounter using Func> @@ -366,7 +473,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1, new KeyValuePair[] { new KeyValuePair("T51", "V52"), new KeyValuePair("T53", "V54") }), }; ObservableCounter observableCounter14 = meter.CreateObservableCounter("ByteObservableCounter", () => byteGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter14, byteGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter14, byteGaugeMeasurementList); Measurement[] shortGaugeMeasurementList = new Measurement[] { @@ -374,7 +481,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(30_000, new KeyValuePair[] { new KeyValuePair("T59", "V60"), new KeyValuePair("T61", "V62") }), }; ObservableCounter observableCounter15 = meter.CreateObservableCounter("ShortObservableCounter", () => shortGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter15, shortGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter15, shortGaugeMeasurementList); Measurement[] intGaugeMeasurementList = new Measurement[] { @@ -382,7 +489,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1_000_002, new KeyValuePair[] { new KeyValuePair("T67", "V68"), new KeyValuePair("T69", "V70") }), }; ObservableCounter observableCounter16 = meter.CreateObservableCounter("IntObservableCounter", () => intGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter16, intGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter16, intGaugeMeasurementList); Measurement[] longGaugeMeasurementList = new Measurement[] { @@ -390,7 +497,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1_000_002_002, new KeyValuePair[] { new KeyValuePair("T75", "V76"), new KeyValuePair("T77", "V78") }), }; ObservableCounter observableCounter17 = meter.CreateObservableCounter("longObservableCounter", () => longGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter17, longGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter17, longGaugeMeasurementList); Measurement[] floatGaugeMeasurementList = new Measurement[] { @@ -398,7 +505,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e6f, new KeyValuePair[] { new KeyValuePair("T83", "V84"), new KeyValuePair("T85", "V86") }), }; ObservableCounter observableCounter18 = meter.CreateObservableCounter("floatObservableCounter", () => floatGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter18, floatGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter18, floatGaugeMeasurementList); Measurement[] doubleGaugeMeasurementList = new Measurement[] { @@ -406,7 +513,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e21, new KeyValuePair[] { new KeyValuePair("T91", "V92"), new KeyValuePair("T93", "V94") }), }; ObservableCounter observableCounter19 = meter.CreateObservableCounter("doubleObservableCounter", () => doubleGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter19, doubleGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter19, doubleGaugeMeasurementList); Measurement[] decimalGaugeMeasurementList = new Measurement[] { @@ -414,31 +521,90 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e6m, new KeyValuePair[] { new KeyValuePair("T99", "V100"), new KeyValuePair("T101", "V102") }), }; ObservableCounter observableCounter20 = meter.CreateObservableCounter("decimalObservableCounter", () => decimalGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter20, decimalGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter20, decimalGaugeMeasurementList); + + // + // CreateObservableUpDownCounter using Func> + // + Measurement[] byteUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(10, new KeyValuePair[] { new KeyValuePair("T48", "V49"), new KeyValuePair("T50", "V51") }), + new Measurement(12, new KeyValuePair[] { new KeyValuePair("T51", "V52"), new KeyValuePair("T53", "V54") }), + }; + ObservableUpDownCounter observableUpDownCounter14 = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => byteUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter14, byteUpDownCounterMeasurementList); + + Measurement[] shortUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-20_000, new KeyValuePair[] { new KeyValuePair("T55", "V56"), new KeyValuePair("T57", "V58") }), + new Measurement(30_000, new KeyValuePair[] { new KeyValuePair("T59", "V60"), new KeyValuePair("T61", "V62") }), + }; + ObservableUpDownCounter observableUpDownCounter15 = meter.CreateObservableUpDownCounter("ShortObservableUpDownCounter", () => shortUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter15, shortUpDownCounterMeasurementList); + + Measurement[] intUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(1_000_001, new KeyValuePair[] { new KeyValuePair("T63", "V64"), new KeyValuePair("T65", "V66") }), + new Measurement(-1_000_002, new KeyValuePair[] { new KeyValuePair("T67", "V68"), new KeyValuePair("T69", "V70") }), + }; + ObservableUpDownCounter observableUpDownCounter16 = meter.CreateObservableUpDownCounter("IntObservableUpDownCounter", () => intUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter16, intUpDownCounterMeasurementList); + + Measurement[] longUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-1_000_001_001, new KeyValuePair[] { new KeyValuePair("T71", "V72"), new KeyValuePair("T73", "V74") }), + new Measurement(1_000_002_002, new KeyValuePair[] { new KeyValuePair("T75", "V76"), new KeyValuePair("T77", "V78") }), + }; + ObservableUpDownCounter observableUpDownCounter17 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => longUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter17, longUpDownCounterMeasurementList); + + Measurement[] floatUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-68.15e8f, new KeyValuePair[] { new KeyValuePair("T79", "V80"), new KeyValuePair("T81", "V82") }), + new Measurement(-68.15e6f, new KeyValuePair[] { new KeyValuePair("T83", "V84"), new KeyValuePair("T85", "V86") }), + }; + ObservableUpDownCounter observableUpDownCounter18 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => floatUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter18, floatUpDownCounterMeasurementList); + + Measurement[] doubleUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-68.15e20, new KeyValuePair[] { new KeyValuePair("T87", "V88"), new KeyValuePair("T89", "V90") }), + new Measurement(68.15e21, new KeyValuePair[] { new KeyValuePair("T91", "V92"), new KeyValuePair("T93", "V94") }), + }; + ObservableUpDownCounter observableUpDownCounter19 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => doubleUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter19, doubleUpDownCounterMeasurementList); + + Measurement[] decimalUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(68.15e8m, new KeyValuePair[] { new KeyValuePair("T95", "V96"), new KeyValuePair("T97", "V98") }), + new Measurement(-68.15e6m, new KeyValuePair[] { new KeyValuePair("T99", "V100"), new KeyValuePair("T101", "V102") }), + }; + ObservableUpDownCounter observableUpDownCounter20 = meter.CreateObservableUpDownCounter("decimalObservableUpDownCounter", () => decimalUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter20, decimalUpDownCounterMeasurementList); // // CreateObservableGauge using IEnumerable> // ObservableGauge observableGauge14 = meter.CreateObservableGauge("ByteObservableGauge", () => byteGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge14, byteGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge14, byteGaugeMeasurementList); ObservableGauge observableGauge15 = meter.CreateObservableGauge("ShortObservableGauge", () => shortGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge15, shortGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge15, shortGaugeMeasurementList); ObservableGauge observableGauge16 = meter.CreateObservableGauge("IntObservableGauge", () => intGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge16, intGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge16, intGaugeMeasurementList); ObservableGauge observableGauge17 = meter.CreateObservableGauge("longObservableGauge", () => longGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge17, longGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge17, longGaugeMeasurementList); ObservableGauge observableGauge18 = meter.CreateObservableGauge("floatObservableGauge", () => floatGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge18, floatGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge18, floatGaugeMeasurementList); ObservableGauge observableGauge19 = meter.CreateObservableGauge("doubleObservableGauge", () => doubleGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge19, doubleGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge19, doubleGaugeMeasurementList); ObservableGauge observableGauge20 = meter.CreateObservableGauge("decimalObservableGauge", () => decimalGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge20, decimalGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge20, decimalGaugeMeasurementList); }).Dispose(); } @@ -485,6 +651,42 @@ public void PassingVariableTagsParametersTest() return (decimal)(value * 2); }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (byte)(value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (short)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (int)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (long)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (float)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (double)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (decimal)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateHistogram("Histogram"), (instrument, value, tags) => { PublishHistogramMeasurement(instrument as Histogram, value, tags); @@ -531,11 +733,15 @@ public void MeterDisposalsTest() Meter meter2 = new Meter("MeterDisposalsTest2"); Meter meter3 = new Meter("MeterDisposalsTest3"); Meter meter4 = new Meter("MeterDisposalsTest4"); + Meter meter5 = new Meter("MeterDisposalsTest5"); + Meter meter6 = new Meter("MeterDisposalsTest6"); Counter counter = meter1.CreateCounter("Counter"); Histogram histogram = meter2.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter3.CreateObservableCounter("ObservableCounter", () => new Measurement(10, new KeyValuePair[] { new KeyValuePair("Key", "value")})); ObservableGauge observableGauge = meter4.CreateObservableGauge("ObservableGauge", () => new Measurement(5.7m, new KeyValuePair[] { new KeyValuePair("Key", "value")})); + UpDownCounter upDownCounter = meter5.CreateUpDownCounter("UpDownCounter"); + ObservableUpDownCounter observableUpDownCounter = meter6.CreateObservableUpDownCounter("ObservableUpDownCounter", () => new Measurement(-5, new KeyValuePair[] { new KeyValuePair("Key", "value")})); using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => theListener.EnableMeasurementEvents(theInstrument, theInstrument); @@ -543,6 +749,7 @@ public void MeterDisposalsTest() int count = 0; listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); @@ -554,30 +761,41 @@ public void MeterDisposalsTest() counter.Add(1); Assert.Equal(1, count); - histogram.Record(1); + upDownCounter.Add(-1); Assert.Equal(2, count); + histogram.Record(1); + Assert.Equal(3, count); + listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); meter1.Dispose(); counter.Add(1); - Assert.Equal(4, count); + Assert.Equal(6, count); meter2.Dispose(); histogram.Record(1); - Assert.Equal(4, count); + Assert.Equal(6, count); - listener.RecordObservableInstruments(); + meter5.Dispose(); + upDownCounter.Add(-10); Assert.Equal(6, count); + listener.RecordObservableInstruments(); + Assert.Equal(9, count); + meter3.Dispose(); listener.RecordObservableInstruments(); - Assert.Equal(7, count); + Assert.Equal(11, count); meter4.Dispose(); listener.RecordObservableInstruments(); - Assert.Equal(7, count); + Assert.Equal(12, count); + + meter6.Dispose(); + listener.RecordObservableInstruments(); + Assert.Equal(12, count); }).Dispose(); } @@ -589,9 +807,11 @@ public void ListenerDisposalsTest() Meter meter = new Meter("ListenerDisposalsTest"); Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("upDownCounter"); Histogram histogram = meter.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => new Measurement(10, new KeyValuePair[] { new KeyValuePair("Key", "value")})); ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => new Measurement(5.7m, new KeyValuePair[] { new KeyValuePair("Key", "value")})); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => new Measurement(-5.7f, new KeyValuePair[] { new KeyValuePair("Key", "value")})); int completedMeasurements = 0; MeterListener listener = new MeterListener(); @@ -600,7 +820,9 @@ public void ListenerDisposalsTest() int count = 0; + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); @@ -612,23 +834,26 @@ public void ListenerDisposalsTest() counter.Add(1); Assert.Equal(1, count); - histogram.Record(1); + upDownCounter.Add(-1); Assert.Equal(2, count); + histogram.Record(1); + Assert.Equal(3, count); + listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); listener.Dispose(); - Assert.Equal(4, completedMeasurements); + Assert.Equal(6, completedMeasurements); counter.Add(1); - Assert.Equal(4, count); + Assert.Equal(6, count); histogram.Record(1); - Assert.Equal(4, count); + Assert.Equal(6, count); listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); }).Dispose(); } @@ -712,8 +937,10 @@ public void ParallelRunningTest() Meter meter = new Meter("ParallelRunningTest"); Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter"); Histogram histogram = meter.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => 1); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => 1); ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => 1); MeterListener listener = new MeterListener(); @@ -723,7 +950,7 @@ public void ParallelRunningTest() listener.SetMeasurementEventCallback((inst, measurement, tags, state) => Interlocked.Add(ref totalCount, measurement)); listener.Start(); - Task[] taskList = new Task[6]; + Task[] taskList = new Task[9]; int loopLength = 10_000; @@ -733,10 +960,13 @@ public void ParallelRunningTest() taskList[3] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { histogram.Record(1); } }); taskList[4] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); taskList[5] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); + taskList[6] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { upDownCounter.Add(1); } }); + taskList[7] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { upDownCounter.Add(1); } }); + taskList[8] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); Task.WaitAll(taskList); - Assert.Equal(loopLength * 8, totalCount); + Assert.Equal(loopLength * 15, totalCount); }).Dispose(); } @@ -817,9 +1047,11 @@ public void TestRecordingMeasurementsWithTagList() using (MeterListener listener = new MeterListener()) { Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter"); Histogram histogram = meter.CreateHistogram("histogram"); listener.EnableMeasurementEvents(counter, counter); + listener.EnableMeasurementEvents(upDownCounter, upDownCounter); listener.EnableMeasurementEvents(histogram, histogram); KeyValuePair[] expectedTags = null; @@ -835,11 +1067,13 @@ public void TestRecordingMeasurementsWithTagList() expectedTags = new KeyValuePair[0]; counter.Add(10, new TagList()); + upDownCounter.Add(-1, new TagList()); histogram.Record(10, new TagList()); // 1 Tags expectedTags = new KeyValuePair[] { new KeyValuePair("Key1", "Value1") }; counter.Add(10, new TagList() { expectedTags[0] }); + upDownCounter.Add(-2, new TagList() { expectedTags[0] }); histogram.Record(10, new TagList() { new KeyValuePair("Key1", "Value1") }); // 2 Tags @@ -850,6 +1084,7 @@ public void TestRecordingMeasurementsWithTagList() }.ToArray(); counter.Add(10, new TagList() { expectedTags[0], expectedTags[1] }); + upDownCounter.Add(-3, new TagList() { expectedTags[0], expectedTags[1] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1] }); // 8 Tags @@ -866,6 +1101,7 @@ public void TestRecordingMeasurementsWithTagList() }.ToArray(); counter.Add(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); + upDownCounter.Add(-4, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); // 13 Tags @@ -888,6 +1124,8 @@ public void TestRecordingMeasurementsWithTagList() counter.Add(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); + upDownCounter.Add(-5, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], + expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); } @@ -913,6 +1151,24 @@ private void PublishCounterMeasurement(Counter counter, T value, KeyValueP } } + private void PublishUpDownCounterMeasurement(UpDownCounter counter, T value, KeyValuePair[] tags) where T : struct + { + switch (tags.Length) + { + case 0: counter.Add(value); break; + case 1: counter.Add(value, tags[0]); break; + case 2: counter.Add(value, tags[0], tags[1]); break; + case 3: counter.Add(value, tags[0], tags[1], tags[2]); break; + case 4: counter.Add(value, tags[0], tags[1], tags[2], tags[3]); break; + case 5: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4]); break; + case 6: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5]); break; + case 7: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6]); break; + case 8: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6], tags[7]); break; + case 9: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6], tags[7], tags[8]); break; + default: counter.Add(value, tags); break; + } + } + private void PublishHistogramMeasurement(Histogram histogram, T value, KeyValuePair[] tags) where T : struct { switch (tags.Length) @@ -940,7 +1196,7 @@ private void ValidateInstrumentInfo(Instrument instrument, string name, string u Assert.Equal(isObservable, instrument.IsObservable); } - private void InstruementMeasurementAggregationValidation(Instrument instrument, Action[]> record) where T : struct + private void InstrumentMeasurementAggregationValidation(Instrument instrument, Action[]> record, bool allowNegative = false) where T : struct { using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => @@ -968,17 +1224,28 @@ private void InstruementMeasurementAggregationValidation(Instrument instru listener.Start(); - for (byte i = 0; i < 100; i++) + if (allowNegative && typeof(T) != typeof(Byte)) { - expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); - expectedValue = ConvertValue(i); - record(expectedValue, expectedTags.ToArray()); + for (short i = 0; i < 100; i++) + { + expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); + expectedValue = ConvertValue((short)(i % 2 == 0 ? 2 : -1)); + record(expectedValue, expectedTags.ToArray()); + } + } + else + { + for (short i = 0; i < 100; i++) + { + expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); + expectedValue = ConvertValue(i); + record(expectedValue, expectedTags.ToArray()); + } } - Assert.Equal(100, counter); } - private void ObservableInstruementMeasurementAggregationValidation(ObservableInstrument instrument, Measurement[] expectedResult) where T : struct + private void ObservableInstrumentMeasurementAggregationValidation(ObservableInstrument instrument, Measurement[] expectedResult) where T : struct { using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => @@ -1121,10 +1388,10 @@ private void InstrumentPassingVariableTagsParametersTest(Instrument instru expectedValue = record(instrument, expectedValue, expectedTags); } - private T ConvertValue(byte value) where T : struct + private T ConvertValue(short value) where T : struct { - if (typeof(T) == typeof(byte)) { return (T)(object)value;} - if (typeof(T) == typeof(short)) { return (T)(object)Convert.ToInt16(value); } + if (typeof(T) == typeof(byte)) { return (T)(object)(byte)value; } + if (typeof(T) == typeof(short)) { return (T)(object)value; } if (typeof(T) == typeof(int)) { return (T)(object)Convert.ToInt32(value); } if (typeof(T) == typeof(long)) { return (T)(object)Convert.ToInt64(value); } if (typeof(T) == typeof(float)) { return (T)(object)Convert.ToSingle(value); } diff --git a/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx index ffeb7516c3a7e..e0aec25828364 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx @@ -137,9 +137,6 @@ Cannot retrieve all entries. - - Only the first eight characters of a custom log name are significant, and there is already another log on the system using the first eight characters of the name given. Name given: '{0}', name of existing log: '{1}'. - Invalid eventID value '{0}'. It must be in the range between '{1}' and '{2}'. @@ -242,7 +239,4 @@ Log {0} has already been registered as a source on the local computer. - - Opening Win32 devices other than file such as COM ports, printers, disk partitions and tape drives is not supported. Avoid use of "\\\\.\\" in the path. - diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj index 9851685566186..220c3e850b5f1 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj @@ -6,6 +6,7 @@ + @@ -18,4 +19,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs new file mode 100644 index 0000000000000..b33f32066185b --- /dev/null +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Diagnostics +{ + public readonly partial struct CounterSample : System.IEquatable + { + } +} diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx index 1a5909f5194cf..829c04125b373 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx @@ -158,9 +158,6 @@ Cannot access shared memory, AppDomain has been unloaded. - - Cannot initialize security descriptor initialized. - Cannot create file mapping. @@ -322,7 +319,7 @@ CounterSet '{0}' does not include any counters. - + CounterSet '{0}' already registered. diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 28133feec83ed..5ebf58e40c57e 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -3,6 +3,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) $(NoWarn);CA1847 + $(NoWarn);CA1066 annotations true Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters. diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs index c89df23ed9aac..315ec5a87ccb4 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics /// /// A struct holding the raw data for a performance counter. /// - public readonly struct CounterSample + public readonly struct CounterSample : IEquatable { private readonly long _rawValue; private readonly long _baseValue; diff --git a/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx index 31cd6a75a072a..ddbeed29f973a 100644 --- a/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx @@ -215,9 +215,6 @@ An async read operation has already been started on the stream. - - Invalid value '{1}' for parameter '{0}'. - Cannot load Category Help data because an invalid index '{0}' was read from the registry. @@ -311,9 +308,6 @@ UseShellExecute is not supported on this platform. - - Retrieving information about local processes is not supported on this platform. - StandardInputEncoding is only supported when standard input is redirected. @@ -338,4 +332,4 @@ sysctl {0} failed with {1} error. - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs index 85525bbe3e8a5..7a776feba46dc 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs @@ -10,11 +10,7 @@ internal static partial class ProcessManager /// true if the machine is remote; false if it's local. public static bool IsRemoteMachine(string machineName) { - if (machineName == null) - throw new ArgumentNullException(nameof(machineName)); - - if (machineName.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidParameter, nameof(machineName), machineName)); + ArgumentException.ThrowIfNullOrEmpty(machineName); return IsRemoteMachineCore(machineName); } diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 18406af45353f..b9d70837e3d16 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -1147,7 +1147,7 @@ public void GetProcesseses_NullMachineName_ThrowsArgumentNullException() [Fact] public void GetProcesses_EmptyMachineName_ThrowsArgumentException() { - AssertExtensions.Throws(null, () => Process.GetProcesses("")); + AssertExtensions.Throws("machineName", () => Process.GetProcesses("")); } [Fact] @@ -1292,7 +1292,7 @@ public void GetProcessesByName_NullMachineName_ThrowsArgumentNullException() public void GetProcessesByName_EmptyMachineName_ThrowsArgumentException() { Process currentProcess = Process.GetCurrentProcess(); - AssertExtensions.Throws(null, () => Process.GetProcessesByName(currentProcess.ProcessName, "")); + AssertExtensions.Throws("machineName", () => Process.GetProcessesByName(currentProcess.ProcessName, "")); } [Fact] diff --git a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs index 0efbf90bb1da1..60e755ecf790c 100644 --- a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs +++ b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs @@ -170,7 +170,7 @@ public enum SymAddressKind BitField = 9, NativeSectionOffset = 10, } - public readonly partial struct SymbolToken + public readonly partial struct SymbolToken : System.IEquatable { private readonly int _dummyPrimitive; public SymbolToken(int val) { throw null; } diff --git a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs index b6a894f144fc9..8b27f618770fb 100644 --- a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs +++ b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.SymbolStore { - public readonly struct SymbolToken + public readonly struct SymbolToken : IEquatable { private readonly int _token; diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx index 12b248f4ddec2..b994dce1b5ab6 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -57,10 +58,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - '{0}' can not be empty string. - Trace - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs index 6c399ae77bc40..52454f94c6906 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs @@ -63,11 +63,7 @@ public string Delimiter } set { - if (value == null) - throw new ArgumentNullException(nameof(Delimiter)); - - if (value.Length == 0) - throw new ArgumentException(SR.Format(SR.Generic_ArgCantBeEmptyString, nameof(Delimiter))); + ArgumentException.ThrowIfNullOrEmpty(value, nameof(Delimiter)); lock (this) { diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs index f7620b442c5c1..352d0d1a6b29c 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs @@ -90,8 +90,8 @@ public static void TestDelimiterProperty() { var target = new DelimitedListTraceListener(FileStream.Null); Assert.Equal(DefaultDelimiter, target.Delimiter); - Assert.Throws(() => target.Delimiter = null); - AssertExtensions.Throws(null, () => target.Delimiter = string.Empty); + AssertExtensions.Throws("Delimiter", () => target.Delimiter = null); + AssertExtensions.Throws("Delimiter", () => target.Delimiter = string.Empty); } [Fact] diff --git a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx index 8b4f1d8731413..4062db3292bae 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -87,7 +88,4 @@ Attempted to set {0} to a value that is too high. Setting level to TraceLevel.Verbose - - Argument {0} cannot be null or zero-length. - - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs index 4b474c82442af..18b00fdf83f63 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs @@ -26,10 +26,7 @@ public string SwitchName [MemberNotNull(nameof(_name))] set { - if (value == null) - throw new ArgumentNullException(nameof(value)); - if (value.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidNullEmptyArgument, nameof(value)), nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _name = value; } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs index aa786154cbb56..4aedca7d878f5 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs @@ -28,10 +28,7 @@ public TraceSource(string name) public TraceSource(string name, SourceLevels defaultLevel) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidNullEmptyArgument, nameof(name)), nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); _sourceName = name; _switchLevel = defaultLevel; diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs index 2ee59adf59464..012a03bcad1c1 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs @@ -82,13 +82,13 @@ public void Test_GenerateManifest_InvalidEventSources() Assert.NotNull(EventSource.GenerateManifest(typeof(Sdt.EventWithReturnEventSource), string.Empty, EventManifestOptions.AllowEventSourceOverride)); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty, strictOptions)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty, EventManifestOptions.AllowEventSourceOverride)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.OutOfRangeKwdEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, @@ -124,7 +124,7 @@ public void Test_GenerateManifest_InvalidEventSources() e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EnumKindMismatchEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EnumKindMismatch", "Op1", "EventKeywords", "Opcodes"), + GetResourceString("EventSource_EnumKindMismatch", "EventKeywords", "Opcodes"), GetResourceString("EventSource_UndefinedKeyword", "0x1", "WriteInteger")), e); @@ -144,14 +144,14 @@ public void Test_GenerateManifest_InvalidEventSources() e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EventIdReusedEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1, "WriteInteger1"), + GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1), GetResourceString("EventSource_TaskOpcodePairReused", "WriteInteger2", 1, "WriteInteger1", 1)), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EventIdReusedEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1, "WriteInteger1"), + GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1), GetResourceString("EventSource_TaskOpcodePairReused", "WriteInteger2", 1, "WriteInteger1", 1)), e); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx index 4510671778d18..dbe197a32bbf4 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx @@ -131,12 +131,6 @@ This store does not support this method. - - The PrincipalContext can only be set on an unpersisted Principal. - - - Principals in this type of store do not support the property '{0}'. - Principals in this version of the store do not support the property '{0}'. @@ -164,30 +158,12 @@ The Principal object must be persisted before this method can be called. - - This type of identity information is not supported on principals in this type of store. - - - This type of identity information can not be cleared on principals in this type of store. - - - This type of store does not permit changing the SAM account name after the principal has been persisted. - - - The identityType parameter cannot be empty. - Persisted Principal objects cannot be used as query filters. - - A PrincipalContext must first be assigned to the PrincipalSearcher before the query can be performed. - A QueryFilter must first be assigned to the PrincipalSearcher before the query can be performed. - - A PrincipalContext must first be assigned to the PrincipalSearcher before the underlying searcher can be retrieved. - There is no underlying searcher for the type of store associated with the PrincipalContext. @@ -212,9 +188,6 @@ The enumerator is positioned before the first element of the collection or after the last element. - - More than one matching identity was found. - Multiple principals contain a matching Identity. @@ -242,9 +215,6 @@ The enumerator is positioned before the first element of the collection or after the last element. - - The Principal object already exists in the collection. - The subtype parameter must be either AuthenticablePrincipal or a subtype of AuthenticablePrincipal. @@ -254,12 +224,6 @@ A PrincipalContext must first be assigned to the unpersisted User object before this method can be called. - - Domain users are not supported on this platform. - - - Local machine users not supported on this platform. - The User object for the current user could not be found. You may not have access to it. @@ -305,21 +269,12 @@ The samAccountName IdentityType must be in the form "domainname\\userName", "machinename\\userName", or "userName". - - This store does not support setting IdentityClaims with a restricted range of times for which the IdentityClaim is valid. - The Group object can not be saved until the unpersisted Principal object in its Members property is either saved or removed from the collection. The Principal object must have a valid SID IdentityType in order to perform this operation. - - An exception occurred while updating the group membership on the store. - - - An exception occurred while saving the changes to the store. - Only domain Principal objects can be inserted into groups in this store. @@ -371,9 +326,6 @@ Computer accounts in this store can not have their passwords expired. - - This store does not permit changing the IdentityClaims on a principal once the principal has been persisted. - One of the Principal objects to be inserted into or removed from the group's membership does not contain a SID. @@ -407,33 +359,6 @@ An error occurred while enumerating the groups. The group could not be found. - - The '{0}' element can only appear once in the configuration file. - - - The '{0}' attribute for element '{1}' of the configuration file must be set to 'true' or 'false'. - - - The '{0}' attribute for element '{1}' of the configuration file is set to an unknown value. - - - The '{0}' attribute for element '{1}' of the configuration file must be set to a string. - - - Unknown element '{0}' was found in the configuration file. - - - The target parameter is not a PrincipalPermission. - - - The SecurityElement is not a permission. - - - The SecurityElement does not have a valid version. Version '1' was expected. - - - The SecurityElement does not contain a valid value for the 'Unrestricted' attribute. - The options value is invalid. The Machine store only supports Negotiate. @@ -452,9 +377,6 @@ Property is not valid for this store type. - - {0} is not supported by the {1} ContextType. - SamAccountName or Name must be assigned to a newly-created Principal object in this store prior to saving. diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj index ff38f3d644c70..c747c1d187c19 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj @@ -217,6 +217,9 @@ + + + diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs index 709ccb1601f73..2d8eebfc84ee7 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs @@ -1357,6 +1357,12 @@ protected static void ExtensionCacheToLdapConverter(Principal p, string property valueCollection = (ICollection)kvp.Value.Value; } + // We make a local copy of all elements to set, instead of adding them to the real property + // directly. This allows us to override all existing elements without using Clear() and then Add(), + // as that order sends a Clear operation and then a number of Append operations, which will fail. + // Instead, setting the new list all at once will send a Clear operation and then an Update operation. + var propertyValueList = new List(); + foreach (object oVal in valueCollection) { if (null != oVal) @@ -1373,8 +1379,11 @@ protected static void ExtensionCacheToLdapConverter(Principal p, string property if (p.unpersisted && null == oVal) continue; - de.Properties[kvp.Key].Add(oVal); + propertyValueList.Add(oVal); } + + de.Properties[kvp.Key].Value = propertyValueList.ToArray(); + GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Collection complete"); } else diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs index b132723c385ac..3a04bcc8a4b77 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs @@ -44,7 +44,7 @@ internal static class CapabilityMap public const string LDAP_CAP_ACTIVE_DIRECTORY_V61_OID = "1.2.840.113556.1.4.1935"; } - internal sealed class CredentialValidator + internal sealed class CredentialValidator : IDisposable { private enum AuthMethod { @@ -341,6 +341,14 @@ public bool Validate(string userName, string password, ContextOptions connection return (BindSam(_serverName, userName, password)); } } + + public void Dispose() + { + foreach (LdapConnection connection in _connCache.Values) + { + connection.Dispose(); + } + } } // ******************************************** public class PrincipalContext : IDisposable @@ -1014,6 +1022,8 @@ public void Dispose() if (_queryCtx != null) _queryCtx.Dispose(); + _credValidate.Dispose(); + _disposed = true; GC.SuppressFinalize(this); } diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs index 4796aa4451558..33de32cb836c0 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs @@ -7,6 +7,7 @@ using System.DirectoryServices.Tests; using System.Linq; using Xunit; +using System.Collections.Generic; namespace System.DirectoryServices.AccountManagement.Tests { @@ -16,6 +17,42 @@ public class AccountManagementTests internal static bool IsActiveDirectoryServer => IsLdapConfigurationExist && LdapConfiguration.Configuration.IsActiveDirectoryServer; internal static bool IsDomainJoinedClient => !Environment.MachineName.Equals(Environment.UserDomainName, StringComparison.OrdinalIgnoreCase); + [Fact] + public void TestConstructors() + { + using var context = new PrincipalContext(ContextType.Machine); + + using (var principal = new ComputerPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Empty(principal.ServicePrincipalNames); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new ComputerPrincipal(null)); + Assert.Throws(() => new ComputerPrincipal(null, "samAccountName", "password", true)); + Assert.Throws(() => new ComputerPrincipal(context, null, "password", true)); + Assert.Throws(() => new ComputerPrincipal(context, "samAccountName", null, true)); + + using (var principal = new UserPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new UserPrincipal(null)); + Assert.Throws(() => new UserPrincipal(null, "samAccountName", "password", true)); + Assert.Throws(() => new UserPrincipal(context, null, "password", true)); + Assert.Throws(() => new UserPrincipal(context, "samAccountName", null, true)); + + using (var principal = new GroupPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new GroupPrincipal(null)); + Assert.Throws(() => new GroupPrincipal(null, "samAccountName")); + Assert.Throws(() => new GroupPrincipal(context, null)); + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestCurrentUser() { @@ -23,7 +60,7 @@ public void TestCurrentUser() using (UserPrincipal p = FindUser(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) { Assert.NotNull(p); - Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.Name); + Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.SamAccountName); } } @@ -34,6 +71,7 @@ public void TestCurrentUserContext() using (UserPrincipal p = FindUser(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) using (UserPrincipal cu = UserPrincipal.Current) { + Assert.NotNull(cu); Assert.NotEqual(cu.Context.Name, p.Context.Name); } } @@ -45,7 +83,7 @@ public void TestCurrentUserUsingSearchFilter() using (UserPrincipal p = FindUserUsingFilter(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) { Assert.NotNull(p); - Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.Name); + Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.SamAccountName); } } @@ -278,6 +316,27 @@ public void TestNegativeCases() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestInvalidSaves() + { + UserData u1 = UserData.GenerateUserData("CoreFxUser9"); + + DeleteUser(u1.Name); + + try + { + using var context = DomainContext; + using var user = new UserPrincipal(context, u1.Name, u1.Password, true); + + Assert.Throws(() => user.Save(null)); + Assert.Throws(() => user.Save(new PrincipalContext(ContextType.Machine))); + } + finally + { + DeleteUser(u1.Name); + } + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestComputerContext() { @@ -306,6 +365,13 @@ public void TestComputerContext() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestComputerNegativeCases() + { + using var context = DomainContext; + + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestUpdateUserAndGroupData() { @@ -325,6 +391,7 @@ public void TestUpdateUserAndGroupData() using (GroupPrincipal gp = FindGroup(g1.Name, context)) { Assert.Equal(group.DisplayName, gp.DisplayName); } user.DisplayName = "Updated CoreFx Test Child User 4"; + user.Save(); group.DisplayName = "Updated CoreFX Test Group Container 4"; group.Save(); @@ -365,6 +432,91 @@ public void TestCredentials() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestCustomUserAttributes() + { + var userData = CustomUserData.GenerateUserData("CustomCoreFxUser1"); + + DeleteUser(userData.Name); + + try + { + using var context = DomainContext; + using (var principal = CreateCustomUser(context, userData)) + { + Assert.NotNull(principal); + ValidateRecentAddedUser(context, userData); + ValidateUserUsingPrincipal(context, principal); + + using var foundPrincipal = FindCustomUser(userData.Name, context); + Assert.NotNull(foundPrincipal); + + Assert.Equal(userData.PostalCode, foundPrincipal.PostalCode); + Assert.Equal(principal.PostalCode, foundPrincipal.PostalCode); + + Assert.Equal(userData.PostalAddress, foundPrincipal.PostalAddress); + Assert.Equal(principal.PostalAddress, foundPrincipal.PostalAddress); + } + } + finally + { + DeleteUser(userData.Name); + } + } + + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestMultiValueCustomAttributes() + { + var userData = CustomUserData.GenerateUserData("CustomCoreFxUser2"); + userData.PostalAddress.Add("Second address"); + + DeleteUser(userData.Name); + + // Check whether directory-data is equivalent to expected data + void CheckAddressWithDirectory(PrincipalContext context, List address) + { + using var foundPrincipal = FindCustomUser(userData.Name, context); + Assert.NotNull(foundPrincipal); + Assert.Equal(address.ToHashSet(), foundPrincipal.PostalAddress.ToHashSet()); + }; + + // Helper to update list + void UpdateAddressList(CustomUserPrincipal principal, Action> update) + { + var localCopy = principal.PostalAddress; + update(localCopy); + principal.PostalAddress = localCopy; + principal.Save(); + } + + try + { + // Initial setup + using var context = DomainContext; + using var principal = CreateCustomUser(context, userData); + Assert.NotNull(principal); + Assert.Equal(userData.PostalAddress, principal.PostalAddress); + + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Add address + UpdateAddressList(principal, addresses => addresses.Add("Third address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Remove address + UpdateAddressList(principal, addresses => addresses.Remove("Second address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Remove address so we have one remaining + UpdateAddressList(principal, addresses => addresses.Remove("Third address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + } + finally + { + DeleteUser(userData.Name); + } + } + private void ValidateRecentAddedUser(PrincipalContext context, UserData userData) { using (UserPrincipal p = FindUser(userData.Name, context)) @@ -440,6 +592,20 @@ private UserPrincipal CreateUser(PrincipalContext context, UserData userData) return user; } + private CustomUserPrincipal CreateCustomUser(PrincipalContext context, CustomUserData userData) + { + CustomUserPrincipal user = new CustomUserPrincipal(context, userData.Name, userData.Password, true); + + // assign some properties to the custom user principal + user.GivenName = userData.FirstName; + user.Surname = userData.LastName; + user.DisplayName = userData.DisplayName; + user.PostalCode = userData.PostalCode; + user.PostalAddress = userData.PostalAddress; + user.Save(); + return user; + } + private GroupPrincipal CreateGroup(PrincipalContext context, GroupData groupData) { GroupPrincipal group = new GroupPrincipal(context, groupData.Name); @@ -490,7 +656,12 @@ private GroupPrincipal FindGroup(string groupName, PrincipalContext context) private UserPrincipal FindUser(string userName, PrincipalContext context) { - return UserPrincipal.FindByIdentity(context, IdentityType.Name, userName); + return UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName); + } + + private CustomUserPrincipal FindCustomUser(string userName, PrincipalContext context) + { + return CustomUserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName); } private UserPrincipal FindUserUsingFilter(string userName, PrincipalContext context) @@ -528,6 +699,23 @@ internal static UserData GenerateUserData(string name) internal string DisplayName { get; set; } } + internal class CustomUserData : UserData + { + internal static new CustomUserData GenerateUserData(string name) => new CustomUserData + { + Name = name, + Password = Guid.NewGuid().ToString() + "#1aZ", + FirstName = "First " + name, + LastName = "Last " + name, + DisplayName = "Display " + name, + PostalAddress = new List { "Postal Address " + name }, + PostalCode = "Code " + name + }; + + internal string PostalCode { get; set; } + internal List PostalAddress { get; set; } + } + internal class GroupData { internal static GroupData GenerateGroupData(string name) @@ -545,11 +733,14 @@ internal static GroupData GenerateGroupData(string name) } [DirectoryObjectClass("user")] + [DirectoryRdnPrefix("CN")] public class CustomUserPrincipal : UserPrincipal { private CustomFilter _customFilter; public CustomUserPrincipal(PrincipalContext context) : base(context) { } + public CustomUserPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) + : base(context, samAccountName, password, enabled) { } public void SetUserNameFilter(string name) { @@ -568,6 +759,27 @@ public override AdvancedFilters AdvancedSearchFilter return _customFilter; } } + + // Custom properties + [DirectoryProperty("postalCode")] + public string PostalCode + { + get => ExtensionGet("postalCode").FirstOrDefault() as string; + set => ExtensionSet("postalCode", value); + } + + [DirectoryProperty("postalAddress")] + public List PostalAddress + { + get => ExtensionGet("postalAddress").OfType().ToList(); + set => ExtensionSet("postalAddress", value == null || value?.Count == 0 ? null : value.ToArray()); + } + + // Method overrides + public new static CustomUserPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue) + { + return FindByIdentityWithType(context, typeof(CustomUserPrincipal), identityType, identityValue) as CustomUserPrincipal; + } } public class CustomFilter : AdvancedFilters @@ -576,7 +788,7 @@ public CustomFilter(Principal p) : base(p) { } public void SetFilter(string userName) { - this.AdvancedFilterSet("cn", userName, typeof(string), MatchType.Equals); + this.AdvancedFilterSet("samAccountName", userName, typeof(string), MatchType.Equals); } } } diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs deleted file mode 100644 index ce6b8cf70565b..0000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs +++ /dev/null @@ -1,83 +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 Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class ComputerPrincipalTest : PrincipalTest - { - [Fact] - public void Ctor_Context() - { - var context = new PrincipalContext(ContextType.Machine); - var principal = new ComputerPrincipal(context); - Assert.Same(context, principal.Context); - Assert.Empty(principal.ServicePrincipalNames); - } - - [Fact] - public void Ctor_NullContext_ThrowsArgumentException() - { - AssertExtensions.Throws(null, () => new ComputerPrincipal(null)); - AssertExtensions.Throws(null, () => new ComputerPrincipal(null, "samAccountName", "password", enabled: true)); - } - - [Fact] - public void Ctor_NullSamAccountName_ThrowsArgumentException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws(null, () => new ComputerPrincipal(context, null, "password", enabled: true)); - } - - [Fact] - public void Ctor_EmptySamAccountName_ThrowsArgumentNullException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws("value", null, () => new ComputerPrincipal(context, string.Empty, "password", enabled: true)); - } - - [Fact] - public void Ctor_NullPassword_ThrowsArgumentException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws(null, () => new ComputerPrincipal(context, "samAccountName", null, enabled: true)); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore), nameof(PlatformDetection.IsNotWindowsIoTCore))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34442", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - public void Ctor_MachineContext_NoException() - { - var context = new PrincipalContext(ContextType.Machine); - var principal = new ComputerPrincipal(context, "samAccountName", "password", enabled: true); - Assert.Equal(ContextType.Machine, principal.ContextType); - } - - [Fact] - public void ComputerPrincipalConstructorTest() - { - if (DomainContext == null) - { - return; - } - - ComputerPrincipal computer = new ComputerPrincipal(DomainContext); - computer.Dispose(); - } - - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new ComputerPrincipal(context) { Name = name }; - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs deleted file mode 100644 index 7f378a13acf43..0000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.DirectoryServices.AccountManagement.Tests -{ - [DirectoryRdnPrefix("CN")] - [DirectoryObjectClass("User")] - public class ExtendedUserPrincipal : UserPrincipal, IExtendedPrincipalTest - { - public ExtendedUserPrincipal(PrincipalContext context) : base(context) { } - - public static new ExtendedUserPrincipal FindByIdentity(PrincipalContext context,string identityValue) - { - return (ExtendedUserPrincipal)FindByIdentityWithType(context, typeof(ExtendedUserPrincipal), identityValue); - } - - [DirectoryProperty("jpegPhoto")] - public byte[] ByteArrayExtension - { - get => (byte[])ExtensionGet("jpegPhoto")[0]; - set => ExtensionSet("jpegPhoto", value); - } - - public object ObjectExtension - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public object[] ObjectArrayExtension - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs deleted file mode 100644 index 8817afbddd186..0000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs +++ /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. - -using Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class GroupPrincipalTest : PrincipalTest - { - [Fact] - public void GroupPrincipalConstructorTest() - { - if (DomainContext == null) - { - return; - } - - GroupPrincipal group = new GroupPrincipal(DomainContext); - group.Dispose(); - } - - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new GroupPrincipal(context, name); - } - - [Fact] - public void IsMemberOfTest() - { - if (DomainContext == null) - { - return; - } - - using (GroupPrincipal group = GroupPrincipal.FindByIdentity(DomainContext, "TestLargeGroup")) - { - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1499-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1500-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1501-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user3000-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user3001-LargeGroup").IsMemberOf(group)); - Assert.False(UserPrincipal.FindByIdentity(DomainContext, "userNotInLargeGroup").IsMemberOf(group)); - } - } - - private void CreateManyUsersInGroup(GroupPrincipal group) - { - for (int i = 1; i < 3002; i++) - { - string name = $"user{i:0000}-LargeGroup"; - UserPrincipal user = new UserPrincipal(DomainContext, name, "Adrumble@6", false); - user.Save(); - group.Members.Add(user); - } - group.Save(); - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs deleted file mode 100644 index a0078001f74f4..0000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs +++ /dev/null @@ -1,143 +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.Collections.Generic; -using System.Security.Principal; -using Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public abstract class PrincipalTest : IDisposable - { - public PrincipalContext DomainContext { get; private set; } - - public PrincipalTest() => RefreshContext(); - - private void RefreshContext() - { - string username = "Administrator"; - string password = Environment.GetEnvironmentVariable("TESTPASSWORD"); - string OU = "Tests"; - string baseDomain = WindowsIdentity.GetCurrent().Name.Split(new char[] { '\\' })[1] + "-TEST"; - string domain = $"{baseDomain}.nttest.microsoft.com"; - string container = $"ou={OU},dc={baseDomain},dc=nttest,dc=microsoft,dc=com"; - DomainContext?.Dispose(); - try - { - DomainContext = new PrincipalContext(ContextType.Domain, domain, container, username, password); - } - catch - { - } - } - - public void Dispose() => DomainContext?.Dispose(); - - [Fact] - public void AddExistingPrincipal() - { - if (DomainContext == null) - { - return; - } - - // use new GUID for the user name so we be sure this user does not exist yet - string name = Guid.NewGuid().ToString(); - using (Principal principal = CreatePrincipal(DomainContext, name)) - { - principal.Save(); - } - - Assert.NotNull(Principal.FindByIdentity(DomainContext, name)); - - // this previously caused the user to be deleted. it is still expected to throw an exception, but not delete the user - bool exceptionThrown = false; - try - { - using (Principal principal = CreatePrincipal(DomainContext, name)) - { - principal.Save(); - } - } - catch (PrincipalExistsException) - { - exceptionThrown = true; - } - - // validate that we correctly throw an exception when trying to add an existing principal - Assert.True(exceptionThrown); - - // validate that we did not delete incorrectly delete the first principal - using (Principal principal2 = Principal.FindByIdentity(DomainContext, name)) - { - Assert.NotNull(principal2); - - // explicitly delete the user and check it was really deleted - principal2.Delete(); - } - - // ensure we cleaned up the test principal - Assert.Null(Principal.FindByIdentity(DomainContext, name)); - } - - [Fact] - public void TestExtendedPrincipal() - { - if (DomainContext == null) - { - return; - } - - string name = Guid.NewGuid().ToString(); - byte[] writtenArray = new byte[] { 10, 20, 30 }; - using (Principal principal = CreateExtendedPrincipal(DomainContext, name)) - { - IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal; - extendedPrincipal.ByteArrayExtension = writtenArray; - principal.Save(); - } - - RefreshContext(); - using (Principal principal = FindExtendedPrincipal(DomainContext, name)) - { - IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal; - byte[] readArray = extendedPrincipal.ByteArrayExtension; - principal.Delete(); - } - } - - [Theory] - [MemberData(nameof(TestDebuggerAttributes_Inputs))] - public void Save_ThrowsInvalidOperationException(PrincipalContext context) - { - if (DomainContext == null) - { - return; - } - - using (Principal principal = CreateExtendedPrincipal(DomainContext, Guid.NewGuid().ToString())) - { - Assert.Throws(() => principal.Save(context)); - } - } - - public static IEnumerable TestDebuggerAttributes_Inputs() - { - yield return new object[] { null }; - yield return new object[] { new PrincipalContext(ContextType.Machine) }; - } - - public abstract Principal CreatePrincipal(PrincipalContext context, string name); - - public abstract Principal CreateExtendedPrincipal(PrincipalContext context, string name); - - public abstract Principal FindExtendedPrincipal(PrincipalContext context, string name); - } - - public interface IExtendedPrincipalTest - { - object ObjectExtension { get; set; } - byte[] ByteArrayExtension { get; set; } - object[] ObjectArrayExtension { get; set; } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj b/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj index 6ee1a6b7217ba..0bb24c8eadd87 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj @@ -3,15 +3,9 @@ $(NetCoreAppCurrent)-windows;net48 - - - - - - + diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs deleted file mode 100644 index 53b99ab5c939c..0000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs +++ /dev/null @@ -1,32 +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.Security.Principal; -using Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class UserPrincipalTest : PrincipalTest - { - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new UserPrincipal(context) { Name = name }; - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - return new ExtendedUserPrincipal(context) { Name = name }; - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - return ExtendedUserPrincipal.FindByIdentity(context, name); - } - - public void UserPrincipalConstructorTest() - { - UserPrincipal user = new UserPrincipal(DomainContext); - user.Dispose(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx index b469e621c1be1..b63f103619fbd 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The URI that is supplied must be either "http" or "https". - A negative value is not permitted for the time limit. @@ -129,18 +126,12 @@ The DSML document could not be parsed. - - The server failed to return a session identifier. - The server failed to return a DirectoryResponse. An ErrorResponse DSML element was returned. - - The server returned an invalid DSML control. - A null reference cannot be added to DirectoryAttribute or DirectoryAttributeModification objects. @@ -162,54 +153,9 @@ An unspecified operation error occurred. - - The LDAP filter string is invalid. - The property is read-only. - - The operation response is missing the result code. - - - The distinguished name is missing in the SearchResultEntry of the search response. - - - The search result is missing the attribute name. - - - The server returned an unknown result code "{0}". - - - The error response is missing the type attribute. - - - The error response contains an invalid type attribute "{0}". - - - This property is not supported on a DsmlErrorResponse. - - - The value is invalid base-64-encoded data. - - - The DsmlSoapHttpConnection does not support "{0}" authentication type. - - - An active session already exists for this connection. - - - The document is read-only. - - - The response from the server is not a well-formed DSML document. - - - No active session exists for this connection. - - - The server returned an unknown response element. - ClientCertificates can contain only zero or one certificate. @@ -312,9 +258,6 @@ The call completed successfully. - - The server failed to return a session identifier. - An operation error occurred. @@ -447,9 +390,6 @@ The value must be a string, byte[], or Uri type. - - Transport layer security is not supported on Windows 2000. - The specified parameter should be a "{0}" type. @@ -459,9 +399,6 @@ The collection cannot contain a null DirectoryControl object. - - The filter type "{0}" is invalid. - The value "{0}" is not the return value from BeginSendRequest. @@ -474,12 +411,6 @@ The array should not contain null reference. - - A non-CLSCompliant exception is thrown. - - - Fast concurrent bind is only supported on Windows 2003 and later operating systems. - The value exceeds the maximum allowed. diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index 915b7d71b0a9d..0a92754626c1f 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -113,6 +113,9 @@ + + + diff --git a/src/libraries/System.DirectoryServices/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices/src/Resources/Strings.resx index 64f8ba2d1f046..437bbe46dcf95 100644 --- a/src/libraries/System.DirectoryServices/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices/src/Resources/Strings.resx @@ -221,9 +221,6 @@ Only one type of operation can be performed in a sequence. - - The '{0}' section can only appear once in a configuration file. - An unknown error occurred. @@ -314,9 +311,6 @@ The specified string parameter is empty. - - The System.DirectoryServices.ActiveDirectory namespace is only supported on computers running Windows 2000 and later operating systems. - The name specified in the directory context must be an ADAM instance. @@ -467,9 +461,6 @@ The local computer is not joined to a domain or the domain cannot be contacted. - - Failed to get the version of the operating system, error is "{0}". - Unable to obtain DNS hostname of Active Directory domain controller with ntdsa object name "{0}". diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs index f9d987de24d1c..1514ee19e8c33 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs @@ -6,6 +6,10 @@ namespace System.Drawing { + public partial struct CharacterRange : System.IEquatable + { + public bool Equals(System.Drawing.CharacterRange other) { throw null; } + } public sealed partial class Graphics { public void DrawRectangle(System.Drawing.Pen pen, System.Drawing.RectangleF rect) { } diff --git a/src/libraries/System.Drawing.Common/src/Resources/Strings.resx b/src/libraries/System.Drawing.Common/src/Resources/Strings.resx index 2d3d8134aabce..eb89ee9ebb7a5 100644 --- a/src/libraries/System.Drawing.Common/src/Resources/Strings.resx +++ b/src/libraries/System.Drawing.Common/src/Resources/Strings.resx @@ -128,9 +128,6 @@ The color {0} is not a system color. - - .NET Component - Function was ended. @@ -224,18 +221,6 @@ '{0}' data length expected {1}, read {2} - - Toolbox item cannot be modified. - - - Property {0} requires an argument of type {1}. - - - Data type {0} is not serializable. Items added to a property dictionary must be serializable. - - - Argument should be a non-empty string. - Internal state of the {0} class is invalid. @@ -263,15 +248,12 @@ Value of '{1}' is not valid for '{0}'. - + Value of '{0}' is not valid for font size unit. Value of '{1}' is not valid for '{0}'. '{0}' should be greater than {2} and less than or equal to {3}. - - Class name is not valid. - Color '{0}' is not valid. @@ -290,9 +272,6 @@ Value of '{1}' is not valid for '{0}'. '{0}' must be greater than or equal to {2}. - - Permission level is not valid. - Permission state is not valid. @@ -350,21 +329,12 @@ Occurs before each page is printed. Useful for changing PageSettings for a particular page. - - System.Drawing is not supported on this platform. - System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information. Defines an object that sends output to a printer. - - XML is not valid. - - - Permission level must be between PrintingPermissionLevel.NoPrinting and PrintingPermissionLevel.AllPrinting. - IDictionary parameter contains at least one entry that is not valid. Ensure all values are consistent with the object's properties. @@ -374,9 +344,6 @@ Resource '{1}' cannot be found in class '{0}'. - - Target does not have permission to print. - Text "{0}" cannot be parsed. The expected text format is "{1}". @@ -407,12 +374,6 @@ Invalid Blend object. The positions array must have 1.0 as its last element. - - Unable to load DLL '{0}': The specified module could not be found. - - - Unable to find an entry point named '{0}' in DLL '{1}'. - {0} only available on WMF files. diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs index 157533b84283c..a0dccdc4b2876 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs @@ -7,51 +7,43 @@ namespace System.Drawing { [StructLayout(LayoutKind.Sequential)] - public struct CharacterRange + public struct CharacterRange : IEquatable { private int _first; private int _length; - /// - /// Initializes a new instance of the class with the specified coordinates. - /// + /// Initializes a new instance of the class with the specified coordinates. public CharacterRange(int First, int Length) { _first = First; _length = Length; } - /// - /// Gets the First character position of this . - /// + /// Gets the First character position of this . public int First { get => _first; set => _first = value; } - /// - /// Gets the Length of this . - /// + /// Gets the Length of this . public int Length { get => _length; set => _length = value; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (!(obj is CharacterRange cr)) - { - return false; - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is CharacterRange other && Equals(other); - return First == cr.First && Length == cr.Length; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CharacterRange other) => First == other.First && Length == other.Length; public static bool operator ==(CharacterRange cr1, CharacterRange cr2) => cr1.Equals(cr2); - public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !(cr1 == cr2); + public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !cr1.Equals(cr2); public override int GetHashCode() => HashCode.Combine(First, Length); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs index a435640a795c1..8fef9cbc472b2 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs @@ -1399,7 +1399,6 @@ internal struct StartupInput { public int GdiplusVersion; // Must be 1 - // public DebugEventProc DebugEventCallback; // Ignored on free builds public IntPtr DebugEventCallback; public bool SuppressBackgroundThread; // FALSE unless you're prepared to call @@ -1416,7 +1415,6 @@ public static StartupInput GetDefault() // In Windows 7 GDI+1.1 story is different as there are different binaries per GDI+ version. bool isWindows7 = os.Platform == PlatformID.Win32NT && os.Version.Major == 6 && os.Version.Minor == 1; result.GdiplusVersion = isWindows7 ? 1 : 2; - // result.DebugEventCallback = null; result.SuppressBackgroundThread = false; result.SuppressExternalCodecs = false; return result; diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/LocalAppContextSwitches.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/LocalAppContextSwitches.Unix.cs index 44fe88b2f6ea9..59d9b10bb98f7 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/LocalAppContextSwitches.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/LocalAppContextSwitches.Unix.cs @@ -7,14 +7,10 @@ namespace System { internal static partial class LocalAppContextSwitches { - private static int s_enableUnixSupport; public static bool EnableUnixSupport { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return GetCachedSwitchValue(@"System.Drawing.EnableUnixSupport", ref s_enableUnixSupport); - } + get => false; } } -} +} \ No newline at end of file diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs index 665a642a3e4f3..bb7b163d1ce95 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs @@ -1,9 +1,12 @@ // 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 System.Diagnostics.CodeAnalysis; + namespace System.Drawing.Printing { - internal readonly partial struct TriState + internal readonly partial struct TriState : IEquatable { private readonly byte _value; // 0 is "default", not false @@ -11,73 +14,46 @@ internal readonly partial struct TriState public static readonly TriState False = new TriState(1); public static readonly TriState True = new TriState(2); - private TriState(byte value) - { - _value = value; - } + private TriState(byte value) => _value = value; - public bool IsDefault - { - get { return this == Default; } - } + public bool IsDefault => this == Default; - public bool IsFalse - { - get { return this == False; } - } + public bool IsFalse => this == False; - public bool IsNotDefault - { - get { return this != Default; } - } + public bool IsNotDefault => this != Default; - public bool IsTrue - { - get { return this == True; } - } + public bool IsTrue => this == True; - public static bool operator ==(TriState left, TriState right) - { - return left._value == right._value; - } + public static bool operator ==(TriState left, TriState right) => left.Equals(right); - public static bool operator !=(TriState left, TriState right) - { - return !(left == right); - } + public static bool operator !=(TriState left, TriState right) => !left.Equals(right); - public override bool Equals(object? o) + public override bool Equals([NotNullWhen(true)] object? o) { - TriState state = (TriState)o!; - return _value == state._value; + Debug.Assert(o is TriState); + return Equals((TriState)o); } - public override int GetHashCode() - { - return _value; - } + public bool Equals(TriState other) => _value == other._value; - public static implicit operator TriState(bool value) - { - return (value) ? True : False; - } + public override int GetHashCode() => _value; + + public static implicit operator TriState(bool value) => value ? True : False; public static explicit operator bool(TriState value) { if (value.IsDefault) + { throw new InvalidCastException(SR.TriStateCompareError); - else - return (value == TriState.True); - } + } - /// - /// Provides some interesting information about the TriState in String form. - /// - public override string ToString() - { - if (this == Default) return "Default"; - else if (this == False) return "False"; - else return "True"; + return (value == TriState.True); } + + /// Provides some interesting information about the TriState in String form. + public override string ToString() => + this == Default ? "Default" : + this == False ? "False" : + "True"; } } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs index 445d7c72c6dd4..098830cbf4a61 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs @@ -83,7 +83,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } else { throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, - "text", text, "x, y, width, height")); } diff --git a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs index 7147cb809be6b..989ee85c09312 100644 --- a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs +++ b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs @@ -84,6 +84,7 @@ public void Equals_Invoke_ReturnsExpected(CharacterRange range, object obj, bool Assert.Equal(expected, range.Equals(obj)); if (obj is CharacterRange otherRange) { + Assert.Equal(expected, range.Equals(otherRange)); Assert.Equal(expected, range == otherRange); Assert.Equal(!expected, range != otherRange); Assert.Equal(expected, range.GetHashCode().Equals(otherRange.GetHashCode())); diff --git a/src/libraries/System.Drawing.Common/tests/Drawing2D/MatrixTests.cs b/src/libraries/System.Drawing.Common/tests/Drawing2D/MatrixTests.cs index 34480479f6956..e014299b88bef 100644 --- a/src/libraries/System.Drawing.Common/tests/Drawing2D/MatrixTests.cs +++ b/src/libraries/System.Drawing.Common/tests/Drawing2D/MatrixTests.cs @@ -910,7 +910,7 @@ private static void AssertEqualFloatArray(float[] expected, float[] actual) { try { - Assert.Equal(expected[i], actual[i], 3); + Assert.Equal((double)expected[i], (double)actual[i], 3); } catch { diff --git a/src/libraries/System.Drawing.Common/tests/FontFamilyTests.cs b/src/libraries/System.Drawing.Common/tests/FontFamilyTests.cs index a87895ba21303..cf6287420d3b1 100644 --- a/src/libraries/System.Drawing.Common/tests/FontFamilyTests.cs +++ b/src/libraries/System.Drawing.Common/tests/FontFamilyTests.cs @@ -69,7 +69,7 @@ public void Ctor_NoSuchFontNameInCollection_ThrowsArgumentException() { using (var fontCollection = new PrivateFontCollection()) { - Assert.Throws(null, () => new FontFamily("Times New Roman", fontCollection)); + AssertExtensions.Throws(null, () => new FontFamily("Times New Roman", fontCollection)); } } diff --git a/src/libraries/System.Drawing.Common/tests/FontTests.cs b/src/libraries/System.Drawing.Common/tests/FontTests.cs index 899bd4e3c1040..4cf0c6e690b50 100644 --- a/src/libraries/System.Drawing.Common/tests/FontTests.cs +++ b/src/libraries/System.Drawing.Common/tests/FontTests.cs @@ -557,7 +557,7 @@ public void GetHeight_Graphics_ReturnsExpected() using (var image = new Bitmap(10, 10)) using (Graphics graphics = Graphics.FromImage(image)) { - Assert.Equal(font.GetHeight(graphics.DpiY), font.GetHeight(graphics), 5); + Assert.Equal((double)font.GetHeight(graphics.DpiY), font.GetHeight(graphics), 5); } } @@ -574,7 +574,7 @@ public void GetHeight_Dpi_ReturnsExpected(float dpi, float expected) using (FontFamily family = FontFamily.GenericSansSerif) using (var font = new Font(family, 10)) { - Assert.Equal(expected, font.GetHeight(dpi), 5); + Assert.Equal((double)expected, font.GetHeight(dpi), 5); } } diff --git a/src/libraries/System.Drawing.Common/tests/ImageTests.cs b/src/libraries/System.Drawing.Common/tests/ImageTests.cs index 5357e9a48b370..00d37e7520df8 100644 --- a/src/libraries/System.Drawing.Common/tests/ImageTests.cs +++ b/src/libraries/System.Drawing.Common/tests/ImageTests.cs @@ -121,7 +121,7 @@ public void GetPropertyItem_InvokeExistsBitmapBmp_Success() public void GetPropertyItem_NoSuchPropertyItemEmptyMemoryBitmap_ThrowsArgumentException(int propid) { using var bitmap = new Bitmap(1, 1); - Assert.Throws(null, () => bitmap.GetPropertyItem(propid)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(propid)); } [Theory] @@ -131,7 +131,7 @@ public void GetPropertyItem_NoSuchPropertyItemEmptyMemoryBitmap_ThrowsArgumentEx public void GetPropertyItem_NoSuchPropertyItemEmptyImageBitmapBmp_ThrowsArgumentException(int propid) { using var bitmap = new Bitmap(Helpers.GetTestBitmapPath("almogaver1bit.bmp")); - Assert.Throws(null, () => bitmap.GetPropertyItem(propid)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(propid)); } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] @@ -149,17 +149,17 @@ public void RemovePropertyItem_InvokeMemoryBitmap_Success() bitmap.RemovePropertyItem(PropertyTagExifUserComment); Assert.Equal(new int[] { PropertyTagChrominanceTable, PropertyTagLuminanceTable }, bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagExifUserComment)); - Assert.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagExifUserComment)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagExifUserComment)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagExifUserComment)); bitmap.RemovePropertyItem(PropertyTagLuminanceTable); Assert.Equal(new int[] { PropertyTagChrominanceTable }, bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagLuminanceTable)); - Assert.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagLuminanceTable)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagLuminanceTable)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagLuminanceTable)); bitmap.RemovePropertyItem(PropertyTagChrominanceTable); Assert.Empty(bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagChrominanceTable)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagChrominanceTable)); Assert.Throws(() => bitmap.RemovePropertyItem(PropertyTagChrominanceTable)); } @@ -170,17 +170,17 @@ public void RemovePropertyItem_InvokeBitmapJpg_Success() using var bitmap = new Bitmap(Helpers.GetTestBitmapPath("nature24bits.jpg")); bitmap.RemovePropertyItem(PropertyTagExifUserComment); Assert.Equal(new int[] { PropertyTagChrominanceTable, PropertyTagLuminanceTable }, bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagExifUserComment)); - Assert.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagExifUserComment)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagExifUserComment)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagExifUserComment)); bitmap.RemovePropertyItem(PropertyTagLuminanceTable); Assert.Equal(new int[] { PropertyTagChrominanceTable }, bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagLuminanceTable)); - Assert.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagLuminanceTable)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagLuminanceTable)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(PropertyTagLuminanceTable)); bitmap.RemovePropertyItem(PropertyTagChrominanceTable); Assert.Empty(bitmap.PropertyIdList); - Assert.Throws(null, () => bitmap.GetPropertyItem(PropertyTagChrominanceTable)); + AssertExtensions.Throws(null, () => bitmap.GetPropertyItem(PropertyTagChrominanceTable)); Assert.Throws(() => bitmap.RemovePropertyItem(PropertyTagChrominanceTable)); } @@ -222,7 +222,7 @@ public void RemovePropertyItem_NoSuchPropertyNotEmptyMemoryBitmap_ThrowsArgument bitmap.SetPropertyItem(item2); bitmap.SetPropertyItem(item3); - Assert.Throws(null, () => bitmap.RemovePropertyItem(propid)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(propid)); } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] @@ -233,7 +233,7 @@ public void RemovePropertyItem_NoSuchPropertyNotEmptyMemoryBitmap_ThrowsArgument public void RemovePropertyItem_NoSuchPropertyNotEmptyBitmapJpg_ThrowsArgumentException(int propid) { using var bitmap = new Bitmap(Helpers.GetTestBitmapPath("nature24bits.jpg")); - Assert.Throws(null, () => bitmap.RemovePropertyItem(propid)); + AssertExtensions.Throws(null, () => bitmap.RemovePropertyItem(propid)); } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] diff --git a/src/libraries/System.Drawing.Common/tests/Printing/PrinterSettingsTests.cs b/src/libraries/System.Drawing.Common/tests/Printing/PrinterSettingsTests.cs index 137ea1d48d31b..0a2fae6c0fd9d 100644 --- a/src/libraries/System.Drawing.Common/tests/Printing/PrinterSettingsTests.cs +++ b/src/libraries/System.Drawing.Common/tests/Printing/PrinterSettingsTests.cs @@ -479,10 +479,10 @@ public void CreateMeasurementGraphics_Default_ReturnsExpected() using (Graphics graphic = printerSettings.CreateMeasurementGraphics()) { Assert.NotNull(graphic); - Assert.Equal(printerSettings.DefaultPageSettings.Bounds.X, graphic.VisibleClipBounds.X, 0); - Assert.Equal(printerSettings.DefaultPageSettings.Bounds.Y, graphic.VisibleClipBounds.Y, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.Bounds.X, graphic.VisibleClipBounds.X, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.Bounds.Y, graphic.VisibleClipBounds.Y, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); } } @@ -494,8 +494,8 @@ public void CreateMeasurementGraphics_Bool_ReturnsExpected() using (Graphics graphic = printerSettings.CreateMeasurementGraphics(true)) { Assert.NotNull(graphic); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); } } @@ -508,10 +508,10 @@ public void CreateMeasurementGraphics_PageSettings_ReturnsExpected() using (Graphics graphic = printerSettings.CreateMeasurementGraphics(pageSettings)) { Assert.NotNull(graphic); - Assert.Equal(printerSettings.DefaultPageSettings.Bounds.X, graphic.VisibleClipBounds.X, 0); - Assert.Equal(printerSettings.DefaultPageSettings.Bounds.Y, graphic.VisibleClipBounds.Y, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.Bounds.X, graphic.VisibleClipBounds.X, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.Bounds.Y, graphic.VisibleClipBounds.Y, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); } } @@ -524,8 +524,8 @@ public void CreateMeasurementGraphics_PageSettingsBool_ReturnsExpected() using (Graphics graphic = printerSettings.CreateMeasurementGraphics(pageSettings, true)) { Assert.NotNull(graphic); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); - Assert.Equal(printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Height, graphic.VisibleClipBounds.Height, 0); + Assert.Equal((double)printerSettings.DefaultPageSettings.PrintableArea.Width, graphic.VisibleClipBounds.Width, 0); } } diff --git a/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj b/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj index ac1fa3b57cfdc..58fe9b144c8fd 100644 --- a/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj +++ b/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj @@ -2,7 +2,7 @@ true true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;net48 + $(NetCoreAppCurrent)-windows;net48 true diff --git a/src/libraries/System.Drawing.Common/tests/SystemPensTest.cs b/src/libraries/System.Drawing.Common/tests/SystemPensTest.cs index 046231cdf50f7..225800bd167d4 100644 --- a/src/libraries/System.Drawing.Common/tests/SystemPensTest.cs +++ b/src/libraries/System.Drawing.Common/tests/SystemPensTest.cs @@ -77,7 +77,7 @@ public void SystemPens_Get_ReturnsExpected(Func getPen, Color expectedColor AssertExtensions.Throws(null, () => pen.StartCap = LineCap.RoundAnchor); using (var matrix = new Matrix()) { - Assert.Throws(null, () => pen.Transform = matrix); + AssertExtensions.Throws(null, () => pen.Transform = matrix); } AssertExtensions.Throws(null, () => pen.Width = 10); } diff --git a/src/libraries/System.Drawing.Common/tests/mono/System.Drawing/GraphicsTests.cs b/src/libraries/System.Drawing.Common/tests/mono/System.Drawing/GraphicsTests.cs index 756e860a2a644..a274b13d74120 100644 --- a/src/libraries/System.Drawing.Common/tests/mono/System.Drawing/GraphicsTests.cs +++ b/src/libraries/System.Drawing.Common/tests/mono/System.Drawing/GraphicsTests.cs @@ -1794,11 +1794,11 @@ public void MeasureString_StringFormat_Alignment() string_format.Alignment = StringAlignment.Far; SizeF far = g.MeasureString(text, font, int.MaxValue, string_format); - Assert.Equal(near.Width, center.Width, 1); - Assert.Equal(near.Height, center.Height, 1); + Assert.Equal((double)near.Width, center.Width, 1); + Assert.Equal((double)near.Height, center.Height, 1); - Assert.Equal(center.Width, far.Width, 1); - Assert.Equal(center.Height, far.Height, 1); + Assert.Equal((double)center.Width, far.Width, 1); + Assert.Equal((double)center.Height, far.Height, 1); } } @@ -1821,11 +1821,11 @@ public void MeasureString_StringFormat_Alignment_DirectionVertical() string_format.Alignment = StringAlignment.Far; SizeF far = g.MeasureString(text, font, int.MaxValue, string_format); - Assert.Equal(near.Width, center.Width, 0); - Assert.Equal(near.Height, center.Height, 0); + Assert.Equal((double)near.Width, center.Width, 0); + Assert.Equal((double)near.Height, center.Height, 0); - Assert.Equal(center.Width, far.Width, 0); - Assert.Equal(center.Height, far.Height, 0); + Assert.Equal((double)center.Width, far.Width, 0); + Assert.Equal((double)center.Height, far.Height, 0); } } @@ -1846,11 +1846,11 @@ public void MeasureString_StringFormat_LineAlignment() string_format.LineAlignment = StringAlignment.Far; SizeF far = g.MeasureString(text, font, int.MaxValue, string_format); - Assert.Equal(near.Width, center.Width, 1); - Assert.Equal(near.Height, center.Height, 1); + Assert.Equal((double)near.Width, center.Width, 1); + Assert.Equal((double)near.Height, center.Height, 1); - Assert.Equal(center.Width, far.Width, 1); - Assert.Equal(center.Height, far.Height, 1); + Assert.Equal((double)center.Width, far.Width, 1); + Assert.Equal((double)center.Height, far.Height, 1); } } @@ -1873,11 +1873,11 @@ public void MeasureString_StringFormat_LineAlignment_DirectionVertical() string_format.LineAlignment = StringAlignment.Far; SizeF far = g.MeasureString(text, font, int.MaxValue, string_format); - Assert.Equal(near.Width, center.Width, 1); - Assert.Equal(near.Height, center.Height, 1); + Assert.Equal((double)near.Width, center.Width, 1); + Assert.Equal((double)near.Height, center.Height, 1); - Assert.Equal(center.Width, far.Width, 1); - Assert.Equal(center.Height, far.Height, 1); + Assert.Equal((double)center.Width, far.Width, 1); + Assert.Equal((double)center.Height, far.Height, 1); } } @@ -1895,7 +1895,7 @@ public void MeasureString_CharactersFitted() // in pixels Assert.True(size2.Width < size.Width); - Assert.Equal(size2.Height, size.Height); + Assert.Equal((double)size2.Height, size.Height); Assert.Equal(1, lines); // documentation seems to suggest chars is total length @@ -1920,8 +1920,8 @@ public void MeasureString_Whitespace() { s += " "; size = g.MeasureString(s, font); - Assert.Equal(expected.Height, size.Height, 1); - Assert.Equal(expected.Width, size.Width, 1); + Assert.Equal((double)expected.Height, size.Height, 1); + Assert.Equal((double)expected.Width, size.Width, 1); } s = "a"; @@ -1932,8 +1932,8 @@ public void MeasureString_Whitespace() for (int i = 1; i < 10; i++) { size = g.MeasureString(s, font); - Assert.Equal(expected.Height, size.Height, 1); - Assert.Equal(expected.Width + i * space_width, size.Width, 1); + Assert.Equal((double)expected.Height, size.Height, 1); + Assert.Equal((double)expected.Width + i * space_width, size.Width, 1); s = " " + s; } @@ -1943,8 +1943,8 @@ public void MeasureString_Whitespace() { s = s + " "; size = g.MeasureString(s, font); - Assert.Equal(expected.Height, size.Height, 1); - Assert.Equal(expected.Width, size.Width, 1); + Assert.Equal((double)expected.Height, size.Height, 1); + Assert.Equal((double)expected.Width, size.Width, 1); } } } @@ -2076,7 +2076,7 @@ public void MeasureCharacterRanges_Prefix() string_format.HotkeyPrefix = HotkeyPrefix.Hide; regions = g.MeasureCharacterRanges(text, font, layout_rect, string_format); RectangleF bounds_hide = regions[0].GetBounds(g); - Assert.Equal(bounds_hide.Width, bounds_show.Width); + Assert.Equal((double)bounds_hide.Width, bounds_show.Width); } } @@ -2125,8 +2125,8 @@ public void Measure() RectangleF sb = small[i].GetBounds(gfx); Assert.Equal(sb.X, zb.X); Assert.Equal(sb.Y, zb.Y); - Assert.Equal(sb.Width, zb.Width); - Assert.Equal(sb.Height, zb.Height); + Assert.Equal((double)sb.Width, zb.Width); + Assert.Equal((double)sb.Height, zb.Height); } Region[] max = Measure_Helper(gfx, new RectangleF(0, 0, float.MaxValue, float.MaxValue)); @@ -2137,8 +2137,8 @@ public void Measure() RectangleF mb = max[i].GetBounds(gfx); Assert.Equal(mb.X, zb.X); Assert.Equal(mb.Y, zb.Y); - Assert.Equal(mb.Width, zb.Width); - Assert.Equal(mb.Height, zb.Height); + Assert.Equal((double)mb.Width, zb.Width); + Assert.Equal((double)mb.Height, zb.Height); } } } @@ -2316,15 +2316,15 @@ public void VisibleClipBound() RectangleF clip = g.VisibleClipBounds; Assert.Equal(0, clip.X); Assert.Equal(0, clip.Y); - Assert.Equal(32, clip.Width, 4); - Assert.Equal(32, clip.Height, 4); + Assert.Equal(32.0, clip.Width, 4); + Assert.Equal(32.0, clip.Height, 4); g.RotateTransform(90); RectangleF rotclip = g.VisibleClipBounds; Assert.Equal(0, rotclip.X); - Assert.Equal(-32, rotclip.Y, 4); - Assert.Equal(32, rotclip.Width, 4); - Assert.Equal(32, rotclip.Height, 4); + Assert.Equal(-32.0, rotclip.Y, 4); + Assert.Equal(32.0, rotclip.Width, 4); + Assert.Equal(32.0, rotclip.Height, 4); } } @@ -2363,15 +2363,15 @@ public void VisibleClipBound_BigClip() g.RotateTransform(90); RectangleF rotclipbound = g.ClipBounds; Assert.Equal(0, rotclipbound.X); - Assert.Equal(-200, rotclipbound.Y, 4); - Assert.Equal(200, rotclipbound.Width, 4); - Assert.Equal(200, rotclipbound.Height, 4); + Assert.Equal(-200.0, rotclipbound.Y, 4); + Assert.Equal(200.0, rotclipbound.Width, 4); + Assert.Equal(200.0, rotclipbound.Height, 4); RectangleF rotclip = g.VisibleClipBounds; Assert.Equal(0, rotclip.X); - Assert.Equal(-100, rotclip.Y, 4); - Assert.Equal(100, rotclip.Width, 4); - Assert.Equal(100, rotclip.Height, 4); + Assert.Equal(-100.0, rotclip.Y, 4); + Assert.Equal(100.0, rotclip.Width, 4); + Assert.Equal(100.0, rotclip.Height, 4); } } @@ -2390,15 +2390,15 @@ public void Rotate() RectangleF vcb = g.VisibleClipBounds; Assert.Equal(0, vcb.X); Assert.Equal(0, vcb.Y); - Assert.Equal(100, vcb.Width, 4); - Assert.Equal(50, vcb.Height, 4); + Assert.Equal(100.0, vcb.Width, 4); + Assert.Equal(50.0, vcb.Height, 4); g.RotateTransform(90); RectangleF rvcb = g.VisibleClipBounds; Assert.Equal(0, rvcb.X); - Assert.Equal(-100, rvcb.Y, 4); - Assert.Equal(50.0f, rvcb.Width, 4); - Assert.Equal(100, rvcb.Height, 4); + Assert.Equal(-100.0, rvcb.Y, 4); + Assert.Equal(50.0, rvcb.Width, 4); + Assert.Equal(100.0, rvcb.Height, 4); } } diff --git a/src/libraries/System.Drawing.Common/tests/mono/System.Imaging/MetafileTest.cs b/src/libraries/System.Drawing.Common/tests/mono/System.Imaging/MetafileTest.cs index a50622aa57edd..6fe608464542e 100644 --- a/src/libraries/System.Drawing.Common/tests/mono/System.Imaging/MetafileTest.cs +++ b/src/libraries/System.Drawing.Common/tests/mono/System.Imaging/MetafileTest.cs @@ -441,21 +441,21 @@ public void WorldTransforms() g.MultiplyTransform(m); // check float[] elements = g.Transform.Elements; - Assert.Equal(-1f, elements[0], 5); - Assert.Equal(0f, elements[1], 5); - Assert.Equal(0f, elements[2], 5); - Assert.Equal(-1f, elements[3], 5); - Assert.Equal(-2f, elements[4], 5); - Assert.Equal(-3f, elements[5], 5); + Assert.Equal(-1.0, elements[0], 5); + Assert.Equal(0.0, elements[1], 5); + Assert.Equal(0.0, elements[2], 5); + Assert.Equal(-1.0, elements[3], 5); + Assert.Equal(-2.0, elements[4], 5); + Assert.Equal(-3.0, elements[5], 5); g.Transform = m; elements = g.Transform.Elements; - Assert.Equal(0f, elements[0], 5); - Assert.Equal(0.5f, elements[1], 5); - Assert.Equal(-2f, elements[2], 5); - Assert.Equal(0f, elements[3], 5); - Assert.Equal(-4f, elements[4], 5); - Assert.Equal(-1f, elements[5], 5); + Assert.Equal(0.0, elements[0], 5); + Assert.Equal(0.5, elements[1], 5); + Assert.Equal(-2.0, elements[2], 5); + Assert.Equal(0.0, elements[3], 5); + Assert.Equal(-4.0, elements[4], 5); + Assert.Equal(-1.0, elements[5], 5); g.ResetTransform(); Assert.True(g.Transform.IsIdentity); diff --git a/src/libraries/System.Drawing.Common/tests/runtimeconfig.template.json b/src/libraries/System.Drawing.Common/tests/runtimeconfig.template.json deleted file mode 100644 index e3ad204dd9e51..0000000000000 --- a/src/libraries/System.Drawing.Common/tests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Drawing.EnableUnixSupport": true - } -} \ No newline at end of file diff --git a/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj b/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj index 162b5d563a72d..e8328af20cde9 100644 --- a/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj +++ b/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj @@ -36,7 +36,6 @@ Link="Common\Interop\Windows\User32\Interop.Win32SystemColors.cs" /> - diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs index 6b20ca15a3101..7d8df542caf68 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs @@ -62,12 +62,7 @@ private void WriteGeneralizedTimeCore( // where "f?" is anything from "f" to "fffffff" (tenth of a second down to 100ns/1-tick) // with no trailing zeros. DateTimeOffset normalized = value.ToUniversalTime(); - - if (normalized.Year > 9999) - { - // This is unreachable since DateTimeOffset guards against this internally. - throw new ArgumentOutOfRangeException(nameof(value)); - } + Debug.Assert(normalized.Year <= 9999, "DateTimeOffset guards against this internally"); // We're only loading in sub-second ticks. // Ticks are defined as 1e-7 seconds, so their printed form diff --git a/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.cs b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.cs index bd7bf6946eff1..54b232c9864a7 100644 --- a/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.cs +++ b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.cs @@ -44,7 +44,6 @@ public void ReadEndArray() { } public void ReadEndIndefiniteLengthByteString() { } public void ReadEndIndefiniteLengthTextString() { } public void ReadEndMap() { } - public System.Half ReadHalf() { throw null; } public int ReadInt32() { throw null; } public long ReadInt64() { throw null; } public void ReadNull() { } @@ -145,7 +144,6 @@ public void WriteEndArray() { } public void WriteEndIndefiniteLengthByteString() { } public void WriteEndIndefiniteLengthTextString() { } public void WriteEndMap() { } - public void WriteHalf(System.Half value) { } public void WriteInt32(int value) { } public void WriteInt64(long value) { } public void WriteNull() { } diff --git a/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.csproj index 963fb857541bd..6aa93dd583d89 100644 --- a/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.csproj @@ -1,11 +1,12 @@ - $(NetCoreAppCurrent);$(NetCoreAppMinimum) + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) enable + @@ -17,4 +18,8 @@ + + + + diff --git a/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.netcoreapp.cs b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.netcoreapp.cs new file mode 100644 index 0000000000000..a68c16ee24dbd --- /dev/null +++ b/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.netcoreapp.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Formats.Cbor +{ + public partial class CborReader + { + public System.Half ReadHalf() { throw null; } + } + public partial class CborWriter + { + public void WriteHalf(System.Half value) { } + } +} diff --git a/src/libraries/System.Formats.Cbor/src/CompatibilitySuppressions.xml b/src/libraries/System.Formats.Cbor/src/CompatibilitySuppressions.xml index 8520fb12af7b6..22aa07a6de51c 100644 --- a/src/libraries/System.Formats.Cbor/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Formats.Cbor/src/CompatibilitySuppressions.xml @@ -1,7 +1,17 @@  - PKV006 - net5.0 + CP0002 + M:System.Formats.Cbor.CborReader.ReadHalf + lib/net5.0/System.Formats.Cbor.dll + lib/netstandard2.0/System.Formats.Cbor.dll + true + + + CP0002 + M:System.Formats.Cbor.CborWriter.WriteHalf(System.Half) + lib/net5.0/System.Formats.Cbor.dll + lib/netstandard2.0/System.Formats.Cbor.dll + true \ No newline at end of file diff --git a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj index d456daec3ab4b..c4783ca29c167 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetCoreAppMinimum) + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true enable true @@ -12,7 +12,6 @@ System.Formats.Cbor.CborWriter - @@ -35,8 +34,21 @@ System.Formats.Cbor.CborWriter - - + + + + + + + + + + + + + + + @@ -47,4 +59,14 @@ System.Formats.Cbor.CborWriter + + + + + + + + + + diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs new file mode 100644 index 0000000000000..3832e832569c9 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Buffers.Binary; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Text; + +namespace System.Formats.Cbor +{ + internal static partial class CborHelpers + { + public static readonly DateTimeOffset UnixEpoch = DateTimeOffset.UnixEpoch; + + public static int GetBytes(Encoding encoding, ReadOnlySpan source, Span destination) + => encoding.GetBytes(source, destination); + + public static int GetByteCount(Encoding encoding, ReadOnlySpan chars) + => encoding.GetByteCount(chars); + + public static int GetChars(Encoding encoding, ReadOnlySpan source, Span destination) + => encoding.GetChars(source, destination); + + public static int GetCharCount(Encoding encoding, ReadOnlySpan source) + => encoding.GetCharCount(source); + + public static string GetString(Encoding encoding, ReadOnlySpan bytes) + => encoding.GetString(bytes); + + public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bytes) + => new BigInteger(bytes, isUnsigned: true, isBigEndian: true); + + public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value) + => value.ToByteArray(isUnsigned: true, isBigEndian: true); + + public static void GetBitsFromDecimal(decimal d, Span destination) + => decimal.GetBits(d, destination); + + public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action) + => string.Create(length, state, action); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Half ReadHalfBigEndian(ReadOnlySpan source) + => BinaryPrimitives.ReadHalfBigEndian(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float ReadSingleBigEndian(ReadOnlySpan source) + => BinaryPrimitives.ReadSingleBigEndian(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double ReadDoubleBigEndian(ReadOnlySpan source) + => BinaryPrimitives.ReadDoubleBigEndian(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void WriteSingleBigEndian(Span destination, float value) + => BinaryPrimitives.WriteSingleBigEndian(destination, value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void WriteDoubleBigEndian(Span destination, double value) + => BinaryPrimitives.WriteDoubleBigEndian(destination, value); + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs new file mode 100644 index 0000000000000..b4aafd735d5f8 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs @@ -0,0 +1,255 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +namespace System.Formats.Cbor +{ + internal static partial class CborHelpers + { + private const long UnixEpochTicks = 719162L /*Number of days from 1/1/0001 to 12/31/1969*/ * 10000 * 1000 * 60 * 60 * 24; /* Ticks per day.*/ + + public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(UnixEpochTicks, TimeSpan.Zero); + + public static unsafe int GetBytes(Encoding encoding, ReadOnlySpan source, Span destination) + { + if (source.IsEmpty || destination.IsEmpty) + { + return 0; + } + + fixed (char* charPtr = source) + fixed (byte* bytePtr = destination) + { + return encoding.GetBytes(charPtr, source.Length, bytePtr, destination.Length); + } + } + + public static unsafe int GetByteCount(Encoding encoding, ReadOnlySpan chars) + { + if (chars.IsEmpty) + { + return 0; + } + + fixed (char* charPtr = chars) + { + return encoding.GetByteCount(charPtr, chars.Length); + } + } + + public static unsafe int GetChars(Encoding encoding, ReadOnlySpan source, Span destination) + { + if (source.IsEmpty || destination.IsEmpty) + { + return 0; + } + + fixed (byte* bytePtr = source) + fixed (char* charPtr = destination) + { + return encoding.GetChars(bytePtr, source.Length, charPtr, destination.Length); + } + } + + public static unsafe int GetCharCount(Encoding encoding, ReadOnlySpan source) + { + if (source.IsEmpty) + { + return 0; + } + + fixed (byte* bytePtr = source) + { + return encoding.GetCharCount(bytePtr, source.Length); + } + } + + public static unsafe string GetString(Encoding encoding, ReadOnlySpan bytes) + { + if (bytes.IsEmpty) + { + return string.Empty; + } + + fixed (byte* bytePtr = bytes) + { + return encoding.GetString(bytePtr, bytes.Length); + } + } + + public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEndianBytes) + { + if (bigEndianBytes.Length == 0) + { + return new BigInteger(bigEndianBytes); + } + + byte[] temp; + if ((bigEndianBytes[0] & 0x80) != 0) // Is negative? + { + // To prevent positive values from being misinterpreted as negative values, + // you can add a zero-byte value to the most significant side of the array. + // Right in this case as it is Big-endian. + var bytesPlusOne = new byte[bigEndianBytes.Length + 1]; + bigEndianBytes.CopyTo(bytesPlusOne.AsSpan().Slice(1)); + temp = bytesPlusOne; + } + else + { + temp = bigEndianBytes; + } + + // Reverse endianness + temp.AsSpan().Reverse(); + + return new BigInteger(temp); + } + + public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value) + { + byte[] littleEndianBytes = value.ToByteArray(); + + if (littleEndianBytes.Length == 1) + { + return littleEndianBytes; + } + + Span bytesAsSpan = littleEndianBytes; + bytesAsSpan.Reverse(); + + int start = 0; + for (int i = 0; i < bytesAsSpan.Length; i++) + { + if (bytesAsSpan[i] == 0x00) + { + start++; + } + else + { + break; + } + } + + Debug.Assert(start <= 1); // If there is a case where we trim more than one byte, we want to add it to our tests. + + return start == 0 ? littleEndianBytes : bytesAsSpan.Slice(start).ToArray(); + } + + public static void GetBitsFromDecimal(decimal d, Span destination) + { + decimal.GetBits(d).CopyTo(destination); + } + + public delegate void SpanAction(Span span, TArg arg); + + public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action) + { + char[] arr = new char[length]; + action(arr, state); + return new string(arr); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort ReadHalfBigEndian(ReadOnlySpan source) + { + ushort value = BitConverter.IsLittleEndian ? + BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteHalfBigEndian(Span destination, ushort value) + { + if (BitConverter.IsLittleEndian) + { + ushort tmp = BinaryPrimitives.ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float ReadSingleBigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + Int32BitsToSingle(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void WriteSingleBigEndian(Span destination, float value) + { + if (BitConverter.IsLittleEndian) + { + int tmp = BinaryPrimitives.ReverseEndianness(SingleToInt32Bits(value)); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double ReadDoubleBigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void WriteDoubleBigEndian(Span destination, double value) + { + if (BitConverter.IsLittleEndian) + { + long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + internal static uint SingleToUInt32Bits(float value) + => (uint)SingleToInt32Bits(value); + + internal static unsafe int SingleToInt32Bits(float value) + => *((int*)&value); + + internal static float UInt32BitsToSingle(uint value) + => Int32BitsToSingle((int)value); + + internal static unsafe float Int32BitsToSingle(int value) + => *((float*)&value); + } + + internal static class StackExtensions + { + public static bool TryPop(this Stack stack, [MaybeNullWhen(false)] out T result) + { + if (stack.Count > 0) + { + result = stack.Pop(); + return true; + } + + result = default; + return false; + } + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.cs deleted file mode 100644 index e3ac9428b037e..0000000000000 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.cs +++ /dev/null @@ -1,50 +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.Buffers.Binary; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace System.Formats.Cbor -{ - // Temporarily implements missing APIs for System.Half - // Remove class once https://github.com/dotnet/runtime/issues/38288 has been addressed - internal static class HalfHelpers - { - public const int SizeOfHalf = sizeof(short); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Half ReadHalfBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - Int16BitsToHalf(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteHalfBigEndian(Span destination, Half value) - { - if (BitConverter.IsLittleEndian) - { - short tmp = BinaryPrimitives.ReverseEndianness(HalfToInt16Bits(value)); - MemoryMarshal.Write(destination, ref tmp); - } - else - { - MemoryMarshal.Write(destination, ref value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe short HalfToInt16Bits(Half value) - { - return *((short*)&value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe Half Int16BitsToHalf(short value) - { - return *(Half*)&value; - } - } -} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs new file mode 100644 index 0000000000000..96514354547b2 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Formats.Cbor +{ + internal static partial class HalfHelpers + { + public static unsafe float HalfToFloat(Half value) + => (float)value; + + public static unsafe double HalfToDouble(Half value) + => (double)value; + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs new file mode 100644 index 0000000000000..36dfafd6ff340 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Formats.Cbor +{ + internal static partial class HalfHelpers + { + // Half constants + private const ushort HalfExponentMask = 0x7C00; + private const ushort HalfExponentShift = 10; + private const ushort HalfSignShift = 15; + private const ushort HalfPositiveInfinityBits = 0x7C00; + private const ushort HalfNegativeInfinityBits = 0xFC00; + + // Float constants + private const uint FloatExponentMask = 0x7F80_0000; + private const int FloatExponentShift = 23; + private const uint FloatSignificandMask = 0x007F_FFFF; + private const uint FloatSignMask = 0x8000_0000; + private const int FloatSignShift = 31; + + #region From Half and related helpers. + // Instead of copying (yet again) the explicit operator, + // we perform a Half to float to double conversion. + public static double HalfToDouble(ushort value) + => (double)HalfToFloat(value); + + public static unsafe float HalfToFloat(ushort value) + { + const ushort ExponentMask = 0x7C00; + const ushort ExponentShift = 10; + const ushort SignificandMask = 0x03FF; + const ushort SignificandShift = 0; + const ushort MaxExponent = 0x1F; + + bool sign = (short)value < 0; + int exp = (sbyte)((value & ExponentMask) >> ExponentShift); + uint sig = (ushort)((value & SignificandMask) >> SignificandShift); + + if (exp == MaxExponent) + { + if (sig != 0) + { + return CreateSingleNaN(sign, (ulong)sig << 54); + } + return sign ? float.NegativeInfinity : float.PositiveInfinity; + } + + if (exp == 0) + { + if (sig == 0) + { + return CborHelpers.UInt32BitsToSingle(sign ? FloatSignMask : 0); // Positive / Negative zero + } + (exp, sig) = NormSubnormalF16Sig(sig); + exp -= 1; + } + + return CreateSingle(sign, (byte)(exp + 0x70), sig << 13); + + static float CreateSingle(bool sign, byte exp, uint sig) + => CborHelpers.Int32BitsToSingle((int)(((sign ? 1U : 0U) << FloatSignShift) + ((uint)exp << FloatExponentShift) + sig)); + } + + private static (int Exp, uint Sig) NormSubnormalF16Sig(uint sig) + { + int shiftDist = LeadingZeroCount(sig) - 16 - 5; + return (1 - shiftDist, sig << shiftDist); + } + + public static int LeadingZeroCount(uint value) + { + // Unguarded fallback contract is 0->31, BSR contract is 0->undefined + if (value == 0) + { + return 32; + } + + return 31 ^ Log2SoftwareFallback(value); + } + + private static ReadOnlySpan Log2DeBruijn => new byte[32] + { + 00, 09, 01, 10, 13, 21, 02, 29, + 11, 14, 16, 18, 22, 25, 03, 30, + 08, 12, 20, 28, 15, 17, 24, 07, + 19, 27, 23, 06, 26, 05, 04, 31 + }; + + private static int Log2SoftwareFallback(uint value) + { + // No AggressiveInlining due to large method size + // Has conventional contract 0->0 (Log(0) is undefined) + + // Fill trailing zeros with ones, eg 00010010 becomes 00011111 + value |= value >> 01; + value |= value >> 02; + value |= value >> 04; + value |= value >> 08; + value |= value >> 16; + + // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check + return Unsafe.AddByteOffset( + // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u + ref MemoryMarshal.GetReference(Log2DeBruijn), + // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here + (IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); + } + + private static float CreateSingleNaN(bool sign, ulong significand) + { + const uint NaNBits = FloatExponentMask | 0x400000; // Most significant significand bit + + uint signInt = (sign ? 1U : 0U) << FloatSignShift; + uint sigInt = (uint)(significand >> 41); + + return CborHelpers.UInt32BitsToSingle(signInt | NaNBits | sigInt); + } + #endregion + + #region To Half and related helpers. + public static ushort FloatToHalf(float value) + { + const int SingleMaxExponent = 0xFF; + + uint floatInt = CborHelpers.SingleToUInt32Bits(value); + bool sign = (floatInt & FloatSignMask) >> FloatSignShift != 0; + int exp = (int)(floatInt & FloatExponentMask) >> FloatExponentShift; + uint sig = floatInt & FloatSignificandMask; + + if (exp == SingleMaxExponent) + { + if (sig != 0) // NaN + { + return CreateHalfNaN(sign, (ulong)sig << 41); // Shift the significand bits to the left end + } + return sign ? HalfNegativeInfinityBits : HalfPositiveInfinityBits; + } + + uint sigHalf = sig >> 9 | ((sig & 0x1FFU) != 0 ? 1U : 0U); // RightShiftJam + + if ((exp | (int)sigHalf) == 0) + { + return HalfCtor(sign, 0, 0); + } + + return RoundPackToHalf(sign, (short)(exp - 0x71), (ushort)(sigHalf | 0x4000)); + } + + private static ushort CreateHalfNaN(bool sign, ulong significand) + { + const uint NaNBits = HalfExponentMask | 0x200; // Most significant significand bit + + uint signInt = (sign ? 1U : 0U) << HalfSignShift; + uint sigInt = (uint)(significand >> 54); + + return (ushort)(signInt | NaNBits | sigInt); + } + + private static ushort HalfCtor(bool sign, ushort exp, ushort sig) + => (ushort)(((sign ? 1 : 0) << HalfSignShift) + (exp << HalfExponentShift) + sig); + + private static ushort RoundPackToHalf(bool sign, short exp, ushort sig) + { + const int RoundIncrement = 0x8; // Depends on rounding mode but it's always towards closest / ties to even + int roundBits = sig & 0xF; + + if ((uint)exp >= 0x1D) + { + if (exp < 0) + { + sig = (ushort)ShiftRightJam(sig, -exp); + exp = 0; + roundBits = sig & 0xF; + } + else if (exp > 0x1D || sig + RoundIncrement >= 0x8000) // Overflow + { + return sign ? HalfNegativeInfinityBits : HalfPositiveInfinityBits; + } + } + + sig = (ushort)((sig + RoundIncrement) >> 4); + sig &= (ushort)~(((roundBits ^ 8) != 0 ? 0 : 1) & 1); + + if (sig == 0) + { + exp = 0; + } + + return HalfCtor(sign, (ushort)exp, sig); + } + + // If any bits are lost by shifting, "jam" them into the LSB. + // if dist > bit count, Will be 1 or 0 depending on i + // (unlike bitwise operators that masks the lower 5 bits) + private static uint ShiftRightJam(uint i, int dist) + => dist < 31 ? (i >> dist) | (i << (-dist & 31) != 0 ? 1U : 0U) : (i != 0 ? 1U : 0U); + #endregion + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs index 9d2188ac34723..6c1e6c0b6087d 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs @@ -7,42 +7,6 @@ namespace System.Formats.Cbor { public partial class CborReader { - /// Reads the next data item as a half-precision floating point number (major type 7). - /// The decoded value. - /// The next data item does not have the correct major type. - /// -or- - /// The next simple value is not a floating-point number encoding. - /// -or- - /// The encoded value is a double-precision float. - /// The next value has an invalid CBOR encoding. - /// -or- - /// There was an unexpected end of CBOR encoding data. - /// -or- - /// The next value uses a CBOR encoding that is not valid under the current conformance mode. - public Half ReadHalf() - { - CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple); - ReadOnlySpan buffer = GetRemainingBytes(); - Half result; - - switch (header.AdditionalInfo) - { - case CborAdditionalInfo.Additional16BitData: - EnsureReadCapacity(buffer, 1 + HalfHelpers.SizeOfHalf); - result = HalfHelpers.ReadHalfBigEndian(buffer.Slice(1)); - AdvanceBuffer(1 + HalfHelpers.SizeOfHalf); - AdvanceDataItemCounters(); - return result; - - case CborAdditionalInfo.Additional32BitData: - case CborAdditionalInfo.Additional64BitData: - throw new InvalidOperationException(SR.Cbor_Reader_ReadingAsLowerPrecision); - - default: - throw new InvalidOperationException(SR.Cbor_Reader_NotAFloatEncoding); - } - } - /// Reads the next data item as a single-precision floating point number (major type 7). /// The decoded value. /// The next data item does not have the correct major type. @@ -64,15 +28,15 @@ public float ReadSingle() switch (header.AdditionalInfo) { case CborAdditionalInfo.Additional16BitData: - EnsureReadCapacity(buffer, 1 + HalfHelpers.SizeOfHalf); - result = (float)HalfHelpers.ReadHalfBigEndian(buffer.Slice(1)); - AdvanceBuffer(1 + HalfHelpers.SizeOfHalf); + EnsureReadCapacity(buffer, 1 + sizeof(ushort)); + result = HalfHelpers.HalfToFloat(CborHelpers.ReadHalfBigEndian(buffer.Slice(1))); + AdvanceBuffer(1 + sizeof(ushort)); AdvanceDataItemCounters(); return result; case CborAdditionalInfo.Additional32BitData: EnsureReadCapacity(buffer, 1 + sizeof(float)); - result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1)); + result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(float)); AdvanceDataItemCounters(); return result; @@ -105,22 +69,22 @@ public double ReadDouble() switch (header.AdditionalInfo) { case CborAdditionalInfo.Additional16BitData: - EnsureReadCapacity(buffer, 1 + HalfHelpers.SizeOfHalf); - result = (double)HalfHelpers.ReadHalfBigEndian(buffer.Slice(1)); - AdvanceBuffer(1 + HalfHelpers.SizeOfHalf); + EnsureReadCapacity(buffer, 1 + sizeof(short)); + result = HalfHelpers.HalfToDouble(CborHelpers.ReadHalfBigEndian(buffer.Slice(1))); + AdvanceBuffer(1 + sizeof(short)); AdvanceDataItemCounters(); return result; case CborAdditionalInfo.Additional32BitData: EnsureReadCapacity(buffer, 1 + sizeof(float)); - result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1)); + result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(float)); AdvanceDataItemCounters(); return result; case CborAdditionalInfo.Additional64BitData: EnsureReadCapacity(buffer, 1 + sizeof(double)); - result = BinaryPrimitives.ReadDoubleBigEndian(buffer.Slice(1)); + result = CborHelpers.ReadDoubleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(double)); AdvanceDataItemCounters(); return result; diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.netcoreapp.cs new file mode 100644 index 0000000000000..d02fc0cd6b2aa --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.netcoreapp.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers.Binary; + +namespace System.Formats.Cbor +{ + public partial class CborReader + { + /// Reads the next data item as a half-precision floating point number (major type 7). + /// The decoded value. + /// The next data item does not have the correct major type. + /// -or- + /// The next simple value is not a floating-point number encoding. + /// -or- + /// The encoded value is a double-precision float. + /// The next value has an invalid CBOR encoding. + /// -or- + /// There was an unexpected end of CBOR encoding data. + /// -or- + /// The next value uses a CBOR encoding that is not valid under the current conformance mode. + public Half ReadHalf() + { + CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple); + ReadOnlySpan buffer = GetRemainingBytes(); + Half result; + + switch (header.AdditionalInfo) + { + case CborAdditionalInfo.Additional16BitData: + EnsureReadCapacity(buffer, 1 + sizeof(short)); + result = BinaryPrimitives.ReadHalfBigEndian(buffer.Slice(1)); + AdvanceBuffer(1 + sizeof(short)); + AdvanceDataItemCounters(); + return result; + case CborAdditionalInfo.Additional32BitData: + case CborAdditionalInfo.Additional64BitData: + throw new InvalidOperationException(SR.Cbor_Reader_ReadingAsLowerPrecision); + + default: + throw new InvalidOperationException(SR.Cbor_Reader_NotAFloatEncoding); + } + } + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs index 6ede28d84230b..b9eac39f55343 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs @@ -192,7 +192,7 @@ public string ReadTextString() string result; try { - result = utf8Encoding.GetString(encodedString); + result = CborHelpers.GetString(utf8Encoding, encodedString); } catch (DecoderFallbackException e) { @@ -244,7 +244,7 @@ public bool TryReadTextString(Span destination, out int charsWritten) return false; } - utf8Encoding.GetChars(encodedSlice, destination); + CborHelpers.GetChars(utf8Encoding, encodedSlice, destination); AdvanceBuffer(bytesRead + byteLength); AdvanceDataItemCounters(); charsWritten = charLength; @@ -387,7 +387,7 @@ private string ReadIndefiniteLengthTextStringConcatenated() } // build the string using range data - string output = string.Create(concatenatedStringSize, (ranges, _data.Slice(_offset), utf8Encoding), BuildString); + string output = CborHelpers.BuildStringFromIndefiniteLengthTextString(concatenatedStringSize, (ranges, _data.Slice(_offset), utf8Encoding), BuildString); AdvanceBuffer(encodingLength); AdvanceDataItemCounters(); @@ -400,7 +400,7 @@ static void BuildString(Span target, (List<(int Offset, int Length)> range foreach ((int o, int l) in input.ranges) { - int charsWritten = input.utf8Encoding.GetChars(source.Slice(o, l), target); + int charsWritten = CborHelpers.GetChars(input.utf8Encoding, source.Slice(o, l), target); target = target.Slice(charsWritten); } @@ -429,7 +429,7 @@ private bool TryReadIndefiniteLengthTextStringConcatenated(Span destinatio foreach ((int o, int l) in ranges) { - utf8Encoding.GetChars(buffer.Slice(o, l), destination); + CborHelpers.GetChars(utf8Encoding, buffer.Slice(o, l), destination); destination = destination.Slice(l); } @@ -507,7 +507,7 @@ private int ValidateUtf8AndGetCharCount(ReadOnlySpan buffer, Encoding utf8 { try { - return utf8Encoding.GetCharCount(buffer); + return CborHelpers.GetCharCount(utf8Encoding, buffer); } catch (DecoderFallbackException e) { diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs index edf6d868b7f62..a2107ccf0f8ae 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs @@ -125,7 +125,7 @@ public DateTimeOffset ReadUnixTimeSeconds() } TimeSpan timespan = TimeSpan.FromSeconds(seconds); - return DateTimeOffset.UnixEpoch + timespan; + return CborHelpers.UnixEpoch + timespan; default: throw new CborContentException(SR.Cbor_Reader_InvalidUnixTimeEncoding); @@ -175,7 +175,7 @@ public BigInteger ReadBigInteger() } byte[] unsignedBigEndianEncoding = ReadByteString(); - BigInteger unsignedValue = new BigInteger(unsignedBigEndianEncoding, isUnsigned: true, isBigEndian: true); + BigInteger unsignedValue = CborHelpers.CreateBigIntegerFromUnsignedBigEndianBytes(unsignedBigEndianEncoding); return isNegative ? -1 - unsignedValue : unsignedValue; } catch diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs index 6d4178bae79bb..74f0524b01638 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace System.Formats.Cbor @@ -10,22 +9,6 @@ public partial class CborWriter { // Implements major type 7 encoding per https://tools.ietf.org/html/rfc7049#section-2.1 - /// Writes a half-precision floating point number (major type 7). - /// The value to write. - /// Writing a new value exceeds the definite length of the parent data item. - /// -or- - /// The major type of the encoded value is not permitted in the parent data item. - /// -or- - /// The written data is not accepted under the current conformance mode. - public void WriteHalf(Half value) - { - EnsureWriteCapacity(1 + HalfHelpers.SizeOfHalf); - WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional16BitData)); - HalfHelpers.WriteHalfBigEndian(_buffer.AsSpan(_offset), value); - _offset += HalfHelpers.SizeOfHalf; - AdvanceDataItemCounters(); - } - /// Writes a single-precision floating point number (major type 7). /// The value to write. /// Writing a new value exceeds the definite length of the parent data item. @@ -36,7 +19,7 @@ public void WriteHalf(Half value) public void WriteSingle(float value) { if (!CborConformanceModeHelpers.RequiresPreservingFloatPrecision(ConformanceMode) && - FloatSerializationHelpers.TryConvertSingleToHalf(value, out Half half)) + TryConvertSingleToHalf(value, out var half)) { WriteHalf(half); } @@ -56,9 +39,9 @@ public void WriteSingle(float value) public void WriteDouble(double value) { if (!CborConformanceModeHelpers.RequiresPreservingFloatPrecision(ConformanceMode) && - FloatSerializationHelpers.TryConvertDoubleToSingle(value, out float single)) + TryConvertDoubleToSingle(value, out float single)) { - if (FloatSerializationHelpers.TryConvertSingleToHalf(single, out Half half)) + if (TryConvertSingleToHalf(single, out var half)) { WriteHalf(half); } @@ -72,12 +55,11 @@ public void WriteDouble(double value) WriteDoubleCore(value); } } - private void WriteSingleCore(float value) { EnsureWriteCapacity(1 + sizeof(float)); WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional32BitData)); - BinaryPrimitives.WriteSingleBigEndian(_buffer.AsSpan(_offset), value); + CborHelpers.WriteSingleBigEndian(_buffer.AsSpan(_offset), value); _offset += sizeof(float); AdvanceDataItemCounters(); } @@ -86,7 +68,7 @@ private void WriteDoubleCore(double value) { EnsureWriteCapacity(1 + sizeof(double)); WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional64BitData)); - BinaryPrimitives.WriteDoubleBigEndian(_buffer.AsSpan(_offset), value); + CborHelpers.WriteDoubleBigEndian(_buffer.AsSpan(_offset), value); _offset += sizeof(double); AdvanceDataItemCounters(); } @@ -144,21 +126,11 @@ public void WriteSimpleValue(CborSimpleValue value) AdvanceDataItemCounters(); } - private static class FloatSerializationHelpers + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryConvertDoubleToSingle(double value, out float result) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryConvertDoubleToSingle(double value, out float result) - { - result = (float)value; - return BitConverter.DoubleToInt64Bits(result) == BitConverter.DoubleToInt64Bits(value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryConvertSingleToHalf(float value, out Half result) - { - result = (Half)value; - return BitConverter.SingleToInt32Bits((float)result) == BitConverter.SingleToInt32Bits(value); - } + result = (float)value; + return BitConverter.DoubleToInt64Bits(result) == BitConverter.DoubleToInt64Bits(value); } } } diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netcoreapp.cs new file mode 100644 index 0000000000000..db8986b1f20f1 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netcoreapp.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers.Binary; +using System.Runtime.CompilerServices; + +namespace System.Formats.Cbor +{ + public partial class CborWriter + { + // Implements major type 7 encoding per https://tools.ietf.org/html/rfc7049#section-2.1 + + /// Writes a half-precision floating point number (major type 7). + /// The value to write. + /// Writing a new value exceeds the definite length of the parent data item. + /// -or- + /// The major type of the encoded value is not permitted in the parent data item. + /// -or- + /// The written data is not accepted under the current conformance mode. + public void WriteHalf(Half value) + { + EnsureWriteCapacity(1 + sizeof(short)); + WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional16BitData)); + BinaryPrimitives.WriteHalfBigEndian(_buffer.AsSpan(_offset), value); + _offset += sizeof(short); + AdvanceDataItemCounters(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryConvertSingleToHalf(float value, out Half result) + { + result = (Half)value; + return BitConverter.SingleToInt32Bits((float)result) == BitConverter.SingleToInt32Bits(value); + } + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs new file mode 100644 index 0000000000000..02f134513facc --- /dev/null +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers.Binary; +using System.Runtime.CompilerServices; + +namespace System.Formats.Cbor +{ + public partial class CborWriter + { + // Implements major type 7 encoding per https://tools.ietf.org/html/rfc7049#section-2.1 + + /// Writes a half-precision floating point number (major type 7). + /// The value to write. + /// Writing a new value exceeds the definite length of the parent data item. + /// -or- + /// The major type of the encoded value is not permitted in the parent data item. + /// -or- + /// The written data is not accepted under the current conformance mode. + private void WriteHalf(ushort value) + { + EnsureWriteCapacity(1 + sizeof(ushort)); + WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional16BitData)); + CborHelpers.WriteHalfBigEndian(_buffer.AsSpan(_offset), value); + _offset += sizeof(ushort); + AdvanceDataItemCounters(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryConvertSingleToHalf(float value, out ushort result) + { + result = HalfHelpers.FloatToHalf(value); + return CborHelpers.SingleToInt32Bits(HalfHelpers.HalfToFloat(result)) == CborHelpers.SingleToInt32Bits(value); + } + } +} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs index 379163789c832..2e600d99dad32 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs @@ -131,7 +131,7 @@ public void WriteTextString(ReadOnlySpan value) int length; try { - length = utf8Encoding.GetByteCount(value); + length = CborHelpers.GetByteCount(utf8Encoding, value); } catch (EncoderFallbackException e) { @@ -150,7 +150,7 @@ public void WriteTextString(ReadOnlySpan value) _currentIndefiniteLengthStringRanges.Add((_offset, value.Length)); } - utf8Encoding.GetBytes(value, _buffer.AsSpan(_offset, length)); + CborHelpers.GetBytes(utf8Encoding, value, _buffer.AsSpan(_offset, length)); _offset += length; AdvanceDataItemCounters(); } diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs index bd94ca2acd15f..6ce58ec11d8e7 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs @@ -88,7 +88,7 @@ public void WriteBigInteger(BigInteger value) { bool isUnsigned = value.Sign >= 0; BigInteger unsignedValue = isUnsigned ? value : -1 - value; - byte[] unsignedBigEndianEncoding = unsignedValue.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] unsignedBigEndianEncoding = CborHelpers.CreateUnsignedBigEndianBytesFromBigInteger(unsignedValue); WriteTag(isUnsigned ? CborTag.UnsignedBigNum : CborTag.NegativeBigNum); WriteByteString(unsignedBigEndianEncoding); @@ -142,7 +142,7 @@ internal static class DecimalHelpers public static void Deconstruct(decimal value, out decimal mantissa, out byte scale) { Span buf = stackalloc int[4]; - decimal.GetBits(value, buf); + CborHelpers.GetBitsFromDecimal(value, buf); int flags = buf[3]; bool isNegative = (flags & SignMask) == SignMask; @@ -154,7 +154,7 @@ public static void Deconstruct(decimal value, out decimal mantissa, out byte sca private static decimal ReconstructFromNegativeScale(decimal mantissa, byte scale) { Span buf = stackalloc int[4]; - decimal.GetBits(mantissa, buf); + CborHelpers.GetBitsFromDecimal(mantissa, buf); int flags = buf[3]; bool isNegative = (flags & SignMask) == SignMask; diff --git a/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netcoreapp.cs b/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netcoreapp.cs new file mode 100644 index 0000000000000..6aaa045512800 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netcoreapp.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Formats.Cbor.Tests +{ + internal static class CborTestHelpers + { + public static readonly DateTimeOffset UnixEpoch = DateTimeOffset.UnixEpoch; + } +} diff --git a/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netstandard.cs new file mode 100644 index 0000000000000..80fb9cd7db6db --- /dev/null +++ b/src/libraries/System.Formats.Cbor/tests/CborTestHelpers.netstandard.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Formats.Cbor.Tests +{ + internal static class CborTestHelpers + { + private const long UnixEpochTicks = 719162L /*Number of days from 1/1/0001 to 12/31/1969*/ * 10000 * 1000 * 60 * 60 * 24; /* Ticks per day.*/ + public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(UnixEpochTicks, TimeSpan.Zero); + } +} diff --git a/src/libraries/System.Formats.Cbor/tests/CoseKeyHelpers.cs b/src/libraries/System.Formats.Cbor/tests/CoseKeyHelpers.cs index a3cfca3069e07..944b86ae7b336 100644 --- a/src/libraries/System.Formats.Cbor/tests/CoseKeyHelpers.cs +++ b/src/libraries/System.Formats.Cbor/tests/CoseKeyHelpers.cs @@ -90,7 +90,13 @@ private static void WriteECParametersAsCosePublicKey(CborWriter writer, ECParame throw new ArgumentException("Unrecognized named curve", curve.Oid.Value); - bool MatchesOid(ECCurve namedCurve) => curve.Oid.Value == namedCurve.Oid.Value; + bool MatchesOid(ECCurve namedCurve) => curve.Oid.Value == namedCurve.Oid.Value +#if NETFRAMEWORK + // If this check fails, resolve the OID Value yourself. + // See https://github.com/dotnet/runtime/issues/62813#issuecomment-994114540 + || (curve.Oid.Value is null && curve.Oid.FriendlyName == namedCurve.Oid.FriendlyName) +#endif + ; } static CoseKeyAlgorithm MapHashAlgorithmNameToCoseKeyAlg(HashAlgorithmName name) diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.ByteString.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.ByteString.cs index 1e06314986d78..567740818915a 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.ByteString.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.ByteString.cs @@ -38,7 +38,7 @@ public static void TryReadByteString_SingleValue_HappyPath(string hexExpectedVal bool result = reader.TryReadByteString(buffer, out int bytesWritten); Assert.True(result); Assert.Equal(expectedValue.Length, bytesWritten); - Assert.Equal(expectedValue, buffer[..bytesWritten]); + Assert.Equal(expectedValue, buffer.Take(bytesWritten)); Assert.Equal(CborReaderState.Finished, reader.PeekState()); } diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Map.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Map.cs index 126cae1b500a9..b94d01a23e2e3 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Map.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Map.cs @@ -226,7 +226,7 @@ public static void ReadMap_UnsortedKeys_ConformanceRequiringSortedKeys_ShouldThr { var reader = new CborReader(hexEncoding.HexToByteArray(), mode); reader.ReadStartMap(); - foreach (object key in keySequence.SkipLast(1)) + foreach (object key in keySequence.Take(keySequence.Length - 1)) { Helpers.VerifyValue(reader, key); // verify key reader.ReadInt32(); // value is always an integer diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.cs index 53075439bdf9c..1c71ba3b8668a 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.cs @@ -12,28 +12,7 @@ public partial class CborReaderTests // Additional pairs generated using http://cbor.me/ [Theory] - [InlineData(0.0, "f90000")] - [InlineData(-0.0, "f98000")] - [InlineData(1.0, "f93c00")] - [InlineData(1.5, "f93e00")] - [InlineData(65504.0, "f97bff")] - [InlineData(5.960464477539063e-8, "f90001")] - [InlineData(0.00006103515625, "f90400")] - [InlineData(-4.0, "f9c400")] - [InlineData(double.PositiveInfinity, "f97c00")] - [InlineData(double.NaN, "f97e00")] - [InlineData(double.NegativeInfinity, "f9fc00")] - public static void ReadHalf_SingleValue_HappyPath(float expectedResult, string hexEncoding) - { - byte[] encoding = hexEncoding.HexToByteArray(); - var reader = new CborReader(encoding); - Assert.Equal(CborReaderState.HalfPrecisionFloat, reader.PeekState()); - Half actualResult = reader.ReadHalf(); - AssertHelpers.Equal((Half)expectedResult, actualResult); - Assert.Equal(CborReaderState.Finished, reader.PeekState()); - } - - [Theory] + [InlineData(1.0, "fa3f800000")] [InlineData(100000.0, "fa47c35000")] [InlineData(3.4028234663852886e+38, "fa7f7fffff")] [InlineData(float.PositiveInfinity, "fa7f800000")] @@ -247,25 +226,6 @@ public static void ReadNull_InvalidTypes_ShouldThrowInvalidOperationException(st Assert.Equal(encoding.Length, reader.BytesRemaining); } - [Theory] - [InlineData("01")] // integer - [InlineData("40")] // empty text string - [InlineData("60")] // empty byte string - [InlineData("80")] // [] - [InlineData("a0")] // {} - [InlineData("f6")] // null - [InlineData("f4")] // false - [InlineData("c202")] // tagged value - [InlineData("fa47c35000")] // single-precision float encoding - [InlineData("fb7ff0000000000000")] // double-precision float encoding - public static void ReadHalf_InvalidTypes_ShouldThrowInvalidOperationException(string hexEncoding) - { - byte[] encoding = hexEncoding.HexToByteArray(); - var reader = new CborReader(encoding); - Assert.Throws(() => reader.ReadHalf()); - Assert.Equal(encoding.Length, reader.BytesRemaining); - } - [Theory] [InlineData("01")] // integer [InlineData("40")] // empty text string @@ -300,21 +260,5 @@ public static void ReadDouble_InvalidTypes_ShouldThrowInvalidOperationException( Assert.Throws(() => reader.ReadDouble()); Assert.Equal(encoding.Length, reader.BytesRemaining); } - - public static class AssertHelpers - { - // temporary workaround for xunit's lack of support for Half equality assertions - public static void Equal(Half expected, Half actual) - { - if (Half.IsNaN(expected)) - { - Assert.True(Half.IsNaN(actual), $"Expected: {expected}\nActual: {actual}"); - } - else - { - Assert.Equal(expected, actual); - } - } - } } } diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.netcoreapp.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.netcoreapp.cs new file mode 100644 index 0000000000000..8a11121bbb1a8 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Simple.netcoreapp.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Test.Cryptography; +using Xunit; + +namespace System.Formats.Cbor.Tests +{ + public partial class CborReaderTests + { + [Theory] + [InlineData(0.0, "f90000")] + [InlineData(-0.0, "f98000")] + [InlineData(1.0, "f93c00")] + [InlineData(1.5, "f93e00")] + [InlineData(65504.0, "f97bff")] + [InlineData(5.960464477539063e-8, "f90001")] + [InlineData(0.00006103515625, "f90400")] + [InlineData(-4.0, "f9c400")] + [InlineData(double.PositiveInfinity, "f97c00")] + [InlineData(double.NaN, "f97e00")] + [InlineData(double.NegativeInfinity, "f9fc00")] + public static void ReadHalf_SingleValue_HappyPath(float expectedResult, string hexEncoding) + { + byte[] encoding = hexEncoding.HexToByteArray(); + var reader = new CborReader(encoding); + Assert.Equal(CborReaderState.HalfPrecisionFloat, reader.PeekState()); + Half actualResult = reader.ReadHalf(); + AssertHelpers.Equal((Half)expectedResult, actualResult); + Assert.Equal(CborReaderState.Finished, reader.PeekState()); + } + + [Theory] + [InlineData("01")] // integer + [InlineData("40")] // empty text string + [InlineData("60")] // empty byte string + [InlineData("80")] // [] + [InlineData("a0")] // {} + [InlineData("f6")] // null + [InlineData("f4")] // false + [InlineData("c202")] // tagged value + [InlineData("fa47c35000")] // single-precision float encoding + [InlineData("fb7ff0000000000000")] // double-precision float encoding + public static void ReadHalf_InvalidTypes_ShouldThrowInvalidOperationException(string hexEncoding) + { + byte[] encoding = hexEncoding.HexToByteArray(); + var reader = new CborReader(encoding); + Assert.Throws(() => reader.ReadHalf()); + Assert.Equal(encoding.Length, reader.BytesRemaining); + } + + public static class AssertHelpers + { + + // temporary workaround for xunit's lack of support for Half equality assertions + public static void Equal(Half expected, Half actual) + { + if (Half.IsNaN(expected)) + { + Assert.True(Half.IsNaN(actual), $"Expected: {expected}\nActual: {actual}"); + } + else + { + Assert.Equal(expected, actual); + } + } + } + } +} diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Tag.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Tag.cs index f09e89115541e..af9adfbe67b50 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Tag.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.Tag.cs @@ -557,7 +557,7 @@ private static (object value, string hexEncoding)[] TaggedValues => (new object[] { CborTag.MimeMessage, 42 }, "d824182a"), (42.0m, "c482201901a4"), ((BigInteger)1, "c24101"), - (DateTimeOffset.UnixEpoch, "c0781c313937302d30312d30315430303a30303a30302e303030303030305a"), + (CborTestHelpers.UnixEpoch, "c0781c313937302d30312d30315430303a30303a30302e303030303030305a"), }; } } diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs index b06b36696f750..4f6acad8e5287 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Linq; using System.Text; using Test.Cryptography; using Xunit; @@ -44,7 +45,7 @@ public static void TryReadTextString_SingleValue_HappyPath(string expectedValue, bool result = reader.TryReadTextString(buffer, out int charsWritten); Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); - Assert.Equal(expectedValue.ToCharArray(), buffer[..charsWritten]); + Assert.Equal(expectedValue.ToCharArray(), buffer.Take(charsWritten)); Assert.Equal(CborReaderState.Finished, reader.PeekState()); } @@ -104,7 +105,11 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_SingleValue__H Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); - Assert.Equal(expectedValue, new string(buffer.Slice(0, charsWritten))); + Assert.Equal(expectedValue, new string(buffer.Slice(0, charsWritten) +#if !NETCOREAPP +.ToArray() +#endif + )); Assert.Equal(CborReaderState.Finished, reader.PeekState()); } @@ -130,7 +135,11 @@ public static void TryReadTextString_BufferTooSmall_ShouldReturnFalse(string act result = reader.TryReadTextString(buffer, out charsWritten); Assert.True(result); Assert.Equal(actualValue.Length, charsWritten); - Assert.Equal(actualValue, new string(buffer.AsSpan(0, charsWritten))); + Assert.Equal(actualValue, new string(buffer.AsSpan(0, charsWritten) +#if !NETCOREAPP +.ToArray() +#endif + )); } [Theory] @@ -152,7 +161,11 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_BufferTooSmall result = reader.TryReadTextString(buffer, out charsWritten); Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); - Assert.Equal(expectedValue, new string(buffer.AsSpan(0, charsWritten))); + Assert.Equal(expectedValue, new string(buffer.AsSpan(0, charsWritten) +#if !NETCOREAPP +.ToArray() +#endif + )); } [Theory] @@ -170,7 +183,11 @@ public static void ReadDefiniteLengthTextStringBytes_SingleValue_HappyPath(strin var reader = new CborReader(encoding); ReadOnlyMemory resultBytes = reader.ReadDefiniteLengthTextStringBytes(); - string result = System.Text.Encoding.UTF8.GetString(resultBytes.Span); + string result = Encoding.UTF8.GetString(resultBytes.Span +#if !NETCOREAPP +.ToArray() +#endif + ); Assert.Equal(expectedValue, result); Assert.Equal(0, reader.BytesRemaining); } diff --git a/src/libraries/System.Formats.Cbor/tests/System.Formats.Cbor.Tests.csproj b/src/libraries/System.Formats.Cbor/tests/System.Formats.Cbor.Tests.csproj index c2211d72e5b19..d6337713f665d 100644 --- a/src/libraries/System.Formats.Cbor/tests/System.Formats.Cbor.Tests.csproj +++ b/src/libraries/System.Formats.Cbor/tests/System.Formats.Cbor.Tests.csproj @@ -1,6 +1,6 @@ - + - $(NetCoreAppCurrent) + $(NetCoreAppCurrent);net48 enable CS8002 @@ -9,8 +9,6 @@ CommonTest\System\Security\Cryptography\ByteUtils.cs - - @@ -32,10 +30,25 @@ + + + + + + + + + + + + + + + + - diff --git a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.cs b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.cs index d6ef2d89aacda..8a0130cdf03f7 100644 --- a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.cs +++ b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.cs @@ -11,26 +11,6 @@ public partial class CborWriterTests // Data points taken from https://tools.ietf.org/html/rfc7049#appendix-A // Additional pairs generated using http://cbor.me/ - [Theory] - [InlineData(0.0, "f90000")] - [InlineData(-0.0, "f98000")] - [InlineData(1.0, "f93c00")] - [InlineData(1.5, "f93e00")] - [InlineData(65504.0, "f97bff")] - [InlineData(5.960464477539063e-8, "f90001")] - [InlineData(0.00006103515625, "f90400")] - [InlineData(-4.0, "f9c400")] - [InlineData(float.PositiveInfinity, "f97c00")] - [InlineData(float.NaN, "f9fe00")] - [InlineData(float.NegativeInfinity, "f9fc00")] - public static void WriteHalf_SingleValue_HappyPath(float input, string hexExpectedEncoding) - { - byte[] expectedEncoding = hexExpectedEncoding.HexToByteArray(); - var writer = new CborWriter(); - writer.WriteHalf((Half)input); - AssertHelper.HexEqual(expectedEncoding, writer.Encode()); - } - [Theory] [InlineData(100000.0, "fa47c35000")] [InlineData(3.4028234663852886e+38, "fa7f7fffff")] diff --git a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.netcoreapp.cs b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.netcoreapp.cs new file mode 100644 index 0000000000000..3ef7ad9655176 --- /dev/null +++ b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Simple.netcoreapp.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Test.Cryptography; +using Xunit; + +namespace System.Formats.Cbor.Tests +{ + public partial class CborWriterTests + { + [Theory] + [InlineData(0.0, "f90000")] + [InlineData(-0.0, "f98000")] + [InlineData(1.0, "f93c00")] + [InlineData(1.5, "f93e00")] + [InlineData(65504.0, "f97bff")] + [InlineData(5.960464477539063e-8, "f90001")] + [InlineData(0.00006103515625, "f90400")] + [InlineData(-4.0, "f9c400")] + [InlineData(float.PositiveInfinity, "f97c00")] + [InlineData(float.NaN, "f9fe00")] + [InlineData(float.NegativeInfinity, "f9fc00")] + public static void WriteHalf_SingleValue_HappyPath(float input, string hexExpectedEncoding) + { + byte[] expectedEncoding = hexExpectedEncoding.HexToByteArray(); + var writer = new CborWriter(); + writer.WriteHalf((Half)input); + AssertHelper.HexEqual(expectedEncoding, writer.Encode()); + } + } +} diff --git a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs index b9cc53ceb237b..3413eadc84cc3 100644 --- a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs +++ b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs @@ -206,7 +206,7 @@ from v in TaggedValues new object[] { CborTag.MimeMessage, 42 }, 42.0m, (BigInteger)1, - DateTimeOffset.UnixEpoch, + CborTestHelpers.UnixEpoch, }; } } diff --git a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.TextString.cs b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.TextString.cs index 70c7232412bf1..15292330a1573 100644 --- a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.TextString.cs +++ b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.TextString.cs @@ -54,7 +54,7 @@ public static void WriteTextString_IndefiniteLength_WithPatching_SingleValue_Hap public static void WriteTextString_NullValue_ShouldThrowArgumentNullException() { var writer = new CborWriter(); - Assert.Throws(() => writer.WriteTextString(null!)); + Assert.Throws(() => writer.WriteTextString((string)null!)); } [Theory] diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs index ee007af28b6d0..36ff2977b807d 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs @@ -65,7 +65,11 @@ internal static int[] GetCurrencyNegativePatterns(string localeName) return PlatformDetection.IsNlsGlobalization ? new int[] { 12 } : new int[] { 9 }; case "es-BO": - return (PlatformDetection.IsNlsGlobalization && PlatformDetection.WindowsVersion < 10) ? new int[] { 14 } : new int[] { 1 }; + return (PlatformDetection.IsNlsGlobalization && PlatformDetection.WindowsVersion < 10) ? + new int[] { 14 } : + // Mac OSX used to return 1 which is the format "-$n". OSX Version 12 (Monterey) started + // to return a different value 12 "$ -n". + PlatformDetection.IsOSX ? new int[] { 1, 12 } : new int[] { 1 }; case "fr-CA": return PlatformDetection.IsNlsGlobalization ? new int[] { 15 } : new int[] { 8, 15 }; diff --git a/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx b/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx index 8c18769cabcdc..355df1fd20412 100644 --- a/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx +++ b/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx @@ -132,9 +132,6 @@ Positive number required. - - Offset plus count is larger than the length of target array. - Only one asynchronous reader or writer is allowed time at one time. diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index 5d800c1f62ca7..fe725937441e2 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -83,7 +83,7 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination { File.SetLastWriteTime(destinationFileName, source.LastWriteTime.DateTime); } - catch (UnauthorizedAccessException) + catch { // some OSes like Android (#35374) might not support setting the last write time, the extraction should not fail because of that } diff --git a/src/libraries/System.IO.Compression/src/Resources/Strings.resx b/src/libraries/System.IO.Compression/src/Resources/Strings.resx index cac801aa8fcc4..08e13fd1bb144 100644 --- a/src/libraries/System.IO.Compression/src/Resources/Strings.resx +++ b/src/libraries/System.IO.Compression/src/Resources/Strings.resx @@ -131,9 +131,6 @@ Found invalid data while decoding. - - Offset plus count is larger than the length of target array. - Only one asynchronous reader or writer is allowed time at one time. @@ -179,9 +176,6 @@ The underlying compression routine returned an unexpected error code. - - The argument must be non-negative. - String cannot be empty. @@ -266,9 +260,6 @@ Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. - - The offset and length parameters are not valid for the array that was given. - This stream from ZipArchiveEntry does not support reading. diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs index ec71718a511d3..ca31e978b332f 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs @@ -310,16 +310,8 @@ protected override void Dispose(bool disposing) finally { _stream = null!; - - try - { - _inflater?.Dispose(); - } - finally - { - _inflater = null!; - base.Dispose(disposing); - } + _inflater = null!; + base.Dispose(disposing); } } } diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs index a127d93bd1d44..7222011895309 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs @@ -689,7 +689,5 @@ private bool DecodeDynamicBlockHeader() _state = InflaterState.DecodeTop; return true; } - - public void Dispose() { } } } diff --git a/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs b/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs index 64455bbc92ccb..ae5a0e9562c7d 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs +++ b/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs @@ -9,7 +9,7 @@ namespace System.IO public static partial class FileSystemAclExtensions { public static void Create(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.DirectorySecurity directorySecurity) { } - public static System.IO.FileStream Create(this System.IO.FileInfo fileInfo, System.IO.FileMode mode, System.Security.AccessControl.FileSystemRights rights, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options, System.Security.AccessControl.FileSecurity fileSecurity) { throw null; } + public static System.IO.FileStream Create(this System.IO.FileInfo fileInfo, System.IO.FileMode mode, System.Security.AccessControl.FileSystemRights rights, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options, System.Security.AccessControl.FileSecurity? fileSecurity) { throw null; } public static System.IO.DirectoryInfo CreateDirectory(this System.Security.AccessControl.DirectorySecurity directorySecurity, string path) { throw null; } public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo) { throw null; } public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.AccessControlSections includeSections) { throw null; } diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx b/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx index d71dfd08146e4..60ea3e762eb47 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx +++ b/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx @@ -1,3 +1,4 @@ + The specified file name or path is too long, or a component of the specified path is too long. diff --git a/src/libraries/System.IO.UnmanagedMemoryStream/tests/UmsSafeBuffer.cs b/src/libraries/System.IO.UnmanagedMemoryStream/tests/UmsSafeBuffer.cs index f5afb82342a63..cec8bb9ee15f1 100644 --- a/src/libraries/System.IO.UnmanagedMemoryStream/tests/UmsSafeBuffer.cs +++ b/src/libraries/System.IO.UnmanagedMemoryStream/tests/UmsSafeBuffer.cs @@ -95,7 +95,7 @@ public static void WriteSafeBuffer() using (var buffer = new TestSafeBuffer(length)) { var stream = new UnmanagedMemoryStream(buffer, 0, (long)buffer.ByteLength, FileAccess.Write); - Assert.Equal(stream.Length, length); + Assert.Equal(length, stream.Length); var bytes = ArrayHelpers.CreateByteArray(length); var copy = bytes.Copy(); @@ -116,7 +116,7 @@ public static void ReadWriteByteSafeBuffer() using (var buffer = new TestSafeBuffer(length)) { var stream = new UnmanagedMemoryStream(buffer, 0, (long)buffer.ByteLength, FileAccess.ReadWrite); - Assert.Equal(stream.Length, length); + Assert.Equal(length, stream.Length); var bytes = ArrayHelpers.CreateByteArray(length); for (int index = 0; index < length; index++) diff --git a/src/libraries/System.IO/tests/IndentedTextWriter.cs b/src/libraries/System.IO/tests/IndentedTextWriter.cs index 96a973ba375bb..78d9a8db49d01 100644 --- a/src/libraries/System.IO/tests/IndentedTextWriter.cs +++ b/src/libraries/System.IO/tests/IndentedTextWriter.cs @@ -312,7 +312,7 @@ public static void Ctor_ExpectedDefaults() Assert.Same(sw, itw.InnerWriter); Assert.Equal(sw.NewLine, itw.NewLine); - Assert.Equal(new string(' ', 4), IndentedTextWriter.DefaultTabString); + Assert.Equal(" ", IndentedTextWriter.DefaultTabString); } [Fact] diff --git a/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs b/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs index 5b2ab1f81e878..efe700c1e9c75 100644 --- a/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs +++ b/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs @@ -123,6 +123,16 @@ public static void TestNullStream_WriteByte() Assert.Equal(0, source.Position); } + [Theory] + [MemberData(nameof(NullReaders))] + public static void TestNullTextReaderDispose(TextReader input) + { + // dispose should be a no-op + input.Dispose(); + input.Dispose(); + Assert.Equal("", input.ReadToEnd()); + } + [Theory] [MemberData(nameof(NullReaders))] public static void TestNullTextReader(TextReader input) @@ -131,16 +141,54 @@ public static void TestNullTextReader(TextReader input) if (sr != null) Assert.True(sr.EndOfStream, "EndOfStream property didn't return true"); - input.ReadLine(); - input.Dispose(); - - input.ReadLine(); + Assert.Null(input.ReadLine()); if (sr != null) Assert.True(sr.EndOfStream, "EndOfStream property didn't return true"); - input.Read(); - input.Peek(); - input.Read(new char[2], 0, 2); - input.ReadToEnd(); + + Assert.Equal(-1, input.Read()); + Assert.Equal(-1, input.Peek()); + var chars = new char[2]; + Assert.Equal(0, input.Read(chars, 0, chars.Length)); + Assert.Equal(0, input.Read(chars.AsSpan())); + Assert.Equal(0, input.ReadBlock(chars, 0, chars.Length)); + Assert.Equal(0, input.ReadBlock(chars.AsSpan())); + Assert.Equal("", input.ReadToEnd()); + input.Dispose(); + } + + [Theory] + [MemberData(nameof(NullReaders))] + public static async Task TestNullTextReaderAsync(TextReader input) + { + var chars = new char[2]; + Assert.Equal(0, await input.ReadAsync(chars, 0, chars.Length)); + Assert.Equal(0, await input.ReadAsync(chars.AsMemory(), default)); + Assert.Equal(0, await input.ReadBlockAsync(chars, 0, chars.Length)); + Assert.Equal(0, await input.ReadBlockAsync(chars.AsMemory(), default)); + Assert.Null(await input.ReadLineAsync()); + Assert.Null(await input.ReadLineAsync(default)); + Assert.Equal("", await input.ReadToEndAsync()); + Assert.Equal("", await input.ReadToEndAsync(default)); + input.Dispose(); + } + + [Theory] + [MemberData(nameof(NullReaders))] + public static async Task TestCanceledNullTextReaderAsync(TextReader input) + { + using CancellationTokenSource tokenSource = new CancellationTokenSource(); + tokenSource.Cancel(); + var token = tokenSource.Token; + var chars = new char[2]; + OperationCanceledException ex; + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadAsync(chars.AsMemory(), token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadBlockAsync(chars.AsMemory(), token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadLineAsync(token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); input.Dispose(); } diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs index 2e19dd283ebbb..b96ed8532d383 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs @@ -19,10 +19,10 @@ public static void NullArgs_ThrowsArgumentNullException() AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, null)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, -1)); - AssertExtensions.Throws("encoding", () => new StreamReader("", (Encoding)null)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, null)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, -1)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", (Encoding)null)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true, null)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true, -1)); AssertExtensions.Throws("options", () => new StreamReader("path", (FileStreamOptions)null)); AssertExtensions.Throws("options", () => new StreamReader("path", Encoding.UTF8, true, null)); @@ -32,12 +32,12 @@ public static void NullArgs_ThrowsArgumentNullException() public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception - AssertExtensions.Throws(null, () => new StreamReader("")); - AssertExtensions.Throws(null, () => new StreamReader("", new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8)); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true)); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, -1)); + AssertExtensions.Throws("path", () => new StreamReader("")); + AssertExtensions.Throws("path", () => new StreamReader("", new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8)); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true)); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true, new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true, -1)); } [Fact] diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs index 4a2b91f8862b5..fccc269868ed7 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs @@ -110,6 +110,44 @@ public async Task ReadToEndAsync() Assert.Equal(5000, result.Length); } + [Fact] + public async Task ReadToEndAsync_WithCancellationToken() + { + using var sw = new StreamReader(GetLargeStream()); + var result = await sw.ReadToEndAsync(default); + + Assert.Equal(5000, result.Length); + } + + [Fact] + public async Task ReadToEndAsync_WithCanceledCancellationToken() + { + using var sw = new StreamReader(GetLargeStream()); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await sw.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")] + public async Task ReadToEndAsync_WithCancellation() + { + string path = GetTestFilePath(); + + // create large (~100MB) file + File.WriteAllLines(path, Enumerable.Repeat("A very large file used for testing StreamReader cancellation. 0123456789012345678901234567890123456789.", 1_000_000)); + + using StreamReader reader = File.OpenText(path); + using CancellationTokenSource cts = new (TimeSpan.FromMilliseconds(50)); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await reader.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + [Fact] public void GetBaseStream() { @@ -301,6 +339,27 @@ public void VanillaReadLines2() Assert.Equal(valueString.Substring(1, valueString.IndexOf('\r') - 1), data); } + [Fact] + public async Task VanillaReadLineAsync() + { + var baseInfo = GetCharArrayStream(); + var sr = baseInfo.Item2; + + string valueString = new string(baseInfo.Item1); + + var data = await sr.ReadLineAsync(); + Assert.Equal(valueString.Substring(0, valueString.IndexOf('\r')), data); + + data = await sr.ReadLineAsync(default); + Assert.Equal(valueString.Substring(valueString.IndexOf('\r') + 1, 3), data); + + data = await sr.ReadLineAsync(); + Assert.Equal(valueString.Substring(valueString.IndexOf('\n') + 1, 2), data); + + data = await sr.ReadLineAsync(default); + Assert.Equal((valueString.Substring(valueString.LastIndexOf('\n') + 1)), data); + } + [Fact] public async Task ContinuousNewLinesAndTabsAsync() { diff --git a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs index 841ff591aeff2..6900fb973843b 100644 --- a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -22,21 +22,18 @@ public static void NullArgs_ThrowsArgumentNullException() AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", null, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null, -1)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", null, null)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null, -1)); } [Fact] public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception - AssertExtensions.Throws(null, () => new StreamWriter("")); - AssertExtensions.Throws(null, () => new StreamWriter("", new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamWriter("", true)); - AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8)); - AssertExtensions.Throws(null, () => new StreamWriter("", Encoding.UTF8, new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8, -1)); + AssertExtensions.Throws("path", () => new StreamWriter("")); + AssertExtensions.Throws("path", () => new StreamWriter("", new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamWriter("", true)); + AssertExtensions.Throws("path", () => new StreamWriter("", true, Encoding.UTF8)); + AssertExtensions.Throws("path", () => new StreamWriter("", Encoding.UTF8, new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamWriter("", true, Encoding.UTF8, -1)); } [Fact] diff --git a/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs b/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs index 9e500923164f3..3c4446f07f47a 100644 --- a/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs +++ b/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs @@ -68,6 +68,23 @@ public static void ReadLine() } } + [Fact] + public static async Task ReadLineAsync() + { + string str1 = "Hello\0\t\v \\ World"; + string str2 = str1 + Environment.NewLine + str1; + + using (StringReader sr = new StringReader(str1)) + { + Assert.Equal(str1, await sr.ReadLineAsync()); + } + using (StringReader sr = new StringReader(str2)) + { + Assert.Equal(str1, await sr.ReadLineAsync(default)); + Assert.Equal(str1, await sr.ReadLineAsync(default)); + } + } + [Fact] public static void ReadPseudoRandomString() { @@ -155,6 +172,14 @@ public static void ReadToEndPseudoRandom() { Assert.Equal(str1, sr.ReadToEnd()); } + [Fact] + public static async Task ReadToEndAsyncString() + { + string str1 = "Hello\0\t\v \\ World"; + StringReader sr = new StringReader(str1); + Assert.Equal(str1, await sr.ReadToEndAsync(default)); + } + [Fact] public static void Closed_DisposedExceptions() { @@ -278,6 +303,8 @@ public async Task Precanceled_ThrowsException() await Assert.ThrowsAnyAsync(() => reader.ReadAsync(Memory.Empty, new CancellationToken(true)).AsTask()); await Assert.ThrowsAnyAsync(() => reader.ReadBlockAsync(Memory.Empty, new CancellationToken(true)).AsTask()); + await Assert.ThrowsAnyAsync(() => reader.ReadLineAsync(new CancellationToken(true)).AsTask()); + await Assert.ThrowsAnyAsync(() => reader.ReadToEndAsync(new CancellationToken(true))); } private static void ValidateDisposedExceptions(StringReader sr) diff --git a/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs b/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs index e6ba6d818f286..48f83d7108e53 100644 --- a/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs +++ b/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Threading; using System.Threading.Tasks; using Xunit; @@ -54,6 +55,26 @@ public async Task ReadToEndAsync() } } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public async Task ReadToEndAsync_WithCancellationToken() + { + using var tr = new CharArrayTextReader(TestDataProvider.LargeData); + var result = await tr.ReadToEndAsync(default); + Assert.Equal(5000, result.Length); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public async Task ReadToEndAsync_WithCanceledCancellationToken() + { + using var tr = new CharArrayTextReader(TestDataProvider.LargeData); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await tr.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + [Fact] public void TestRead() { diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs index 8125fc9ac1159..e481185ffa57a 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs @@ -20,7 +20,7 @@ public static Exception Unreachable get { Debug.Fail("Unreachable"); - return new InvalidOperationException("Code supposed to be unreachable"); + return new UnreachableException(); } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs index d078d82a597f4..f42254df42dd3 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs @@ -44,7 +44,7 @@ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Index}: {(IsBoxed ? "boxed" : null)} {(InClosure ? "in closure" : null)}"); } - internal readonly struct LocalDefinition + internal readonly struct LocalDefinition : IEquatable { internal LocalDefinition(int localIndex, ParameterExpression parameter) { @@ -53,27 +53,14 @@ internal LocalDefinition(int localIndex, ParameterExpression parameter) } public int Index { get; } + public ParameterExpression Parameter { get; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is LocalDefinition) - { - LocalDefinition other = (LocalDefinition)obj; - return other.Index == Index && other.Parameter == Parameter; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is LocalDefinition other && Equals(other); - return false; - } + public bool Equals(LocalDefinition other) => other.Index == Index && other.Parameter == Parameter; - public override int GetHashCode() - { - if (Parameter == null) - { - return 0; - } - return Parameter.GetHashCode() ^ Index.GetHashCode(); - } + public override int GetHashCode() => Parameter is null ? 0 : Parameter.GetHashCode() ^ Index.GetHashCode(); } internal sealed class LocalVariables diff --git a/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs b/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs index 40e794a5f6935..ac7715a193c65 100644 --- a/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs +++ b/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs @@ -1402,7 +1402,7 @@ public void CanReturnAnythingFromExplicitVoidCatch(bool useInterpreter) [Fact] public void CatchesMustReturnVoidWithVoidBody() { - Assert.Throws(null, () => + AssertExtensions.Throws(null, () => Expression.TryCatch( Expression.Empty(), Expression.Catch(typeof(InvocationExpression), Expression.Constant("hello")), diff --git a/src/libraries/System.Management/tests/System/Management/ManagementObjectTests.cs b/src/libraries/System.Management/tests/System/Management/ManagementObjectTests.cs index 4c349613a352f..15f0f6b48f6e9 100644 --- a/src/libraries/System.Management/tests/System/Management/ManagementObjectTests.cs +++ b/src/libraries/System.Management/tests/System/Management/ManagementObjectTests.cs @@ -5,6 +5,7 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using Xunit; +using Xunit.Sdk; namespace System.Management.Tests { @@ -64,28 +65,33 @@ public void Set_Property_Win32_ComputerSystem() [OuterLoop] public void Invoke_Instance_And_Static_Method_Win32_Process() { - var processClass = new ManagementClass("Win32_Process"); - object[] methodArgs = { "notepad.exe", null, null, 0 }; + // Retries are sometimes necessary as underlying API call can return + // ERROR_NOT_READY or occasionally ERROR_INVALID_BLOCK or ERROR_NOT_ENOUGH_MEMORY + RetryHelper.Execute(() => + { + var processClass = new ManagementClass("Win32_Process"); + object[] methodArgs = { "notepad.exe", null, null, 0 }; - object resultObj = processClass.InvokeMethod("Create", methodArgs); + object resultObj = processClass.InvokeMethod("Create", methodArgs); - var resultCode = (uint)resultObj; - Assert.Equal(0u, resultCode); + var resultCode = (uint)resultObj; + Assert.Equal(0u, resultCode); - var processId = (uint)methodArgs[3]; - Assert.True(0u != processId, $"Unexpected process ID: {processId}"); + var processId = (uint)methodArgs[3]; + Assert.True(0u != processId, $"Unexpected process ID: {processId}"); - using (Process targetProcess = Process.GetProcessById((int)processId)) - using (var process = new ManagementObject($"Win32_Process.Handle=\"{processId}\"")) - { - Assert.False(targetProcess.HasExited); + using (Process targetProcess = Process.GetProcessById((int)processId)) + using (var process = new ManagementObject($"Win32_Process.Handle=\"{processId}\"")) + { + Assert.False(targetProcess.HasExited); - resultObj = process.InvokeMethod("Terminate", new object[] { 0 }); - resultCode = (uint)resultObj; - Assert.Equal(0u, resultCode); + resultObj = process.InvokeMethod("Terminate", new object[] { 0 }); + resultCode = (uint)resultObj; + Assert.Equal(0u, resultCode); - Assert.True(targetProcess.HasExited); - } + Assert.True(targetProcess.HasExited); + } + }, maxAttempts: 10, retryWhen: e => e is XunitException); } [ConditionalFact(typeof(WmiTestHelper), nameof(WmiTestHelper.IsWmiSupported))] diff --git a/src/libraries/System.Memory/src/Resources/Strings.resx b/src/libraries/System.Memory/src/Resources/Strings.resx index 3734871f888da..6a69c1128e152 100644 --- a/src/libraries/System.Memory/src/Resources/Strings.resx +++ b/src/libraries/System.Memory/src/Resources/Strings.resx @@ -141,9 +141,6 @@ End position was not reached during enumeration. - - Unexpected segment type. - Cannot advance past the end of the buffer, which has a size of {0}. diff --git a/src/libraries/System.Memory/tests/MemoryMarshal/AsReadOnlyRef.cs b/src/libraries/System.Memory/tests/MemoryMarshal/AsReadOnlyRef.cs index 1a654bdff8d20..e48790231b288 100644 --- a/src/libraries/System.Memory/tests/MemoryMarshal/AsReadOnlyRef.cs +++ b/src/libraries/System.Memory/tests/MemoryMarshal/AsReadOnlyRef.cs @@ -22,7 +22,7 @@ public static void AsReadOnlyRef() Array.Fill(array, 0x42); ref readonly TestHelpers.TestStructExplicit asStruct = ref MemoryMarshal.AsRef(new ReadOnlySpan(array)); - Assert.Equal(asStruct.UI1, (uint)0x42424242); + Assert.Equal((uint)0x42424242, asStruct.UI1); } [Fact] diff --git a/src/libraries/System.Memory/tests/MemoryMarshal/AsRef.cs b/src/libraries/System.Memory/tests/MemoryMarshal/AsRef.cs index 39d4cace81035..a51b41051957c 100644 --- a/src/libraries/System.Memory/tests/MemoryMarshal/AsRef.cs +++ b/src/libraries/System.Memory/tests/MemoryMarshal/AsRef.cs @@ -22,7 +22,7 @@ public static void AsRef() Array.Fill(array, 0x42); ref TestHelpers.TestStructExplicit asStruct = ref MemoryMarshal.AsRef(new Span(array)); - Assert.Equal(asStruct.UI1, (uint)0x42424242); + Assert.Equal((uint)0x42424242, asStruct.UI1); } [Fact] diff --git a/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs b/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs index 33250569da2da..1a9027d0fc744 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -115,5 +117,104 @@ public static void IndexOfSequenceLengthOneValueJustPasttVeryEnd_Byte() int index = span.IndexOf(value); Assert.Equal(-1, index); } + + public static IEnumerable IndexOfSubSeqData_Byte() + { + // searchSpace, value, expected IndexOf value, expected LastIndexOf value + yield return new object[] { new byte[]{0,0,0,0,0},new byte[]{0,0,0}, 0, 2}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0},new byte[]{0,71,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0},new byte[]{0,0,0}, 0, 7}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,71,0,1,0}, 10, 10}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,71,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,1,0,0,0}, 12, 12}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,1,0,0,0}, 11, 11}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,1,0,0,0}, 6, 6}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0}, 0, 44}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0}, 0, 43}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0}, 7, 42}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0}, 7, 41}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0}, 7, 11}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0}, 7, 10}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0}, 7, 9}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0}, 7, 7}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0}, 5, 48}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,0}, 44, 44}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0,0,0}, 5, 19}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0}, 7, 11}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,1,0,0,1,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,1,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,1,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,1,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{159,133,159,133,159,133}, 0, 22}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{159,133,255,159,133}, -1, -1}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,160,86,160,86,160,86,160,86,160,80},new byte[]{160,86,160,86,160,86,160,86,160,80}, 40, 40}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,160,86,160,86,160,86,160,86,160,80,160,80,160,80,160,80,160,80,160,80,160,80,160,86,160,86,160,86,160,86},new byte[]{160,86,160,86,160,86,160,86}, 40, 62}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{0,0,0,1}, -1, -1}; + yield return new object[] { new byte[]{255,160,82,159,134,159,127,255,159,141,160,85,160,82,160,88,255,159,141,159,127,159,134,255,160,88,160,85,160,82,159,141,159,127,159,134,160,88,160,85,160,82,159,141,255,159,127,159,134,160,88,160,85,160,82,159,141,159,127,159,134,160,88,159,141,160,85,255,160,82,159,134,159,141,159,134,160,85,160,82,159,141,159,127,159,134,160,82,159,141,160,85,159,134,255,160,88,159,127,160,82,160,85,159,134,255,159,141,159,127,159,134,160,85,159,141},new byte[]{255,159,141,159,127,159,134,255}, 16, 16}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,49}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49},new byte[]{49,49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49,50},new byte[]{49,49,49}, 29, 29}; + yield return new object[] { new byte[]{49,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,49,49}, 0, 1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49,50},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{49,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,49,48,48}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,48,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{160,80,48,160,80,160,80}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 15}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 17}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 18, 32}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,49,49,49,49,49,49,49,49,49,49,49,49}, 20, 20}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71},new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71}, 60, 60}; + yield return new object[] { new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,71,71,71,71,71,71,71,71,71,71,71,71,71,71},new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71}, 0, 0}; + } + + [Theory] + [MemberData(nameof(IndexOfSubSeqData_Byte))] + public static void ValueStartsAndEndsWithTheSameBytes(byte[] searchSpace, byte[] value, int expectedIndexOfValue, int expectedLastIndexOfValue) + { + Assert.Equal(expectedIndexOfValue, searchSpace.AsSpan().IndexOf(value)); + Assert.Equal(expectedLastIndexOfValue, searchSpace.AsSpan().LastIndexOf(value)); + } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs b/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs index bda626153a5d0..b341a79c9b1f3 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -115,5 +117,104 @@ public static void IndexOfSequenceLengthOneValueJustPasttVeryEnd_Char() int index = span.IndexOf(value); Assert.Equal(-1, index); } + + public static IEnumerable IndexOfSubSeqData_Char() + { + // searchSpace, value, expected IndexOf value, expected LastIndexOf value + yield return new object[] { "11111", "111", 0, 2 }; + yield return new object[] { "1111111111", "1x1", -1, -1 }; + yield return new object[] { "1111111111", "111", 0, 7 }; + yield return new object[] { "11111111111x12111", "1x121", 10, 10 }; + yield return new object[] { "11111111111x12111", "11121", -1, -1 }; + yield return new object[] { "1111111111x121111", "11121", -1, -1 }; + yield return new object[] { "11111x12111111111", "11121", -1, -1 }; + yield return new object[] { "11111111111x12111", "1x211", -1, -1 }; + yield return new object[] { "11111111111x12111", "11211", -1, -1 }; + yield return new object[] { "1111111111x121111", "11211", -1, -1 }; + yield return new object[] { "11111x12111111111", "11211", -1, -1 }; + yield return new object[] { "11111111111x12111", "12111", 12, 12 }; + yield return new object[] { "1111111111x121111", "12111", 11, 11 }; + yield return new object[] { "11111x12111111111", "12111", 6, 6 }; + yield return new object[] { "1111x1211111111111x12", "11121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "11121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1211211", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111", 0, 44 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111", 0, 43 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111", 7, 42 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111", 7, 41 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111", 7, 11 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111", 7, 10 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111", 7, 9 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111", 7, 7 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1211", 5, 48 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11121", 44, 44 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "121111", 5, 19 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "12111211", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111", 7, 11 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1121121111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111211111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111211111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1121111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11122111112111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111211111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111211111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111211111121111111", -1, -1 }; + yield return new object[] { "жжжжжжжжжжжжжж", "жжж", 0, 11 }; + yield return new object[] { "жжжжжжжжжжжжжжжжжжжжжжжжжжжж", "ж0ж", -1, -1 }; + yield return new object[] { "жжжжжаааааааааааааааччччс", "ччччс", 20, 20 }; + yield return new object[] { "жжжжжаааааааааааааааччччсссссссчччч", "чччч", 20, 31 }; + yield return new object[] { "жжжжжжжжжжжжжжжжжжжжжжжжжжжж", "1112", -1, -1 }; + yield return new object[] { "0уза0оцущ0оаз0щцуоазщцуо0азщцуоазщоц0узозцуоазуоцз0щауцз0оазцо", "0оаз0", 9, 9 }; + yield return new object[] { "abababababababababababababababbc", "bb", 29, 29 }; + yield return new object[] { "abababababababababababababababb", "bb", 29, 29 }; + yield return new object[] { "abababababababababababababababbc", "bb", 29, 29 }; + yield return new object[] { "babababababababababababababababc", "bb", -1, -1 }; + yield return new object[] { "abababababababababababababababbb", "bbb", 29, 29 }; + yield return new object[] { "abababababababababababababababbbc", "bbb", 29, 29 }; + yield return new object[] { "bbbbabababababababababababababababc", "bbb", 0, 1 }; + yield return new object[] { "abababababababababababababababbc", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababb", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababbc", "aa", -1, -1 }; + yield return new object[] { "babababababababababababababababc", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababbb", "aaa", -1, -1 }; + yield return new object[] { "abababababababababababababababbbc", "aaa", -1, -1 }; + yield return new object[] { "bbbbabababababababababababababababc", "aaa", -1, -1 }; + yield return new object[] { "ababababababababababababababababbc", "abaa", -1, -1 }; + yield return new object[] { "babbbabababababababababababababababc", "babb", 0, 0 }; + yield return new object[] { "babbbabababababababababababababababc", "сaсс", -1, -1 }; + yield return new object[] { "babbbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 15 }; + yield return new object[] { "babbbbbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 17 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 18, 32 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "bbbbbbbbbbbbb", 20, 20 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbb", -1, -1 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbb", 0, 0 }; + yield return new object[] { "xxxxxxxxxxxxxxbabbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxx", 60, 60 }; + yield return new object[] { "xxxxxxxxxxxxxxxbabbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxx", 0, 0 }; + } + + [Theory] + [MemberData(nameof(IndexOfSubSeqData_Char))] + public static void ValueStartsAndEndsWithTheSameChars(string searchSpace, string value, int expectedIndexOfValue, int expectedLastIndexOfValue) + { + Assert.Equal(expectedIndexOfValue, searchSpace.AsSpan().IndexOf(value)); + Assert.Equal(expectedLastIndexOfValue, searchSpace.AsSpan().LastIndexOf(value)); + } } } diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 7464b6aa14086..9e9afe1491426 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -123,9 +123,6 @@ The format of the HTTP method is invalid. - - The HTTP method '{0}' is not supported on this platform. - The reason phrase must not contain new-line characters. @@ -231,9 +228,6 @@ Buffering more than {0} bytes is not supported. - - The value '{0}' is not supported for property '{1}'. - The read operation failed, see inner exception. @@ -297,9 +291,6 @@ Access to the path '{0}' is denied. - - The stream does not support concurrent read operations. - The username for a credential object cannot be null or empty. @@ -357,9 +348,6 @@ Received an HTTP/2 pseudo-header as a trailing header. - - The handler was disposed of while active operations were in progress. - The buffer was not long enough. @@ -381,12 +369,6 @@ Cannot access a closed stream. - - Using this feature requires Windows 10 Version 1607. - - - Client certificate was not found in the personal (\"MY\") certificate store. In UWP, client certificates are only supported if they have been added to that certificate store. - Only the 'http', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies. @@ -516,9 +498,6 @@ End of headers reached with incomplete token. - - Failed to HPACK encode the headers. - The HTTP headers length exceeded the set limit of {0} bytes. @@ -528,9 +507,6 @@ The HTTP/3 server sent invalid data on the connection. HTTP/3 error code '{0}' (0x{1}). - - The HTTP/3 server sent invalid data on the stream. HTTP/3 error code '{0}' (0x{1}). - The server is unable to process the request using the current HTTP version and indicates the request should be retried on an older HTTP version. @@ -549,9 +525,6 @@ Connection aborted by peer ({0}). - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. @@ -570,9 +543,6 @@ Requesting HTTP version {0} with version policy {1} while unable to establish HTTP/{2} connection. - - Requesting HTTP version {0} with version policy {1} while server returned HTTP/1.1 in ALPN. - Requesting HTTP version {0} with version policy {1} while server offers only version fallback. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs index 8d022091ea396..b03247fbfc3d7 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs @@ -148,10 +148,10 @@ protected internal override async Task SendAsync(HttpReques { throw new ArgumentNullException(nameof(request), SR.net_http_handler_norequest); } - + CancellationTokenRegistration? abortRegistration = null; try { - var requestObject = new JSObject(); + using var requestObject = new JSObject(); if (request.Options.TryGetValue(FetchOptions, out IDictionary? fetchOptions)) { @@ -221,44 +221,39 @@ protected internal override async Task SendAsync(HttpReques } - WasmHttpReadStream? wasmHttpReadStream = null; - JSObject abortController = new HostObject("AbortController"); - JSObject signal = (JSObject)abortController.GetObjectProperty("signal"); + using JSObject signal = (JSObject)abortController.GetObjectProperty("signal"); requestObject.SetObjectProperty("signal", signal); - signal.Dispose(); - CancellationTokenSource abortCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - CancellationTokenRegistration abortRegistration = abortCts.Token.Register((Action)(() => + abortRegistration = cancellationToken.Register(() => { - if (abortController.JSHandle != -1) + if (!abortController.IsDisposed) { abortController.Invoke("abort"); abortController?.Dispose(); } - wasmHttpReadStream?.Dispose(); - abortCts.Dispose(); - })); + }); - var args = new System.Runtime.InteropServices.JavaScript.Array(); + using var args = new System.Runtime.InteropServices.JavaScript.Array(); if (request.RequestUri != null) { args.Push(request.RequestUri.ToString()); args.Push(requestObject); } - requestObject.Dispose(); - var response = s_fetch?.Invoke("apply", s_window, args) as Task; - args.Dispose(); - if (response == null) + var responseTask = s_fetch?.Invoke("apply", s_window, args) as Task; + if (responseTask == null) throw new Exception(SR.net_http_marshalling_response_promise_from_fetch); - JSObject t = (JSObject)await response.ConfigureAwait(continueOnCapturedContext: true); + cancellationToken.ThrowIfCancellationRequested(); - var status = new WasmFetchResponse(t, abortController, abortCts, abortRegistration); - HttpResponseMessage httpResponse = new HttpResponseMessage((HttpStatusCode)status.Status); - httpResponse.RequestMessage = request; + var fetchResponseJs = (JSObject)await responseTask.ConfigureAwait(continueOnCapturedContext: true); + + var fetchResponse = new WasmFetchResponse(fetchResponseJs, abortController, abortRegistration.Value); + abortRegistration = null; + var responseMessage = new HttpResponseMessage((HttpStatusCode)fetchResponse.Status); + responseMessage.RequestMessage = request; // Here we will set the ReasonPhrase so that it can be evaluated later. // We do not have a status code but this will signal some type of what happened @@ -267,9 +262,9 @@ protected internal override async Task SendAsync(HttpReques // https://developer.mozilla.org/en-US/docs/Web/API/Response/type // opaqueredirect: The fetch request was made with redirect: "manual". // The Response's status is 0, headers are empty, body is null and trailer is empty. - if (status.ResponseType == "opaqueredirect") + if (fetchResponse.ResponseType == "opaqueredirect") { - httpResponse.SetReasonPhraseWithoutValidation(status.ResponseType); + responseMessage.SetReasonPhraseWithoutValidation(fetchResponse.ResponseType); } bool streamingEnabled = false; @@ -278,9 +273,9 @@ protected internal override async Task SendAsync(HttpReques request.Options.TryGetValue(EnableStreamingResponse, out streamingEnabled); } - httpResponse.Content = streamingEnabled - ? new StreamContent(wasmHttpReadStream = new WasmHttpReadStream(status)) - : (HttpContent)new BrowserHttpContent(status); + responseMessage.Content = streamingEnabled + ? new StreamContent(new WasmHttpReadStream(fetchResponse)) + : new BrowserHttpContent(fetchResponse); // Fill the response headers // CORS will only allow access to certain headers. @@ -290,7 +285,7 @@ protected internal override async Task SendAsync(HttpReques // View more information https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types // // Note: Some of the headers may not even be valid header types in .NET thus we use TryAddWithoutValidation - using (JSObject respHeaders = status.Headers) + using (JSObject respHeaders = fetchResponse.Headers) { if (respHeaders != null) { @@ -306,8 +301,8 @@ protected internal override async Task SendAsync(HttpReques { var name = (string)resultValue[0]; var value = (string)resultValue[1]; - if (!httpResponse.Headers.TryAddWithoutValidation(name, value)) - httpResponse.Content.Headers.TryAddWithoutValidation(name, value); + if (!responseMessage.Headers.TryAddWithoutValidation(name, value)) + responseMessage.Content.Headers.TryAddWithoutValidation(name, value); } nextResult?.Dispose(); nextResult = (JSObject)entriesIterator.Invoke("next"); @@ -320,7 +315,7 @@ protected internal override async Task SendAsync(HttpReques } } } - return httpResponse; + return responseMessage; } catch (OperationCanceledException oce) when (cancellationToken.IsCancellationRequested) @@ -331,6 +326,10 @@ protected internal override async Task SendAsync(HttpReques { throw TranslateJSException(jse, cancellationToken); } + finally + { + abortRegistration?.Dispose(); + } } private static Exception TranslateJSException(JSException jse, CancellationToken cancellationToken) @@ -350,15 +349,13 @@ private sealed class WasmFetchResponse : IDisposable { private readonly JSObject _fetchResponse; private readonly JSObject _abortController; - private readonly CancellationTokenSource _abortCts; private readonly CancellationTokenRegistration _abortRegistration; private bool _isDisposed; - public WasmFetchResponse(JSObject fetchResponse, JSObject abortController, CancellationTokenSource abortCts, CancellationTokenRegistration abortRegistration) + public WasmFetchResponse(JSObject fetchResponse, JSObject abortController, CancellationTokenRegistration abortRegistration) { _fetchResponse = fetchResponse ?? throw new ArgumentNullException(nameof(fetchResponse)); _abortController = abortController ?? throw new ArgumentNullException(nameof(abortController)); - _abortCts = abortCts; _abortRegistration = abortRegistration; } @@ -383,10 +380,13 @@ public void Dispose() _isDisposed = true; - _abortCts.Dispose(); _abortRegistration.Dispose(); _fetchResponse?.Dispose(); + if (_abortController != null && !_abortController.IsDisposed) + { + _abortController.Invoke("abort"); + } _abortController?.Dispose(); } } @@ -460,15 +460,15 @@ protected override void Dispose(bool disposing) private sealed class WasmHttpReadStream : Stream { - private WasmFetchResponse? _status; + private WasmFetchResponse? _fetchResponse; private JSObject? _reader; private byte[]? _bufferedBytes; private int _position; - public WasmHttpReadStream(WasmFetchResponse status) + public WasmHttpReadStream(WasmFetchResponse fetchResponse) { - _status = status; + _fetchResponse = fetchResponse; } public override bool CanRead => true; @@ -489,17 +489,19 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) { + CancellationHelper.ThrowIfCancellationRequested(cancellationToken); + if (_reader == null) { // If we've read everything, then _reader and _status will be null - if (_status == null) + if (_fetchResponse == null) { return 0; } try { - using (JSObject body = _status.Body) + using (JSObject body = _fetchResponse.Body) { _reader = (JSObject)body.Invoke("getReader"); } @@ -514,6 +516,11 @@ public override async ValueTask ReadAsync(Memory buffer, Cancellation } } + using var abortRegistration = cancellationToken.Register(() => + { + _reader.Invoke("cancel"); + }); + if (_bufferedBytes != null && _position < _bufferedBytes.Length) { return ReadBuffered(); @@ -524,13 +531,19 @@ public override async ValueTask ReadAsync(Memory buffer, Cancellation var t = (Task)_reader.Invoke("read"); using (var read = (JSObject)await t.ConfigureAwait(continueOnCapturedContext: true)) { + if (cancellationToken.IsCancellationRequested) + { + _reader.Invoke("cancel"); + throw CancellationHelper.CreateOperationCanceledException(null, cancellationToken); + } + if ((bool)read.GetObjectProperty("done")) { _reader.Dispose(); _reader = null; - _status?.Dispose(); - _status = null; + _fetchResponse?.Dispose(); + _fetchResponse = null; return 0; } @@ -569,7 +582,7 @@ int ReadBuffered() protected override void Dispose(bool disposing) { _reader?.Dispose(); - _status?.Dispose(); + _fetchResponse?.Dispose(); } public override void Flush() diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index ee53b9e626c75..3eae142edcd4c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -5,11 +5,28 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; namespace System.Net.Http.Headers { + /// + /// Key/value pairs of headers. The value is either a raw or a . + /// We're using a custom type instead of because we need ref access to fields. + /// + internal struct HeaderEntry + { + public HeaderDescriptor Key; + public object Value; + + public HeaderEntry(HeaderDescriptor key, object value) + { + Key = key; + Value = value; + } + } + public abstract class HttpHeaders : IEnumerable>> { // This type is used to store a collection of headers in 'headerStore': @@ -32,8 +49,9 @@ public abstract class HttpHeaders : IEnumerableKey/value pairs of headers. The value is either a raw or a . - private Dictionary? _headerStore; + /// Either a array or a Dictionary<, > + private object? _headerStore; + private int _count; private readonly HttpHeaderType _allowedHeaderTypes; private readonly HttpHeaderType _treatAsCustomHeaderTypes; @@ -52,8 +70,6 @@ internal HttpHeaders(HttpHeaderType allowedHeaderTypes, HttpHeaderType treatAsCu _treatAsCustomHeaderTypes = treatAsCustomHeaderTypes & ~HttpHeaderType.NonTrailing; } - internal Dictionary? HeaderStore => _headerStore; - /// Gets a view of the contents of this headers collection that does not parse nor validate the data upon access. public HttpHeadersNonValidated NonValidated => new HttpHeadersNonValidated(this); @@ -71,7 +87,8 @@ internal void Add(HeaderDescriptor descriptor, string? value) // it to the store if we added at least one value. if (addToStore && (info.ParsedValue != null)) { - AddHeaderToStore(descriptor, info); + Debug.Assert(!ContainsKey(descriptor)); + AddEntryToStore(new HeaderEntry(descriptor, info)); } } @@ -104,7 +121,8 @@ internal void Add(HeaderDescriptor descriptor, IEnumerable values) // However, if all values for a _new_ header were invalid, then don't add the header. if (addToStore && (info.ParsedValue != null)) { - AddHeaderToStore(descriptor, info); + Debug.Assert(!ContainsKey(descriptor)); + AddEntryToStore(new HeaderEntry(descriptor, info)); } } } @@ -120,29 +138,24 @@ internal bool TryAddWithoutValidation(HeaderDescriptor descriptor, string? value // values, e.g. adding two null-strings (or empty, or whitespace-only) results in "My-Header: ,". value ??= string.Empty; - // Ensure the header store dictionary has been created. - _headerStore ??= new Dictionary(); + ref object? storeValueRef = ref GetValueRefOrAddDefault(descriptor); + object? currentValue = storeValueRef; - if (_headerStore.TryGetValue(descriptor, out object? currentValue)) + if (currentValue is null) { - if (currentValue is HeaderStoreItemInfo info) - { - // The header store already contained a HeaderStoreItemInfo, so add to it. - AddRawValue(info, value); - } - else + storeValueRef = value; + } + else + { + if (currentValue is not HeaderStoreItemInfo info) { // The header store contained a single raw string value, so promote it // to being a HeaderStoreItemInfo and add to it. Debug.Assert(currentValue is string); - _headerStore[descriptor] = info = new HeaderStoreItemInfo() { RawValue = currentValue }; - AddRawValue(info, value); + storeValueRef = info = new HeaderStoreItemInfo() { RawValue = currentValue }; } - } - else - { - // The header store did not contain the header. Add the raw string. - _headerStore.Add(descriptor, value); + + AddRawValue(info, value); } return true; @@ -159,28 +172,33 @@ internal bool TryAddWithoutValidation(HeaderDescriptor descriptor, IEnumerable enumerator = values.GetEnumerator()) + using IEnumerator enumerator = values.GetEnumerator(); + if (enumerator.MoveNext()) { + TryAddWithoutValidation(descriptor, enumerator.Current); if (enumerator.MoveNext()) { - TryAddWithoutValidation(descriptor, enumerator.Current); - if (enumerator.MoveNext()) + ref object? storeValueRef = ref GetValueRefOrAddDefault(descriptor); + Debug.Assert(storeValueRef is not null); + + object value = storeValueRef; + if (value is not HeaderStoreItemInfo info) { - HeaderStoreItemInfo info = GetOrCreateHeaderInfo(descriptor, parseRawValues: false); - do - { - AddRawValue(info, enumerator.Current ?? string.Empty); - } - while (enumerator.MoveNext()); + Debug.Assert(value is string); + storeValueRef = info = new HeaderStoreItemInfo { RawValue = value }; } + + do + { + AddRawValue(info, enumerator.Current ?? string.Empty); + } + while (enumerator.MoveNext()); } } return true; } - public void Clear() => _headerStore?.Clear(); - public IEnumerable GetValues(string name) => GetValues(GetHeaderDescriptor(name)); internal IEnumerable GetValues(HeaderDescriptor descriptor) @@ -206,7 +224,7 @@ public bool TryGetValues(string name, [NotNullWhen(true)] out IEnumerable? values) { - if (_headerStore != null && TryGetAndParseHeaderInfo(descriptor, out HeaderStoreItemInfo? info)) + if (TryGetAndParseHeaderInfo(descriptor, out HeaderStoreItemInfo? info)) { values = GetStoreValuesAsStringArray(descriptor, info); return true; @@ -223,7 +241,7 @@ internal bool Contains(HeaderDescriptor descriptor) // We can't just call headerStore.ContainsKey() since after parsing the value the header may not exist // anymore (if the value contains newline chars, we remove the header). So try to parse the // header value. - return _headerStore != null && TryGetAndParseHeaderInfo(descriptor, out _); + return TryGetAndParseHeaderInfo(descriptor, out _); } public override string ToString() @@ -235,35 +253,34 @@ public override string ToString() var vsb = new ValueStringBuilder(stackalloc char[512]); - if (_headerStore is Dictionary headerStore) + foreach (HeaderEntry entry in GetEntries()) { - foreach (KeyValuePair header in headerStore) - { - vsb.Append(header.Key.Name); - vsb.Append(": "); + vsb.Append(entry.Key.Name); + vsb.Append(": "); - GetStoreValuesAsStringOrStringArray(header.Key, header.Value, out string? singleValue, out string[]? multiValue); - Debug.Assert(singleValue is not null ^ multiValue is not null); + GetStoreValuesAsStringOrStringArray(entry.Key, entry.Value, out string? singleValue, out string[]? multiValue); + Debug.Assert(singleValue is not null ^ multiValue is not null); - if (singleValue is not null) - { - vsb.Append(singleValue); - } - else - { - // Note that if we get multiple values for a header that doesn't support multiple values, we'll - // just separate the values using a comma (default separator). - string? separator = header.Key.Parser is HttpHeaderParser parser && parser.SupportsMultipleValues ? parser.Separator : HttpHeaderParser.DefaultSeparator; + if (singleValue is not null) + { + vsb.Append(singleValue); + } + else + { + // Note that if we get multiple values for a header that doesn't support multiple values, we'll + // just separate the values using a comma (default separator). + string? separator = entry.Key.Parser is HttpHeaderParser parser && parser.SupportsMultipleValues ? parser.Separator : HttpHeaderParser.DefaultSeparator; - for (int i = 0; i < multiValue!.Length; i++) - { - if (i != 0) vsb.Append(separator); - vsb.Append(multiValue[i]); - } + Debug.Assert(multiValue is not null && multiValue.Length > 0); + vsb.Append(multiValue[0]); + for (int i = 1; i < multiValue.Length; i++) + { + vsb.Append(separator); + vsb.Append(multiValue[i]); } - - vsb.Append(Environment.NewLine); } + + vsb.Append(Environment.NewLine); } return vsb.ToString(); @@ -292,39 +309,57 @@ internal string GetHeaderString(HeaderDescriptor descriptor) #region IEnumerable>> Members - public IEnumerator>> GetEnumerator() => _headerStore != null && _headerStore.Count > 0 ? - GetEnumeratorCore() : - ((IEnumerable>>)Array.Empty>>()).GetEnumerator(); + public IEnumerator>> GetEnumerator() => _count == 0 ? + ((IEnumerable>>)Array.Empty>>()).GetEnumerator() : + GetEnumeratorCore(); private IEnumerator>> GetEnumeratorCore() { - foreach (KeyValuePair header in _headerStore!) + HeaderEntry[]? entries = GetEntriesArray(); + Debug.Assert(_count != 0 && entries is not null, "Caller should have validated the collection is not empty"); + + int count = _count; + for (int i = 0; i < count; i++) { - HeaderDescriptor descriptor = header.Key; - object value = header.Value; + HeaderEntry entry = entries[i]; - HeaderStoreItemInfo? info = value as HeaderStoreItemInfo; - if (info is null) + if (entry.Value is not HeaderStoreItemInfo info) { // To retain consistent semantics, we need to upgrade a raw string to a HeaderStoreItemInfo // during enumeration so that we can parse the raw value in order to a) return // the correct set of parsed values, and b) update the instance for subsequent enumerations // to reflect that parsing. - _headerStore[descriptor] = info = new HeaderStoreItemInfo() { RawValue = value }; + info = new HeaderStoreItemInfo() { RawValue = entry.Value }; + + if (EntriesAreLiveView) + { + entries[i].Value = info; + } + else + { + Debug.Assert(ContainsKey(entry.Key)); + ((Dictionary)_headerStore!)[entry.Key] = info; + } } // Make sure we parse all raw values before returning the result. Note that this has to be // done before we calculate the array length (next line): A raw value may contain a list of // values. - if (!ParseRawHeaderValues(descriptor, info, removeEmptyHeader: false)) + if (!ParseRawHeaderValues(entry.Key, info)) { - // We have an invalid header value (contains newline chars). Delete it. - _headerStore.Remove(descriptor); + // We saw an invalid header value (contains newline chars) and deleted it. + + // If the HeaderEntry[] we are enumerating is the live header store, the entries have shifted. + if (EntriesAreLiveView) + { + i--; + count--; + } } else { - string[] values = GetStoreValuesAsStringArray(descriptor, info); - yield return new KeyValuePair>(descriptor.Name, values); + string[] values = GetStoreValuesAsStringArray(entry.Key, info); + yield return new KeyValuePair>(entry.Key.Name, values); } } } @@ -342,7 +377,7 @@ internal void AddParsedValue(HeaderDescriptor descriptor, object value) Debug.Assert(value != null); Debug.Assert(descriptor.Parser != null, "Can't add parsed value if there is no parser available."); - HeaderStoreItemInfo info = GetOrCreateHeaderInfo(descriptor, parseRawValues: true); + HeaderStoreItemInfo info = GetOrCreateHeaderInfo(descriptor); // If the current header has only one value, we can't add another value. The strongly typed property // must not call AddParsedValue(), but SetParsedValue(). E.g. for headers like 'Date', 'Host'. @@ -358,7 +393,7 @@ internal void SetParsedValue(HeaderDescriptor descriptor, object value) // This method will first clear all values. This is used e.g. when setting the 'Date' or 'Host' header. // i.e. headers not supporting collections. - HeaderStoreItemInfo info = GetOrCreateHeaderInfo(descriptor, parseRawValues: true); + HeaderStoreItemInfo info = GetOrCreateHeaderInfo(descriptor); info.InvalidValue = null; info.ParsedValue = null; @@ -381,17 +416,10 @@ internal void SetOrRemoveParsedValue(HeaderDescriptor descriptor, object? value) public bool Remove(string name) => Remove(GetHeaderDescriptor(name)); - internal bool Remove(HeaderDescriptor descriptor) => _headerStore != null && _headerStore.Remove(descriptor); - internal bool RemoveParsedValue(HeaderDescriptor descriptor, object value) { Debug.Assert(value != null); - if (_headerStore == null) - { - return false; - } - // If we have a value for this header, then verify if we have a single value. If so, compare that // value with 'item'. If we have a list of values, then remove 'item' from the list. if (TryGetAndParseHeaderInfo(descriptor, out HeaderStoreItemInfo? info)) @@ -462,11 +490,6 @@ internal bool ContainsParsedValue(HeaderDescriptor descriptor, object value) { Debug.Assert(value != null); - if (_headerStore == null) - { - return false; - } - // If we have a value for this header, then verify if we have a single value. If so, compare that // value with 'item'. If we have a list of values, then compare each item in the list with 'item'. if (TryGetAndParseHeaderInfo(descriptor, out HeaderStoreItemInfo? info)) @@ -517,41 +540,58 @@ internal virtual void AddHeaders(HttpHeaders sourceHeaders) Debug.Assert(sourceHeaders != null); Debug.Assert(GetType() == sourceHeaders.GetType(), "Can only copy headers from an instance of the same type."); - Dictionary? sourceHeadersStore = sourceHeaders._headerStore; - if (sourceHeadersStore is null || sourceHeadersStore.Count == 0) + // Only add header values if they're not already set on the message. Note that we don't merge + // collections: If both the default headers and the message have set some values for a certain + // header, then we don't try to merge the values. + if (_count == 0 && sourceHeaders._headerStore is HeaderEntry[] sourceEntries) { - return; - } - - _headerStore ??= new Dictionary(); + // If the target collection is empty, we don't have to search for existing values + _count = sourceHeaders._count; + if (_headerStore is not HeaderEntry[] entries || entries.Length < _count) + { + entries = new HeaderEntry[sourceEntries.Length]; + _headerStore = entries; + } - foreach (KeyValuePair header in sourceHeadersStore) - { - // Only add header values if they're not already set on the message. Note that we don't merge - // collections: If both the default headers and the message have set some values for a certain - // header, then we don't try to merge the values. - if (!_headerStore.ContainsKey(header.Key)) + for (int i = 0; i < _count && i < sourceEntries.Length; i++) { - object sourceValue = header.Value; - if (sourceValue is HeaderStoreItemInfo info) + HeaderEntry entry = sourceEntries[i]; + if (entry.Value is HeaderStoreItemInfo info) { - AddHeaderInfo(header.Key, info); + entry.Value = CloneHeaderInfo(entry.Key, info); } - else + entries[i] = entry; + } + } + else + { + foreach (HeaderEntry entry in sourceHeaders.GetEntries()) + { + ref object? storeValueRef = ref GetValueRefOrAddDefault(entry.Key); + if (storeValueRef is null) { - Debug.Assert(sourceValue is string); - _headerStore.Add(header.Key, sourceValue); + object sourceValue = entry.Value; + if (sourceValue is HeaderStoreItemInfo info) + { + storeValueRef = CloneHeaderInfo(entry.Key, info); + } + else + { + Debug.Assert(sourceValue is string); + storeValueRef = sourceValue; + } } } } } - private void AddHeaderInfo(HeaderDescriptor descriptor, HeaderStoreItemInfo sourceInfo) + private HeaderStoreItemInfo CloneHeaderInfo(HeaderDescriptor descriptor, HeaderStoreItemInfo sourceInfo) { - HeaderStoreItemInfo destinationInfo = CreateAndAddHeaderToStore(descriptor); - - // Always copy raw values - destinationInfo.RawValue = CloneStringHeaderInfoValues(sourceInfo.RawValue); + var destinationInfo = new HeaderStoreItemInfo + { + // Always copy raw values + RawValue = CloneStringHeaderInfoValues(sourceInfo.RawValue) + }; if (descriptor.Parser == null) { @@ -585,6 +625,8 @@ private void AddHeaderInfo(HeaderDescriptor descriptor, HeaderStoreItemInfo sour } } } + + return destinationInfo; } private static void CloneAndAddValue(HeaderStoreItemInfo destinationInfo, object source) @@ -623,74 +665,54 @@ private static void CloneAndAddValue(HeaderStoreItemInfo destinationInfo, object } } - private HeaderStoreItemInfo GetOrCreateHeaderInfo(HeaderDescriptor descriptor, bool parseRawValues) + private HeaderStoreItemInfo GetOrCreateHeaderInfo(HeaderDescriptor descriptor) { - HeaderStoreItemInfo? result = null; - bool found; - if (parseRawValues) + if (TryGetAndParseHeaderInfo(descriptor, out HeaderStoreItemInfo? info)) { - found = TryGetAndParseHeaderInfo(descriptor, out result); + return info; } else { - found = TryGetHeaderValue(descriptor, out object? value); - if (found) - { - if (value is HeaderStoreItemInfo hsti) - { - result = hsti; - } - else - { - Debug.Assert(value is string); - _headerStore![descriptor] = result = new HeaderStoreItemInfo { RawValue = value }; - } - } - } - - if (!found) - { - result = CreateAndAddHeaderToStore(descriptor); + return CreateAndAddHeaderToStore(descriptor); } - - Debug.Assert(result != null); - return result; } private HeaderStoreItemInfo CreateAndAddHeaderToStore(HeaderDescriptor descriptor) { + Debug.Assert(!ContainsKey(descriptor)); + // If we don't have the header in the store yet, add it now. HeaderStoreItemInfo result = new HeaderStoreItemInfo(); // If the descriptor header type is in _treatAsCustomHeaderTypes, it must be converted to a custom header before calling this method Debug.Assert((descriptor.HeaderType & _treatAsCustomHeaderTypes) == 0); - AddHeaderToStore(descriptor, result); + AddEntryToStore(new HeaderEntry(descriptor, result)); return result; } - private void AddHeaderToStore(HeaderDescriptor descriptor, object value) - { - Debug.Assert(value is string || value is HeaderStoreItemInfo); - (_headerStore ??= new Dictionary()).Add(descriptor, value); - } - internal bool TryGetHeaderValue(HeaderDescriptor descriptor, [NotNullWhen(true)] out object? value) { - if (_headerStore == null) + ref object storeValueRef = ref GetValueRefOrNullRef(descriptor); + if (Unsafe.IsNullRef(ref storeValueRef)) { value = null; return false; } - - return _headerStore.TryGetValue(descriptor, out value); + else + { + value = storeValueRef; + return true; + } } private bool TryGetAndParseHeaderInfo(HeaderDescriptor key, [NotNullWhen(true)] out HeaderStoreItemInfo? info) { - if (TryGetHeaderValue(key, out object? value)) + ref object storeValueRef = ref GetValueRefOrNullRef(key); + if (!Unsafe.IsNullRef(ref storeValueRef)) { + object value = storeValueRef; if (value is HeaderStoreItemInfo hsi) { info = hsi; @@ -698,20 +720,21 @@ private bool TryGetAndParseHeaderInfo(HeaderDescriptor key, [NotNullWhen(true)] else { Debug.Assert(value is string); - _headerStore![key] = info = new HeaderStoreItemInfo() { RawValue = value }; + storeValueRef = info = new HeaderStoreItemInfo() { RawValue = value }; } - return ParseRawHeaderValues(key, info, removeEmptyHeader: true); + return ParseRawHeaderValues(key, info); } info = null; return false; } - private bool ParseRawHeaderValues(HeaderDescriptor descriptor, HeaderStoreItemInfo info, bool removeEmptyHeader) + private bool ParseRawHeaderValues(HeaderDescriptor descriptor, HeaderStoreItemInfo info) { // Unlike TryGetHeaderInfo() this method tries to parse all non-validated header values (if any) // before returning to the caller. + Debug.Assert(!info.IsEmpty); if (info.RawValue != null) { List? rawValues = info.RawValue as List; @@ -730,16 +753,12 @@ private bool ParseRawHeaderValues(HeaderDescriptor descriptor, HeaderStoreItemIn info.RawValue = null; // During parsing, we removed the value since it contains newline chars. Return false to indicate that - // this is an empty header. If the caller specified to remove empty headers, we'll remove the header before - // returning. + // this is an empty header. if ((info.InvalidValue == null) && (info.ParsedValue == null)) { - if (removeEmptyHeader) - { - // After parsing the raw value, no value is left because all values contain newline chars. - Debug.Assert(_headerStore != null); - _headerStore.Remove(descriptor); - } + // After parsing the raw value, no value is left because all values contain newline chars. + Debug.Assert(_count > 0); + Remove(descriptor); return false; } } @@ -808,7 +827,8 @@ internal bool TryParseAndAddValue(HeaderDescriptor descriptor, string? value) { // If we get here, then the value could be parsed correctly. If we created a new HeaderStoreItemInfo, add // it to the store if we added at least one value. - AddHeaderToStore(descriptor, info); + Debug.Assert(!ContainsKey(descriptor)); + AddEntryToStore(new HeaderEntry(descriptor, info)); } return result; @@ -1061,12 +1081,14 @@ internal bool TryGetHeaderDescriptor(string name, out HeaderDescriptor descripto if (HeaderDescriptor.TryGet(name, out descriptor)) { - if ((descriptor.HeaderType & _allowedHeaderTypes) != 0) + HttpHeaderType headerType = descriptor.HeaderType; + + if ((headerType & _allowedHeaderTypes) != 0) { return true; } - if ((descriptor.HeaderType & _treatAsCustomHeaderTypes) != 0) + if ((headerType & _treatAsCustomHeaderTypes) != 0) { descriptor = descriptor.AsCustomHeader(); return true; @@ -1128,7 +1150,8 @@ internal static void GetStoreValuesAsStringOrStringArray(HeaderDescriptor descri } else { - values = multiValue = length != 0 ? new string[length] : Array.Empty(); + Debug.Assert(length > 1, "The header should have been removed when it became empty"); + values = multiValue = new string[length]; } int currentIndex = 0; @@ -1252,5 +1275,234 @@ internal bool CanAddParsedValue(HttpHeaderParser parser) internal bool IsEmpty => (RawValue == null) && (InvalidValue == null) && (ParsedValue == null); } + + + #region Low-level implementation details that work with _headerStore directly + + // Used to store the CollectionsMarshal.GetValueRefOrAddDefault out parameter. + // This is a workaround for the Roslyn bug where we can't use a discard instead: + // https://github.com/dotnet/roslyn/issues/56587#issuecomment-934955526 + private static bool s_dictionaryGetValueRefOrAddDefaultExistsDummy; + + private const int InitialCapacity = 4; + internal const int ArrayThreshold = 64; // Above this threshold, header ordering will not be preserved + + internal HeaderEntry[]? GetEntriesArray() + { + object? store = _headerStore; + if (store is null) + { + return null; + } + else if (store is HeaderEntry[] entries) + { + return entries; + } + else + { + return GetEntriesFromDictionary(); + } + + HeaderEntry[] GetEntriesFromDictionary() + { + var dictionary = (Dictionary)_headerStore!; + var entries = new HeaderEntry[dictionary.Count]; + int i = 0; + foreach (KeyValuePair entry in dictionary) + { + entries[i++] = new HeaderEntry + { + Key = entry.Key, + Value = entry.Value + }; + } + return entries; + } + } + + internal ReadOnlySpan GetEntries() + { + return new ReadOnlySpan(GetEntriesArray(), 0, _count); + } + + internal int Count => _count; + + private bool EntriesAreLiveView => _headerStore is HeaderEntry[]; + + private ref object GetValueRefOrNullRef(HeaderDescriptor key) + { + ref object valueRef = ref Unsafe.NullRef(); + + object? store = _headerStore; + if (store is HeaderEntry[] entries) + { + for (int i = 0; i < _count && i < entries.Length; i++) + { + if (key.Equals(entries[i].Key)) + { + valueRef = ref entries[i].Value; + break; + } + } + } + else if (store is not null) + { + valueRef = ref CollectionsMarshal.GetValueRefOrNullRef(Unsafe.As>(store), key); + } + + return ref valueRef; + } + + private ref object? GetValueRefOrAddDefault(HeaderDescriptor key) + { + object? store = _headerStore; + if (store is HeaderEntry[] entries) + { + for (int i = 0; i < _count && i < entries.Length; i++) + { + if (key.Equals(entries[i].Key)) + { + return ref entries[i].Value!; + } + } + + int count = _count; + _count++; + if ((uint)count < (uint)entries.Length) + { + entries[count].Key = key; + return ref entries[count].Value!; + } + + return ref GrowEntriesAndAddDefault(key); + } + else if (store is null) + { + _count++; + entries = new HeaderEntry[InitialCapacity]; + _headerStore = entries; + ref HeaderEntry firstEntry = ref MemoryMarshal.GetArrayDataReference(entries); + firstEntry.Key = key; + return ref firstEntry.Value!; + } + else + { + return ref DictionaryGetValueRefOrAddDefault(key); + } + + ref object? GrowEntriesAndAddDefault(HeaderDescriptor key) + { + var entries = (HeaderEntry[])_headerStore!; + if (entries.Length == ArrayThreshold) + { + return ref ConvertToDictionaryAndAddDefault(key); + } + else + { + Array.Resize(ref entries, entries.Length << 1); + _headerStore = entries; + ref HeaderEntry firstNewEntry = ref entries[entries.Length >> 1]; + firstNewEntry.Key = key; + return ref firstNewEntry.Value!; + } + } + + ref object? ConvertToDictionaryAndAddDefault(HeaderDescriptor key) + { + var entries = (HeaderEntry[])_headerStore!; + var dictionary = new Dictionary(ArrayThreshold); + _headerStore = dictionary; + foreach (HeaderEntry entry in entries) + { + dictionary.Add(entry.Key, entry.Value); + } + Debug.Assert(dictionary.Count == _count - 1); + return ref CollectionsMarshal.GetValueRefOrAddDefault(dictionary, key, out s_dictionaryGetValueRefOrAddDefaultExistsDummy); + } + + ref object? DictionaryGetValueRefOrAddDefault(HeaderDescriptor key) + { + var dictionary = (Dictionary)_headerStore!; + ref object? value = ref CollectionsMarshal.GetValueRefOrAddDefault(dictionary, key, out s_dictionaryGetValueRefOrAddDefaultExistsDummy); + if (value is null) + { + _count++; + } + return ref value; + } + } + + private void AddEntryToStore(HeaderEntry entry) + { + Debug.Assert(!ContainsKey(entry.Key)); + + if (_headerStore is HeaderEntry[] entries) + { + int count = _count; + if ((uint)count < (uint)entries.Length) + { + entries[count] = entry; + _count++; + return; + } + } + + GetValueRefOrAddDefault(entry.Key) = entry.Value; + } + + internal bool ContainsKey(HeaderDescriptor key) + { + return !Unsafe.IsNullRef(ref GetValueRefOrNullRef(key)); + } + + public void Clear() + { + if (_headerStore is HeaderEntry[] entries) + { + Array.Clear(entries, 0, _count); + } + else + { + _headerStore = null; + } + _count = 0; + } + + internal bool Remove(HeaderDescriptor key) + { + bool removed = false; + + object? store = _headerStore; + if (store is HeaderEntry[] entries) + { + for (int i = 0; i < _count && i < entries.Length; i++) + { + if (key.Equals(entries[i].Key)) + { + while (i + 1 < _count && (uint)(i + 1) < (uint)entries.Length) + { + entries[i] = entries[i + 1]; + i++; + } + entries[i] = default; + removed = true; + break; + } + } + } + else if (store is not null) + { + removed = Unsafe.As>(store).Remove(key); + } + + if (removed) + { + _count--; + } + + return removed; + } + + #endregion // _headerStore implementation } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs index 5e67476d116a9..b2d2f5c3a8727 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs @@ -25,7 +25,7 @@ namespace System.Net.Http.Headers /// Gets the number of headers stored in the collection. /// Multiple header values associated with the same header name are considered to be one header as far as this count is concerned. - public int Count => _headers?.HeaderStore?.Count ?? 0; + public int Count => _headers?.Count ?? 0; /// Gets whether the collection contains the specified header. /// The name of the header. @@ -33,7 +33,7 @@ namespace System.Net.Http.Headers public bool Contains(string headerName) => _headers is HttpHeaders headers && headers.TryGetHeaderDescriptor(headerName, out HeaderDescriptor descriptor) && - headers.TryGetHeaderValue(descriptor, out _); + headers.ContainsKey(descriptor); /// Gets the values for the specified header name. /// The name of the header. @@ -83,8 +83,8 @@ public bool TryGetValues(string headerName, out HeaderStringValues values) /// Gets an enumerator that iterates through the . /// An enumerator that iterates through the . public Enumerator GetEnumerator() => - _headers is HttpHeaders headers && headers.HeaderStore is Dictionary store ? - new Enumerator(store.GetEnumerator()) : + _headers is HttpHeaders headers && headers.GetEntriesArray() is HeaderEntry[] entries ? + new Enumerator(entries, headers.Count) : default; /// @@ -120,35 +120,34 @@ IEnumerable IReadOnlyDictionary. /// Enumerates the elements of a . public struct Enumerator : IEnumerator> { - /// The wrapped enumerator for the underlying headers dictionary. - private Dictionary.Enumerator _headerStoreEnumerator; - /// The current value. + private readonly HeaderEntry[] _entries; + private readonly int _numberOfEntries; + private int _index; private KeyValuePair _current; - /// true if the enumerator was constructed via the ctor; otherwise, false./ - private bool _valid; - /// Initializes the enumerator. - /// The underlying dictionary enumerator. - internal Enumerator(Dictionary.Enumerator headerStoreEnumerator) + internal Enumerator(HeaderEntry[] entries, int numberOfEntries) { - _headerStoreEnumerator = headerStoreEnumerator; + _entries = entries; + _numberOfEntries = numberOfEntries; + _index = 0; _current = default; - _valid = true; } /// public bool MoveNext() { - if (_valid && _headerStoreEnumerator.MoveNext()) + int index = _index; + if (_entries is HeaderEntry[] entries && index < _numberOfEntries && (uint)index < (uint)entries.Length) { - KeyValuePair current = _headerStoreEnumerator.Current; + HeaderEntry entry = entries[index]; + _index++; - HttpHeaders.GetStoreValuesAsStringOrStringArray(current.Key, current.Value, out string? singleValue, out string[]? multiValue); + HttpHeaders.GetStoreValuesAsStringOrStringArray(entry.Key, entry.Value, out string? singleValue, out string[]? multiValue); Debug.Assert(singleValue is not null ^ multiValue is not null); _current = new KeyValuePair( - current.Key.Name, - singleValue is not null ? new HeaderStringValues(current.Key, singleValue) : new HeaderStringValues(current.Key, multiValue!)); + entry.Key.Name, + singleValue is not null ? new HeaderStringValues(entry.Key, singleValue) : new HeaderStringValues(entry.Key, multiValue!)); return true; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs index 724e00b571556..d14bbbf2799cf 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs @@ -21,16 +21,16 @@ public partial class HttpClientHandler : HttpMessageHandler private const string GetHttpMessageHandlerType = "Android.Runtime.AndroidEnvironment, Mono.Android"; #elif TARGET_IOS private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.iOS"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.iOS"; + private const string AssemblyName = "Microsoft.iOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.iOS"; #elif TARGET_MACCATALYST private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.MacCatalyst"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.MacCatalyst"; + private const string AssemblyName = "Microsoft.MacCatalyst"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.MacCatalyst"; #elif TARGET_TVOS private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.TVOS"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.TVOS"; + private const string AssemblyName = "Microsoft.tvOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.tvOS"; #else #error Unknown target #endif diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs index 234ca135aa9bd..c754dff03e59d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs @@ -422,31 +422,25 @@ private void Parse(string challenge) internal static class StringBuilderExtensions { - // Characters that require escaping in quoted string - private static readonly char[] SpecialCharacters = new[] { '"', '\\' }; - public static void AppendKeyValue(this StringBuilder sb, string key, string value, bool includeQuotes = true, bool includeComma = true) { - sb.Append(key); - sb.Append('='); + sb.Append(key).Append('='); + if (includeQuotes) { + ReadOnlySpan valueSpan = value; sb.Append('"'); - int lastSpecialIndex = 0; - int specialIndex; while (true) { - specialIndex = value.IndexOfAny(SpecialCharacters, lastSpecialIndex); - if (specialIndex >= 0) + int i = valueSpan.IndexOfAny('"', '\\'); // Characters that require escaping in quoted string + if (i >= 0) { - sb.Append(value, lastSpecialIndex, specialIndex - lastSpecialIndex); - sb.Append('\\'); - sb.Append(value[specialIndex]); - lastSpecialIndex = specialIndex + 1; + sb.Append(valueSpan.Slice(0, i)).Append('\\').Append(valueSpan[i]); + valueSpan = valueSpan.Slice(i + 1); } else { - sb.Append(value, lastSpecialIndex, value.Length - lastSpecialIndex); + sb.Append(valueSpan); break; } } @@ -459,8 +453,7 @@ public static void AppendKeyValue(this StringBuilder sb, string key, string valu if (includeComma) { - sb.Append(','); - sb.Append(' '); + sb.Append(',').Append(' '); } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index 811d33dbfb4ef..a4e224bd5b9b3 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -1337,15 +1337,10 @@ private void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders heade { if (NetEventSource.Log.IsEnabled()) Trace(""); - if (headers.HeaderStore is null) - { - return; - } - HeaderEncodingSelector? encodingSelector = _pool.Settings._requestHeaderEncodingSelector; ref string[]? tmpHeaderValuesArray = ref t_headerValues; - foreach (KeyValuePair header in headers.HeaderStore) + foreach (HeaderEntry header in headers.GetEntries()) { int headerValuesCount = HttpHeaders.GetStoreValuesIntoStringArray(header.Key, header.Value, ref tmpHeaderValuesArray); Debug.Assert(headerValuesCount > 0, "No values for header??"); @@ -1361,7 +1356,7 @@ private void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders heade // The Connection, Upgrade and ProxyConnection headers are also not supported in HTTP2. if (knownHeader != KnownHeaders.Host && knownHeader != KnownHeaders.Connection && knownHeader != KnownHeaders.Upgrade && knownHeader != KnownHeaders.ProxyConnection) { - if (header.Key.KnownHeader == KnownHeaders.TE) + if (knownHeader == KnownHeaders.TE) { // HTTP/2 allows only 'trailers' TE header. rfc7540 8.1.2.2 foreach (string value in headerValues) @@ -2043,7 +2038,7 @@ private void VerifyKeepAlive() _keepAlivePingTimeoutTimestamp = now + _keepAlivePingTimeout; long pingPayload = Interlocked.Increment(ref _keepAlivePingPayload); - SendPingAsync(pingPayload); + LogExceptions(SendPingAsync(pingPayload)); return; } break; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 3a236ccc65ae3..9a7ebccc416a8 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -622,14 +622,9 @@ private void BufferHeaders(HttpRequestMessage request) // TODO: special-case Content-Type for static table values values? private void BufferHeaderCollection(HttpHeaders headers) { - if (headers.HeaderStore == null) - { - return; - } - HeaderEncodingSelector? encodingSelector = _connection.Pool.Settings._requestHeaderEncodingSelector; - foreach (KeyValuePair header in headers.HeaderStore) + foreach (HeaderEntry header in headers.GetEntries()) { int headerValuesCount = HttpHeaders.GetStoreValuesIntoStringArray(header.Key, header.Value, ref _headerValues); Debug.Assert(headerValuesCount > 0, "No values for header??"); @@ -645,7 +640,7 @@ private void BufferHeaderCollection(HttpHeaders headers) // The Connection, Upgrade and ProxyConnection headers are also not supported in HTTP/3. if (knownHeader != KnownHeaders.Host && knownHeader != KnownHeaders.Connection && knownHeader != KnownHeaders.Upgrade && knownHeader != KnownHeaders.ProxyConnection) { - if (header.Key.KnownHeader == KnownHeaders.TE) + if (knownHeader == KnownHeaders.TE) { // HTTP/2 allows only 'trailers' TE header. rfc7540 8.1.2.2 // HTTP/3 does not mention this one way or another; assume it has the same rule. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index 12b6b4bf3c55a..deb0f5d9373d1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -258,10 +258,12 @@ private async ValueTask WriteHeadersAsync(HttpHeaders headers, string? cookiesFr { Debug.Assert(_currentRequest != null); - if (headers.HeaderStore != null) + if (headers.GetEntriesArray() is HeaderEntry[] entries) { - foreach (KeyValuePair header in headers.HeaderStore) + for (int i = 0; i < headers.Count; i++) { + HeaderEntry header = entries[i]; + if (header.Key.KnownHeader != null) { await WriteBytesAsync(header.Key.KnownHeader.AsciiBytesWithColonSpace, async).ConfigureAwait(false); @@ -298,10 +300,10 @@ private async ValueTask WriteHeadersAsync(HttpHeaders headers, string? cookiesFr separator = parser.Separator!; } - for (int i = 1; i < headerValuesCount; i++) + for (int j = 1; j < headerValuesCount; j++) { await WriteAsciiStringAsync(separator, async).ConfigureAwait(false); - await WriteStringAsync(_headerValues[i], async, valueEncoding).ConfigureAwait(false); + await WriteStringAsync(_headerValues[j], async, valueEncoding).ConfigureAwait(false); } } } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index 3c011b669ca9a..523c25c83bed9 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -1044,12 +1044,12 @@ public sealed class SocketsHttpHandlerTest_Cookies_Http11 : HttpClientHandlerTes public SocketsHttpHandlerTest_Cookies_Http11(ITestOutputHelper output) : base(output) { } } - [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public sealed class SocketsHttpHandler_HttpClientHandler_Http11_Cancellation_Test : SocketsHttpHandler_Cancellation_Test { public SocketsHttpHandler_HttpClientHandler_Http11_Cancellation_Test(ITestOutputHelper output) : base(output) { } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void ConnectTimeout_Default() { using (var handler = new SocketsHttpHandler()) @@ -1062,6 +1062,7 @@ public void ConnectTimeout_Default() [InlineData(0)] [InlineData(-2)] [InlineData(int.MaxValue + 1L)] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void ConnectTimeout_InvalidValues(long ms) { using (var handler = new SocketsHttpHandler()) @@ -1075,6 +1076,7 @@ public void ConnectTimeout_InvalidValues(long ms) [InlineData(1)] [InlineData(int.MaxValue - 1)] [InlineData(int.MaxValue)] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void ConnectTimeout_ValidValues_Roundtrip(long ms) { using (var handler = new SocketsHttpHandler()) @@ -1085,6 +1087,7 @@ public void ConnectTimeout_ValidValues_Roundtrip(long ms) } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void ConnectTimeout_SetAfterUse_Throws() { using (var handler = new SocketsHttpHandler()) @@ -1098,6 +1101,7 @@ public void ConnectTimeout_SetAfterUse_Throws() } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void Expect100ContinueTimeout_Default() { using (var handler = new SocketsHttpHandler()) @@ -1109,6 +1113,7 @@ public void Expect100ContinueTimeout_Default() [Theory] [InlineData(-2)] [InlineData(int.MaxValue + 1L)] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void Expect100ContinueTimeout_InvalidValues(long ms) { using (var handler = new SocketsHttpHandler()) @@ -1122,6 +1127,7 @@ public void Expect100ContinueTimeout_InvalidValues(long ms) [InlineData(1)] [InlineData(int.MaxValue - 1)] [InlineData(int.MaxValue)] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void Expect100ContinueTimeout_ValidValues_Roundtrip(long ms) { using (var handler = new SocketsHttpHandler()) @@ -1132,6 +1138,7 @@ public void Expect100ContinueTimeout_ValidValues_Roundtrip(long ms) } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "ConnectTimeout is not supported on Browser")] public void Expect100ContinueTimeout_SetAfterUse_Throws() { using (var handler = new SocketsHttpHandler()) @@ -2254,9 +2261,9 @@ public async Task Http2_MultipleConnectionsEnabled_OpenAndCloseMultipleConnectio await Task.WhenAll(handleRequestTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); - Assert.Equal(handleRequestTasks[0].Result.Count, MaxConcurrentStreams); - Assert.Equal(handleRequestTasks[1].Result.Count, MaxConcurrentStreams); - Assert.Equal(handleRequestTasks[2].Result.Count, MaxConcurrentStreams); + Assert.Equal(MaxConcurrentStreams, handleRequestTasks[0].Result.Count); + Assert.Equal(MaxConcurrentStreams, handleRequestTasks[1].Result.Count); + Assert.Equal(MaxConcurrentStreams, handleRequestTasks[2].Result.Count); await connection0.ShutdownIgnoringErrorsAsync(handleRequestTasks[0].Result.LastStreamId).ConfigureAwait(false); await connection2.ShutdownIgnoringErrorsAsync(handleRequestTasks[2].Result.LastStreamId).ConfigureAwait(false); @@ -2277,9 +2284,9 @@ public async Task Http2_MultipleConnectionsEnabled_OpenAndCloseMultipleConnectio await Task.WhenAll(finalHandleTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); - Assert.Equal(finalHandleTasks[0].Result.Count, MaxConcurrentStreams); - Assert.Equal(finalHandleTasks[1].Result.Count, MaxConcurrentStreams); - Assert.Equal(finalHandleTasks[2].Result.Count, MaxConcurrentStreams); + Assert.Equal(MaxConcurrentStreams, finalHandleTasks[0].Result.Count); + Assert.Equal(MaxConcurrentStreams, finalHandleTasks[1].Result.Count); + Assert.Equal(MaxConcurrentStreams, finalHandleTasks[2].Result.Count); await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/HPack/HPackRoundtripTests.cs b/src/libraries/System.Net.Http/tests/UnitTests/HPack/HPackRoundtripTests.cs index c3b16afb47360..d2f81304dd912 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/HPack/HPackRoundtripTests.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/HPack/HPackRoundtripTests.cs @@ -60,7 +60,7 @@ private static Memory HPackEncode(HttpHeaders headers, Encoding? valueEnco FillAvailableSpaceWithOnes(buffer); string[] headerValues = Array.Empty(); - foreach (KeyValuePair header in headers.HeaderStore) + foreach (HeaderEntry header in headers.GetEntries()) { int headerValuesCount = HttpHeaders.GetStoreValuesIntoStringArray(header.Key, header.Value, ref headerValues); Assert.InRange(headerValuesCount, 0, int.MaxValue); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs index 139422163a95b..79196e77c75ea 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs @@ -1710,6 +1710,24 @@ public void GetEnumerator_UseExplicitInterfaceImplementation_EnumeratorReturnsNo Assert.False(enumerator.MoveNext(), "Only 2 values expected, but enumerator returns a third one."); } + [Fact] + public void GetEnumerator_InvalidValueBetweenValidHeaders_EnumeratorReturnsAllValidValuesAndRemovesInvalidValue() + { + MockHeaders headers = new MockHeaders(); + headers.TryAddWithoutValidation("foo", "fooValue"); + headers.TryAddWithoutValidation("invalid", "invalid\nvalue"); + headers.TryAddWithoutValidation("bar", "barValue"); + + Assert.Equal(3, headers.Count); + + IDictionary> dict = headers.ToDictionary(pair => pair.Key, pair => pair.Value); + Assert.Equal("fooValue", Assert.Single(Assert.Contains("foo", dict))); + Assert.Equal("barValue", Assert.Single(Assert.Contains("bar", dict))); + + Assert.Equal(2, headers.Count); + Assert.False(headers.NonValidated.Contains("invalid")); + } + [Fact] public void AddParsedValue_AddSingleValueToNonExistingHeader_HeaderGetsCreatedAndValueAdded() { @@ -2208,6 +2226,150 @@ public void HeaderStringValues_Constructed_ProducesExpectedResults() } } + [Theory] + [MemberData(nameof(NumberOfHeadersUpToArrayThreshold_AddNonValidated_EnumerateNonValidated))] + public void Add_WithinArrayThresholdHeaders_EnumerationPreservesOrdering(int numberOfHeaders, bool addNonValidated, bool enumerateNonValidated) + { + var headers = new MockHeaders(); + + for (int i = 0; i < numberOfHeaders; i++) + { + if (addNonValidated) + { + headers.TryAddWithoutValidation(i.ToString(), i.ToString()); + } + else + { + headers.Add(i.ToString(), i.ToString()); + } + } + + KeyValuePair[] entries = enumerateNonValidated + ? headers.NonValidated.Select(pair => KeyValuePair.Create(pair.Key, Assert.Single(pair.Value))).ToArray() + : headers.Select(pair => KeyValuePair.Create(pair.Key, Assert.Single(pair.Value))).ToArray(); + + Assert.Equal(numberOfHeaders, entries.Length); + for (int i = 0; i < numberOfHeaders; i++) + { + Assert.Equal(i.ToString(), entries[i].Key); + Assert.Equal(i.ToString(), entries[i].Value); + } + } + + [Fact] + public void Add_Remove_HeaderOrderingIsPreserved() + { + var headers = new MockHeaders(); + headers.Add("a", ""); + headers.Add("b", ""); + headers.Add("c", ""); + + headers.Remove("b"); + + Assert.Equal(new[] { "a", "c" }, headers.Select(pair => pair.Key)); + } + + [Fact] + public void Add_AddToExistingKey_OriginalOrderingIsPreserved() + { + var headers = new MockHeaders(); + headers.Add("a", "a1"); + headers.Add("b", "b1"); + headers.Add("a", "a2"); + + Assert.Equal(new[] { "a", "b" }, headers.Select(pair => pair.Key)); + } + + [Theory] + [InlineData(3)] + [InlineData(4)] + [InlineData(5)] + [InlineData(HttpHeaders.ArrayThreshold / 4)] + [InlineData(HttpHeaders.ArrayThreshold / 2)] + [InlineData(HttpHeaders.ArrayThreshold - 1)] + [InlineData(HttpHeaders.ArrayThreshold)] + [InlineData(HttpHeaders.ArrayThreshold + 1)] + [InlineData(HttpHeaders.ArrayThreshold * 2)] + [InlineData(HttpHeaders.ArrayThreshold * 4)] + public void Add_LargeNumberOfHeaders_OperationsStillSupported(int numberOfHeaders) + { + string[] keys = Enumerable.Range(1, numberOfHeaders).Select(i => i.ToString()).ToArray(); + + var headers = new MockHeaders(); + foreach (string key in keys) + { + Assert.False(headers.NonValidated.Contains(key)); + headers.TryAddWithoutValidation(key, key); + Assert.True(headers.NonValidated.Contains(key)); + } + + string[] nonValidatedKeys = headers.NonValidated.Select(pair => pair.Key).ToArray(); + Assert.Equal(numberOfHeaders, nonValidatedKeys.Length); + + string[] newKeys = headers.Select(pair => pair.Key).ToArray(); + Assert.Equal(numberOfHeaders, newKeys.Length); + + string[] nonValidatedKeysAfterValidation = headers.NonValidated.Select(pair => pair.Key).ToArray(); + Assert.Equal(numberOfHeaders, nonValidatedKeysAfterValidation.Length); + + if (numberOfHeaders > HttpHeaders.ArrayThreshold) + { + // Ordering is lost when adding more than ArrayThreshold headers + Array.Sort(nonValidatedKeys, (a, b) => int.Parse(a).CompareTo(int.Parse(b))); + Array.Sort(newKeys, (a, b) => int.Parse(a).CompareTo(int.Parse(b))); + Array.Sort(nonValidatedKeysAfterValidation, (a, b) => int.Parse(a).CompareTo(int.Parse(b))); + } + Assert.Equal(keys, nonValidatedKeys); + Assert.Equal(keys, newKeys); + Assert.Equal(keys, nonValidatedKeysAfterValidation); + + headers.Add("3", "secondValue"); + Assert.True(headers.TryGetValues("3", out IEnumerable valuesFor3)); + Assert.Equal(new[] { "3", "secondValue" }, valuesFor3); + + Assert.True(headers.TryAddWithoutValidation("invalid", "invalid\nvalue")); + Assert.True(headers.TryAddWithoutValidation("valid", "validValue")); + + Assert.Equal(numberOfHeaders + 2, headers.NonValidated.Count); + + // Remove all headers except for "1", "valid", "invalid" + for (int i = 2; i <= numberOfHeaders; i++) + { + Assert.True(headers.Remove(i.ToString())); + } + + Assert.False(headers.Remove("3")); + + // "1", "invalid", "valid" + Assert.True(headers.NonValidated.Contains("invalid")); + Assert.Equal(3, headers.NonValidated.Count); + + Assert.Equal(new[] { "1", "valid" }, headers.Select(pair => pair.Key).OrderBy(i => i)); + + Assert.Equal(2, headers.NonValidated.Count); + + headers.Clear(); + + Assert.Equal(0, headers.NonValidated.Count); + Assert.Empty(headers); + Assert.False(headers.Contains("3")); + + Assert.True(headers.TryAddWithoutValidation("3", "newValue")); + Assert.True(headers.TryGetValues("3", out valuesFor3)); + Assert.Equal(new[] { "newValue" }, valuesFor3); + } + + public static IEnumerable NumberOfHeadersUpToArrayThreshold_AddNonValidated_EnumerateNonValidated() + { + for (int i = 0; i <= HttpHeaders.ArrayThreshold; i++) + { + yield return new object[] { i, false, false }; + yield return new object[] { i, false, true }; + yield return new object[] { i, true, false }; + yield return new object[] { i, true, true }; + } + } + public static IEnumerable GetInvalidHeaderNames() { yield return new object[] { "invalid header" }; diff --git a/src/libraries/System.Net.Mail/src/Resources/Strings.resx b/src/libraries/System.Net.Mail/src/Resources/Strings.resx index a72e327927cce..06521daf4ca9d 100644 --- a/src/libraries/System.Net.Mail/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Mail/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -57,19 +58,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - The parameter '{0}' cannot be an empty string. - The IAsyncResult object was not returned from the corresponding asynchronous method on this class. {0} can only be called once for each asynchronous operation. - - This property cannot be set to an empty string. - This method is not implemented by this class. diff --git a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj index 0fa2b09742513..afd76e87b7fdc 100644 --- a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj +++ b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj @@ -272,7 +272,7 @@ - + diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index 0ea9aa12af67e..4fc0954e94521 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -12,7 +12,6 @@ public abstract class AttachmentBase : IDisposable { internal bool disposed; private readonly MimePart _part = new MimePart(); - private static readonly char[] s_contentCIDInvalidChars = new char[] { '<', '>' }; internal AttachmentBase() { @@ -69,15 +68,7 @@ protected virtual void Dispose(bool disposing) internal void SetContentFromFile(string fileName, ContentType? contentType) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - if (fileName.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); - } + ArgumentException.ThrowIfNullOrEmpty(fileName); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); _part.SetContent(stream, contentType); @@ -85,15 +76,7 @@ internal void SetContentFromFile(string fileName, ContentType? contentType) internal void SetContentFromFile(string fileName, string? mediaType) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - if (fileName.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); - } + ArgumentException.ThrowIfNullOrEmpty(fileName); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); _part.SetContent(stream, null, mediaType); @@ -248,7 +231,7 @@ public string ContentId } else { - if (value.IndexOfAny(s_contentCIDInvalidChars) != -1) + if (value.AsSpan().IndexOfAny('<', '>') >= 0) // invalid chars { throw new ArgumentException(SR.MailHeaderInvalidCID, nameof(value)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs index 1acfc449c5afd..ae8940ef25f92 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs @@ -119,15 +119,12 @@ public static bool TryCreate(string address, string? displayName, Encoding? disp private static bool TryParse(string address, string? displayName, Encoding? displayNameEncoding, out (string displayName, string user, string host, Encoding displayNameEncoding) parsedData, bool throwExceptionIfFail) { - if (string.IsNullOrEmpty(address)) + if (throwExceptionIfFail) + { + ArgumentException.ThrowIfNullOrEmpty(address); + } + else if (string.IsNullOrEmpty(address)) { - if (throwExceptionIfFail) - { - throw address is null ? - new ArgumentNullException(nameof(address)) : - new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(address)), nameof(address)); - } - parsedData = default; return false; } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs index 88bea09486e76..41d3ba32a7021 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs @@ -18,14 +18,7 @@ public MailAddressCollection() public void Add(string addresses) { - if (addresses == null) - { - throw new ArgumentNullException(nameof(addresses)); - } - if (addresses.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(addresses)), nameof(addresses)); - } + ArgumentException.ThrowIfNullOrEmpty(addresses); ParseValue(addresses); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs index 4e7ad597cabf9..dfa63b9641f7c 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs @@ -37,17 +37,8 @@ public MailMessage() public MailMessage(string from, string to) { - if (from == null) - throw new ArgumentNullException(nameof(from)); - - if (to == null) - throw new ArgumentNullException(nameof(to)); - - if (from.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - - if (to.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); + ArgumentException.ThrowIfNullOrEmpty(from); + ArgumentException.ThrowIfNullOrEmpty(to); _message = new Message(from, to); if (NetEventSource.Log.IsEnabled()) NetEventSource.Associate(this, _message); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs index 53e41d8f86e6c..e6536a48e2b45 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs @@ -44,17 +44,8 @@ internal Message() internal Message(string from, string to) : this() { - if (from == null) - throw new ArgumentNullException(nameof(from)); - - if (to == null) - throw new ArgumentNullException(nameof(to)); - - if (from.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - - if (to.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); + ArgumentException.ThrowIfNullOrEmpty(from); + ArgumentException.ThrowIfNullOrEmpty(to); _from = new MailAddress(from); MailAddressCollection collection = new MailAddressCollection(); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs index beeea14766bca..71f0af271d14b 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs @@ -168,15 +168,7 @@ public string? Host throw new InvalidOperationException(SR.SmtpInvalidOperationDuringSend); } - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); value = value.Trim(); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs index b3ca5f87ac509..028e9456ce3d1 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs @@ -79,14 +79,7 @@ public string DispositionType get { return _dispositionType; } set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); _isChanged = true; _dispositionType = value; diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs index 5595f7aab2228..08bcb5e7c6e72 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs @@ -45,14 +45,7 @@ public ContentType() : this(Default) /// Unparsed value of the Content-Type header. public ContentType(string contentType) { - if (contentType == null) - { - throw new ArgumentNullException(nameof(contentType)); - } - if (contentType.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(contentType)), nameof(contentType)); - } + ArgumentException.ThrowIfNullOrEmpty(contentType); _isChanged = true; _type = contentType; @@ -99,15 +92,7 @@ public string MediaType get { return _mediaType + "/" + _subType; } set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); int offset = 0; _mediaType = MailBnfHelper.ReadToken(value, ref offset, null); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs index 89f988930f6ef..c77b6abdbaac4 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs @@ -22,15 +22,7 @@ internal HeaderCollection() : base(StringComparer.OrdinalIgnoreCase) public override void Remove(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); base.Remove(name); } @@ -40,15 +32,7 @@ public override void Remove(string name) public override string? Get(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); return base.Get(name); } @@ -57,15 +41,7 @@ public override void Remove(string name) public override string[]? GetValues(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); return base.GetValues(name); } @@ -93,25 +69,8 @@ internal void InternalAdd(string name, string value) public override void Set(string name, string value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(value); if (!MimeBasePart.IsAscii(name, false)) { @@ -131,22 +90,8 @@ public override void Set(string name, string value) public override void Add(string name, string value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } - if (value.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(value); MailBnfHelper.ValidateHeaderName(name); diff --git a/src/libraries/System.Net.Mail/tests/Functional/ContentDispositionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/ContentDispositionTest.cs index d6d6db3623494..2f25ed2bf8f12 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/ContentDispositionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/ContentDispositionTest.cs @@ -261,7 +261,7 @@ public void GetViaDateTimeProperty_WithLocalTime_ShouldSetDateTimeKindAppropriat cd.Parameters["creation-date"] = ValidDateTimeLocal; Assert.Equal(DateTimeKind.Local, cd.CreationDate.Kind); - Assert.Equal(cd.Parameters["creation-date"], ValidDateTimeLocal); + Assert.Equal(ValidDateTimeLocal, cd.Parameters["creation-date"]); } [Fact] diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs index bd0fb5298432d..ecdbdede4315d 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs @@ -341,7 +341,7 @@ public void TestZeroTimeout() [InlineData("howdydoo")] [InlineData("")] [InlineData(null)] - [SkipOnCoreClr("System.Net.Tests are flaky and/or long running: https://github.com/dotnet/runtime/issues/131", RuntimeConfiguration.Checked)] + [SkipOnCoreClr("System.Net.Tests are flaky and/or long running: https://github.com/dotnet/runtime/issues/131", ~RuntimeConfiguration.Release)] [ActiveIssue("https://github.com/dotnet/runtime/issues/131", TestRuntimes.Mono)] // System.Net.Tests are flaky and/or long running public async Task TestMailDeliveryAsync(string body) { @@ -360,7 +360,7 @@ public async Task TestMailDeliveryAsync(string body) [Fact] [PlatformSpecific(TestPlatforms.Windows)] // NTLM support required, see https://github.com/dotnet/runtime/issues/25827 - [SkipOnCoreClr("System.Net.Tests are flaky and/or long running: https://github.com/dotnet/runtime/issues/131", RuntimeConfiguration.Checked)] + [SkipOnCoreClr("System.Net.Tests are flaky and/or long running: https://github.com/dotnet/runtime/issues/131", ~RuntimeConfiguration.Release)] [ActiveIssue("https://github.com/dotnet/runtime/issues/131", TestRuntimes.Mono)] // System.Net.Tests are flaky and/or long running public async Task TestCredentialsCopyInAsyncContext() { diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs index 5da904a7c6f9d..a0127f539bc6c 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs @@ -47,7 +47,7 @@ public static IPHostEntry GetHostEntry(IPAddress address) if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(address))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(address)); } IPHostEntry ipHostEntry = GetHostEntryCore(address, AddressFamily.Unspecified); @@ -81,7 +81,7 @@ public static IPHostEntry GetHostEntry(string hostNameOrAddress, AddressFamily f if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(hostNameOrAddress))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(hostNameOrAddress)); } ipHostEntry = GetHostEntryCore(address, family); @@ -207,7 +207,7 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress, AddressFami if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(hostNameOrAddress))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(hostNameOrAddress)); } addresses = (family == AddressFamily.Unspecified || address.AddressFamily == family) ? new IPAddress[] { address } : Array.Empty(); diff --git a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs index 5ae74af0bd538..d2c0b1fc229c6 100644 --- a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs +++ b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.Win32; using System.IO; +using System.Linq; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Threading; @@ -15,6 +17,33 @@ public class NameResolutionPalTests { private readonly ITestOutputHelper _output; + private static Lazy s_ipv6LocalHostNameLookupBrokenByNrpRule = new Lazy(() => + { + // On some machines using Microsoft corporate VPN, something sometimes installs an DNS Name Resolution Policy rule + // that breaks reverse lookup of ipv6 localhost names. + if (PlatformDetection.IsWindows) + { + // Equivalent of `Get-DnsClientNrptRule -Name .ip6.arpa` + using RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig"); + if (key != null) + { + // Also filtering out anything not written by MSFTVPN + foreach (string name in key.GetSubKeyNames().Where(name => name.Contains("MSFTVPN"))) + { + using RegistryKey? key2 = key.OpenSubKey(name); + if (key2 != null && key2.GetValue("Name") is string[] values && values.Length == 1 && values[0] == ".ip6.arpa") + { + return true; + } + } + } + } + + return false; + }); + + private static bool Ipv6LocalHostNameLookupNotBrokenByNrpRule => !s_ipv6LocalHostNameLookupBrokenByNrpRule.Value; + public NameResolutionPalTests(ITestOutputHelper output) { _output = output; @@ -131,7 +160,7 @@ public void TryGetNameInfo_LocalHost_IPv4() Assert.NotNull(name); } - [Fact] + [ConditionalFact(nameof(Ipv6LocalHostNameLookupNotBrokenByNrpRule))] public void TryGetNameInfo_LocalHost_IPv6() { SocketError error; @@ -230,7 +259,7 @@ public void TryGetNameInfo_LocalHost_IPv4_TryGetAddrInfo(bool justAddresses) Assert.NotNull(addresses); } - [Theory] + [ConditionalTheory(nameof(Ipv6LocalHostNameLookupNotBrokenByNrpRule))] [InlineData(false)] [InlineData(true)] public void TryGetNameInfo_LocalHost_IPv6_TryGetAddrInfo(bool justAddresses) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs index 5d95e8b2b9733..30bd2f7713d84 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Threading.Tasks; using System.Threading; namespace System.Net.NetworkInformation @@ -12,7 +11,7 @@ namespace System.Net.NetworkInformation // Linux implementation of NetworkChange public partial class NetworkChange { - private static volatile int s_socket; + private static volatile SocketWrapper? s_socket; // Lock controlling access to delegate subscriptions, socket initialization, availability-changed state and timer. private static readonly object s_gate = new object(); @@ -34,7 +33,7 @@ public static event NetworkAddressChangedEventHandler? NetworkAddressChanged { lock (s_gate) { - if (s_socket == 0) + if (s_socket == null) { CreateSocket(); } @@ -51,8 +50,8 @@ public static event NetworkAddressChangedEventHandler? NetworkAddressChanged { if (s_addressChangedSubscribers.Count == 0 && s_availabilityChangedSubscribers.Count == 0) { - Debug.Assert(s_socket == 0, - "s_socket != 0, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); + Debug.Assert(s_socket == null, + "s_socket is not null, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); return; } @@ -74,7 +73,7 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC { lock (s_gate) { - if (s_socket == 0) + if (s_socket == null) { CreateSocket(); } @@ -113,8 +112,8 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC { if (s_addressChangedSubscribers.Count == 0 && s_availabilityChangedSubscribers.Count == 0) { - Debug.Assert(s_socket == 0, - "s_socket != 0, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); + Debug.Assert(s_socket == null, + "s_socket is not null, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); return; } @@ -140,7 +139,7 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC private static unsafe void CreateSocket() { - Debug.Assert(s_socket == 0, "s_socket != 0, must close existing socket before opening another."); + Debug.Assert(s_socket == null, "s_socket is not null, must close existing socket before opening another."); int newSocket; Interop.Error result = Interop.Sys.CreateNetworkChangeListenerSocket(&newSocket); if (result != Interop.Error.SUCCESS) @@ -149,32 +148,34 @@ private static unsafe void CreateSocket() throw new NetworkInformationException(message); } - s_socket = newSocket; - new Thread(s => LoopReadSocket((int)s!)) + s_socket = new SocketWrapper(newSocket); + + new Thread(args => LoopReadSocket((SocketWrapper)args!)) { IsBackground = true, Name = ".NET Network Address Change" - }.UnsafeStart(newSocket); + }.UnsafeStart(s_socket); } private static void CloseSocket() { - Debug.Assert(s_socket != 0, "s_socket was 0 when CloseSocket was called."); - Interop.Error result = Interop.Sys.CloseNetworkChangeListenerSocket(s_socket); + Debug.Assert(s_socket != null, "s_socket was null when CloseSocket was called."); + Interop.Error result = Interop.Sys.CloseNetworkChangeListenerSocket(s_socket != null ? s_socket.Socket : -1); if (result != Interop.Error.SUCCESS) { string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); throw new NetworkInformationException(message); } - s_socket = 0; + s_socket = null; } - private static unsafe void LoopReadSocket(int socket) + private static unsafe void LoopReadSocket(SocketWrapper initiallyCreatedSocket) { - while (socket == s_socket) + while (s_socket == initiallyCreatedSocket) //if both references are equal then s_socket was not changed { - Interop.Sys.ReadEvents(socket, &ProcessEvent); + //we can continue processing events + Interop.Sys.ReadEvents(initiallyCreatedSocket.Socket, &ProcessEvent); } } @@ -185,7 +186,7 @@ private static void ProcessEvent(int socket, Interop.Sys.NetworkChangeKind kind) { lock (s_gate) { - if (socket == s_socket) + if (s_socket != null && socket == s_socket.Socket) { OnSocketEvent(kind); } @@ -290,5 +291,19 @@ private static void OnAvailabilityTimerFired(object? state) } } } + + // SocketWrapper class was introduced to prevent event thread leaks on Linux + // as described on GitHub: https://github.com/dotnet/runtime/issues/63788 + // For each CreateSocket() new s_socket instance is created and we pass it to ".NET Network Address Change" thread. + // We then continue loop in LoopReadSocket method as long as both references are equal. + private class SocketWrapper + { + public SocketWrapper(int socket) + { + Socket = socket; + } + + public int Socket { get; } + } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs index ef5fb68547fc7..2af54c4938ca4 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs @@ -379,8 +379,8 @@ public override UnicastIPAddressInformationCollection GetUnicastAddresses() => public override async Task GetUnicastAddressesAsync() { // Wait for the address table to stabilize. - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource)s).TrySetResult(), tcs)) { await tcs.Task.ConfigureAwait(false); } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs index 6a2a07a81fa0a..c99f15dcfd475 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Diagnostics; +using System.Threading; +using System.Linq; namespace System.Net.NetworkInformation.Tests { @@ -23,5 +26,31 @@ public void NetworkAddressChanged_JustRemove_Success() { NetworkChange.NetworkAddressChanged -= _addressHandler; } + + [PlatformSpecific(TestPlatforms.Linux)] + [OuterLoop("May take several seconds")] + [ConditionalFact(nameof(SupportsGettingThreadsWithPsCommand))] + public void NetworkAddressChanged_AddRemoveMultipleTimes_CheckForLeakingThreads() + { + for (int i = 1; i <= 10; i++) + { + NetworkChange.NetworkAddressChanged += _addressHandler; + NetworkChange.NetworkAddressChanged -= _addressHandler; + } + + Thread.Sleep(2000); //allow some time for threads to exit + + //We are searching for threads containing ".NET Network Ad" + //because ps command trims actual thread name ".NET Network Address Change". + //This thread is created in: + // src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs + int numberOfNetworkAddressChangeThreads = ProcessUtil.GetProcessThreadsWithPsCommand(Process.GetCurrentProcess().Id) + .Where(e => e.IndexOf(".NET Network Ad") > 0).Count(); + + Assert.Equal(0, numberOfNetworkAddressChangeThreads); //there should be no threads because there are no event subscribers + } + + private static bool SupportsGettingThreadsWithPsCommand + => TestConfiguration.SupportsGettingThreadsWithPsCommand; } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs new file mode 100644 index 0000000000000..842c20672ce70 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; + +namespace System.Net.NetworkInformation.Tests +{ + internal static class ProcessUtil + { + public static IEnumerable GetProcessThreadsWithPsCommand(int pid, int? timeoutInMilliseconds = null) + { + ProcessStartInfo psi = new ProcessStartInfo("ps", $"-T --no-headers -p {pid}"); + psi.RedirectStandardOutput = true; + + Process? process; + + try + { + process = Process.Start(psi); + } + catch (Exception ex) + { + throw new Exception($"Exception while trying to run 'ps' command", ex); + } + + if (process == null) + { + throw new Exception("Could not create process 'ps'"); + } + + try + { + if (timeoutInMilliseconds.HasValue) + { + if (!process.WaitForExit(timeoutInMilliseconds.Value)) + { + throw new Exception($"Process 'ps' did not exit after {timeoutInMilliseconds} milliseconds"); + } + } + else + { + process.WaitForExit(); + } + + string output = process.StandardOutput.ReadToEnd(); + if (process.ExitCode != 0) + { + throw new Exception($"Process 'ps' returned exit code {process.ExitCode}"); + } + + using StringReader sr = new StringReader(output); + + while (true) + { + string? line = sr.ReadLine(); + if (line == null) + { + break; + } + + yield return line; + } + } + finally + { + process.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj index 911dc187186c3..efd19ba3094f1 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj @@ -40,6 +40,8 @@ + + diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs new file mode 100644 index 0000000000000..058f13d49d700 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs @@ -0,0 +1,29 @@ +// 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 System.Linq; + +namespace System.Net.NetworkInformation.Tests +{ + internal static class TestConfiguration + { + public static bool SupportsGettingThreadsWithPsCommand { get { return s_supportsGettingThreadsWithPsCommand.Value; } } + + private static Lazy s_supportsGettingThreadsWithPsCommand = new Lazy(() => + { + if (OperatingSystem.IsWindows()) + { + return false; + } + + // On other platforms we will try it. + try + { + _ = ProcessUtil.GetProcessThreadsWithPsCommand(Process.GetCurrentProcess().Id).ToArray(); + return true; + } + catch { return false; } + }); + } +} \ No newline at end of file diff --git a/src/libraries/System.Net.Ping/src/Resources/Strings.resx b/src/libraries/System.Net.Ping/src/Resources/Strings.resx index 1ad9023082ef5..1a1c7112b5d30 100644 --- a/src/libraries/System.Net.Ping/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Ping/src/Resources/Strings.resx @@ -84,9 +84,6 @@ IPv6 is not installed. - - Ping functionality is not currently supported in UWP. - System.Net.Ping is not supported on this platform. diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs index 0d81532f2bc14..94cdeb2fe890c 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs @@ -19,6 +19,7 @@ public partial class Ping private const int MinIpHeaderLengthInBytes = 20; private const int MaxIpHeaderLengthInBytes = 60; private const int IpV6HeaderLengthInBytes = 40; + private static ushort DontFragment = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)0x4000) : (ushort)0x4000; private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { @@ -29,15 +30,17 @@ private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, in bool ipv4 = address.AddressFamily == AddressFamily.InterNetwork; bool sendIpHeader = ipv4 && options != null && SendIpHeader; + int totalLength = 0; if (sendIpHeader) { iph.VersionAndLength = 0x45; + totalLength = sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length); // On OSX this strangely must be host byte order. - iph.TotalLength = (ushort)(sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length)); + iph.TotalLength = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)totalLength) : (ushort)totalLength; iph.Protocol = 1; // ICMP iph.Ttl = (byte)options!.Ttl; - iph.Flags = (ushort)(options.DontFragment ? 0x4000 : 0); + iph.Flags = (ushort)(options.DontFragment ? DontFragment : 0); #pragma warning disable 618 iph.DestinationAddress = (uint)address.Address; #pragma warning restore 618 @@ -52,7 +55,7 @@ private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, in { Type = ipv4 ? (byte)IcmpV4MessageType.EchoRequest : (byte)IcmpV6MessageType.EchoRequest, Identifier = id, - }, buffer)); + }, buffer, totalLength)); } private Socket GetRawSocket(SocketConfig socketConfig) @@ -405,14 +408,14 @@ public SocketConfig(EndPoint endPoint, int timeout, PingOptions? options, bool i public readonly byte[] SendBuffer; } - private static unsafe byte[] CreateSendMessageBuffer(IpHeader ipHeader, IcmpHeader icmpHeader, byte[] payload) + private static unsafe byte[] CreateSendMessageBuffer(IpHeader ipHeader, IcmpHeader icmpHeader, byte[] payload, int totalLength = 0) { int icmpHeaderSize = sizeof(IcmpHeader); int offset = 0; - int packetSize = ipHeader.TotalLength != 0 ? ipHeader.TotalLength : checked(icmpHeaderSize + payload.Length); + int packetSize = totalLength != 0 ? totalLength : checked(icmpHeaderSize + payload.Length); byte[] result = new byte[packetSize]; - if (ipHeader.TotalLength != 0) + if (totalLength != 0) { int ipHeaderSize = sizeof(IpHeader); new Span(&ipHeader, sizeof(IpHeader)).CopyTo(result); diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs index 3897853f6d856..987d0462d70ca 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs @@ -15,7 +15,7 @@ namespace System.Net.NetworkInformation { public partial class Ping { - private static bool SendIpHeader => false; + private static bool SendIpHeader => OperatingSystem.IsFreeBSD(); private static bool NeedsConnect => OperatingSystem.IsLinux(); private static bool SupportsDualMode => true; diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs b/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs index a36d4f93deb02..8a87d2f0111e6 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs @@ -14,7 +14,9 @@ internal static class TestSettings public const int PingTimeout = 10 * 1000; public const string PayloadAsString = "'Post hoc ergo propter hoc'. 'After it, therefore because of it'. It means one thing follows the other, therefore it was caused by the other. But it's not always true. In fact it's hardly ever true."; - public static readonly byte[] PayloadAsBytes = Encoding.UTF8.GetBytes(TestSettings.PayloadAsString); + + // By default, FreeBSD supports buffer only up to 56 bytes + public static readonly byte[] PayloadAsBytes = Encoding.UTF8.GetBytes(OperatingSystem.IsFreeBSD() ? TestSettings.PayloadAsString.Substring(0, 55) : TestSettings.PayloadAsString); public static readonly byte[] PayloadAsBytesShort = Encoding.UTF8.GetBytes("ABCDEF0123456789"); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 8ed63ef9f97b3..4d0bfa918fd24 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -717,7 +717,7 @@ public override bool Equals([NotNullWhen(true)] object? comparand) && string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(Value, other.Value, StringComparison.Ordinal) && string.Equals(Path, other.Path, StringComparison.Ordinal) - && string.Equals(Domain, other.Domain, StringComparison.OrdinalIgnoreCase) + && CookieComparer.EqualDomains(Domain, other.Domain) && (Version == other.Version); } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs b/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs index e8c7c78b68c0b..edfe5ce52551a 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs @@ -203,7 +203,7 @@ internal int InternalAdd(Cookie cookie, bool isStrict) for (int i = 0; i < listCount; i++) { Cookie c = (Cookie)m_list[i]!; - if (CookieComparer.Compare(cookie, c) == 0) + if (CookieComparer.Equals(cookie, c)) { ret = 0; // Will replace or reject @@ -237,7 +237,7 @@ internal int IndexOf(Cookie cookie) int idx = 0; foreach (Cookie? c in m_list) { - if (CookieComparer.Compare(cookie, c!) == 0) + if (CookieComparer.Equals(cookie, c!)) { return idx; } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs index f0e19c005ab7f..d12a7b9d0751b 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs @@ -57,20 +57,8 @@ public void Add(Uri uriPrefix, string authType, NetworkCredential cred) public void Add(string host, int port, string authenticationType, NetworkCredential credential) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - - if (authenticationType == null) - { - throw new ArgumentNullException(nameof(authenticationType)); - } - - if (host.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host)), nameof(host)); - } + ArgumentException.ThrowIfNullOrEmpty(host); + ArgumentNullException.ThrowIfNull(authenticationType); if (port < 0) { @@ -200,18 +188,8 @@ public void Remove(string? host, int port, string? authenticationType) public NetworkCredential? GetCredential(string host, int port, string authenticationType) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - if (authenticationType == null) - { - throw new ArgumentNullException(nameof(authenticationType)); - } - if (host.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host)), nameof(host)); - } + ArgumentException.ThrowIfNullOrEmpty(host); + ArgumentNullException.ThrowIfNull(authenticationType); if (port < 0) { throw new ArgumentOutOfRangeException(nameof(port)); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs b/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs index fc6fb3b9177bb..1cdc3c5774cc7 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs @@ -16,15 +16,7 @@ public DnsEndPoint(string host, int port) : this(host, port, AddressFamily.Unspe public DnsEndPoint(string host, int port, AddressFamily addressFamily) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - - if (string.IsNullOrEmpty(host)) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host))); - } + ArgumentException.ThrowIfNullOrEmpty(host); if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) { diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs index b43ac159ead52..4d826d0e61afa 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs @@ -30,8 +30,8 @@ public static void Ctor_HostPort_AddressFamily_Success() [Fact] public static void Ctor_HostPortAddressFamily_Invalid() { - Assert.Throws(() => new DnsEndPoint(null, 500, AddressFamily.InterNetwork)); //Null host - AssertExtensions.Throws(null, () => new DnsEndPoint("", 500, AddressFamily.InterNetwork)); //Empty host + AssertExtensions.Throws("host", () => new DnsEndPoint(null, 500, AddressFamily.InterNetwork)); //Null host + AssertExtensions.Throws("host", () => new DnsEndPoint("", 500, AddressFamily.InterNetwork)); //Empty host Assert.Throws(() => new DnsEndPoint("host", IPEndPoint.MinPort - 1, AddressFamily.InterNetwork)); //Port < min port (0) Assert.Throws(() => new DnsEndPoint("host", IPEndPoint.MaxPort + 1, AddressFamily.InterNetwork)); //Port > max port (65535) diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs index b3673331aebcd..53cb06963caa7 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs @@ -866,6 +866,51 @@ public void SetCookies_DomainCheckFailure_IgnoresAbsenceOfLeadingDot(string doma Assert.Throws(() => container.SetCookies(uri, cookie)); } + [Theory] + [InlineData("example.com", "example.com" )] + [InlineData("example.com", ".example.com" )] + [InlineData(".example.com", "example.com" )] + [InlineData(".example.com", ".example.com")] + public void SetCookies_DomainCheckSuccess_IgnoresLeadingDot(params string[] domains) + { + var uri = new Uri($"https://{domains[0].Trim('.')}/", UriKind.Absolute); + var container = new CookieContainer(); + + // First HTTP response... + container.SetCookies(uri, $"foo=bar; Path=/; Domain={domains[0]}"); + + // Second HTTP response... + container.SetCookies(uri, $"foo=baz; Path=/; Domain={domains[1]}"); + + CookieCollection acceptedCookies = container.GetCookies(uri); + Assert.Equal(1, acceptedCookies.Count); + Assert.Equal(domains[1], acceptedCookies[0].Domain); + } + + [Theory] + [InlineData("test.example.com", "example.com")] + [InlineData("test.example.com", ".example.com")] + [InlineData("example.com", "test.example.com")] + [InlineData(".example.com", "test.example.com")] + public void SetCookies_DomainCheckFailure_IgnoresLeadingDot(params string[] domains) + { + var uri = new Uri($"https://test.example.com/", UriKind.Absolute); + var container = new CookieContainer(); + + // First HTTP response... + container.SetCookies(uri, $"foo=bar; Path=/; Domain={domains[0]}"); + + // Second HTTP response... + container.SetCookies(uri, $"foo=baz; Path=/; Domain={domains[1]}"); + + CookieCollection acceptedCookies = container.GetCookies(uri); + Assert.Equal(2, acceptedCookies.Count); + foreach (Cookie cookie in acceptedCookies) + { + Assert.Contains(cookie.Domain, domains); + } + } + // Test default-path calculation as defined in // https://tools.ietf.org/html/rfc6265#section-5.1.4 public static readonly TheoryData DefaultPathData = new TheoryData() diff --git a/src/libraries/System.Net.Quic/src/Resources/Strings.resx b/src/libraries/System.Net.Quic/src/Resources/Strings.resx index a692407e18364..f1e227448e030 100644 --- a/src/libraries/System.Net.Quic/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Quic/src/Resources/Strings.resx @@ -123,12 +123,6 @@ Connection aborted by peer ({0}). - - Must pass loopback address and port 0 - - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs index 24200021ec054..d536dfa58dbdc 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs @@ -156,9 +156,13 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, ulong ms = (ulong)options.IdleTimeout.Ticks / TimeSpan.TicksPerMillisecond; if (ms > (1ul << 62) - 1) throw new Exception("IdleTimeout is too large (max 2^62-1 milliseconds)"); - settings.IsSetFlags |= QuicSettingsIsSetFlags.IdleTimeoutMs; settings.IdleTimeoutMs = (ulong)options.IdleTimeout.TotalMilliseconds; } + else + { + settings.IdleTimeoutMs = 0; + } + settings.IsSetFlags |= QuicSettingsIsSetFlags.IdleTimeoutMs; uint status; SafeMsQuicConfigurationHandle? configurationHandle; diff --git a/src/libraries/System.Net.Requests/src/Resources/Strings.resx b/src/libraries/System.Net.Requests/src/Resources/Strings.resx index a3b2bb922d3c7..e93fad131a92c 100644 --- a/src/libraries/System.Net.Requests/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Requests/src/Resources/Strings.resx @@ -87,9 +87,6 @@ This method is not implemented by this class. - - This operation is not supported. - This property is not implemented by this class. diff --git a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj index 0de5ec949fbe1..3d688f2b4b0df 100644 --- a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj +++ b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj @@ -106,7 +106,7 @@ - + diff --git a/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs b/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs index ff439513b116b..6cf0d7d7740ee 100644 --- a/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs +++ b/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs @@ -40,9 +40,9 @@ public void Ctor_VerifyDefaults_Success() Assert.NotNull(request.Headers); Assert.Equal(0, request.Headers.Count); Assert.True(request.KeepAlive); - Assert.Equal(request.Method, WebRequestMethods.Ftp.DownloadFile); + Assert.Equal(WebRequestMethods.Ftp.DownloadFile, request.Method); Assert.Null(request.Proxy); - Assert.Equal(request.ReadWriteTimeout, 5 * 60 * 1000); + Assert.Equal(5 * 60 * 1000, request.ReadWriteTimeout); Assert.Null(request.RenameTo); Assert.Equal("ftp", request.RequestUri.Scheme); Assert.Equal("foo.com", request.RequestUri.Host); diff --git a/src/libraries/System.Net.Security/src/Resources/Strings.resx b/src/libraries/System.Net.Security/src/Resources/Strings.resx index e33b4122a7d53..5373ba6ee3307 100644 --- a/src/libraries/System.Net.Security/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/src/Resources/Strings.resx @@ -221,9 +221,6 @@ Authentication failed on the remote side (the stream might still be available for additional authentication attempts). - - Re-authentication failed because the remote party continued to encrypt more than {0} bytes before answering re-authentication. - Protocol error: A received message contains a valid signature but it was not encrypted as required by the effective Protection Level. @@ -233,9 +230,6 @@ Received an invalid authentication frame. The message size is limited to {0} bytes, attempted to read {1} bytes. - - Received incomplete authentication message. Remote party has probably closed the connection. - Cannot determine the frame size or a corrupted frame was received. @@ -245,78 +239,9 @@ The specified value is not valid in the '{0}' enumeration. - - Enumerating security packages: - - - Security package '{0}' was not found. - - - {0}(In-Buffer length={1}, Out-Buffer length={2}, returned code={3}). - - - {0}(In-Buffers count={1}, Out-Buffer length={2}, returned code={3}). - - - {0}(Protocol={1}, Cipher={2} {3} bit strength, Hash={4} {5} bit strength, Key Exchange={6} {7} bit strength). - - - Remote certificate: {0}. - - - Locating the private key for the certificate: {0}. - - - Certificate is of type X509Certificate2 and contains the private key. - - - Found the certificate in the {0} store. - - - Cannot find the certificate in either the LocalMachine store or the CurrentUser store. - Opening Certificate store {0} failed, exception: {1}. - - Got a certificate from the client delegate. - - - Client delegate did not provide a certificate; and there are not other user-provided certificates. Need to attempt a session restart. - - - Client delegate did not provide a certificate; but there are other user-provided certificates. - - - Attempting to restart the session using the user-provided certificate: {0}. - - - We have user-provided certificates. The server has not specified any issuers, so try all the certificates. - - - We have user-provided certificates. The server has specified {0} issuer(s). Looking for certificates that match any of the issuers. - - - Selected certificate: {0}. - - - Left with {0} client certificates to choose from. - - - Trying to find a matching certificate in the certificate store. - - - Using the cached credential handle. - - - Remote certificate was verified as valid by the user. - - - Remote certificate was verified as invalid by the user. - - - Remote certificate has no errors. - Remote certificate has errors: @@ -341,9 +266,6 @@ The ServiceNameCollection must contain at least one service name. - - A service name must not be null or empty. - Failed to allocate SSL/TLS context, OpenSSL error - {0}. @@ -374,9 +296,6 @@ SSL Write BIO failed with OpenSSL error - {0}. - - Failed to push X509_NAME into stack. - Getting SSL connection info failed with OpenSSL error - {0}. @@ -457,7 +376,7 @@ Client stream needs to be drained before renegotiation. - + Setting an SNI hostname is not supported on this API level. diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 9f90dbd3951f0..047cbdcc98aea 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -363,6 +363,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs b/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs new file mode 100644 index 0000000000000..bdf3547912c91 --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs @@ -0,0 +1,256 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// MD4.cs - Message Digest 4 Abstract class +// +// Author: +// Sebastien Pouliot (sebastien@xamarin.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright 2013 Xamarin Inc. (http://www.xamarin.com) +// + +// +// 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.Buffers.Binary; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; + +// +// This class is a port of the Mono managed implementation of the MD4 algorithm +// and required to support NTLM in Android only. +// It's an implementation detail and is not intended to be a public API. +// Assuming that NTLM would be System.Net.Security, it makes sense to put MD4 here as well. +// +namespace System.Net.Security +{ + internal sealed class MD4 + { + private const int S11 = 3; + private const int S12 = 7; + private const int S13 = 11; + private const int S14 = 19; + private const int S21 = 3; + private const int S22 = 5; + private const int S23 = 9; + private const int S24 = 13; + private const int S31 = 3; + private const int S32 = 9; + private const int S33 = 11; + private const int S34 = 15; + + internal static void HashData(ReadOnlySpan source, Span destination) + { + Debug.Assert(destination.Length == 128 >> 3); + + Span buffer = stackalloc byte[64]; + buffer.Clear(); + // Initialize the context + Span state = stackalloc uint[4] { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; + Span count = stackalloc uint[2] { 0, 0 }; + + HashCore(source, state, count, buffer); + + // Save number of bits + Span bits = stackalloc byte[8]; + Encode(bits, count); + + // Pad out to 56 mod 64 + uint index = ((count[0] >> 3) & 0x3f); + int padLen = (int)((index < 56) ? (56 - index) : (120 - index)); + Span padding = stackalloc byte[padLen]; + padding.Clear(); + padding[0] = 0x80; + HashCore(padding, state, count, buffer); + + // Append length (before padding) + HashCore(bits, state, count, buffer); + + // Write state to destination + Encode(destination, state); + } + + private static void HashCore(ReadOnlySpan input, Span state, Span count, Span buffer) + { + // Compute number of bytes mod 64 + int index = (int)((count[0] >> 3) & 0x3F); + // Update number of bits + count[0] += (uint)(input.Length << 3); + if (count[0] < (input.Length << 3)) + { + count[1]++; + } + + count[1] += (uint)(input.Length >> 29); + + int partLen = 64 - index; + int i = 0; + // Transform as many times as possible. + if (input.Length >= partLen) + { + if (index != 0) + { + input.Slice(0, partLen).CopyTo(buffer.Slice(index)); + MD4Transform(state, buffer); + index = 0; + } + else + { + partLen = 0; + } + + for (i = partLen; i + 63 < input.Length; i += 64) + { + MD4Transform(state, input.Slice(i)); + } + } + + // Buffer remaining input + input.Slice(i).CopyTo(buffer.Slice(index)); + } + + //--- private methods --------------------------------------------------- + + // F, G and H are basic MD4 functions. + private static uint F(uint x, uint y, uint z) + { + return (uint)(((x) & (y)) | ((~x) & (z))); + } + + private static uint G(uint x, uint y, uint z) + { + return (uint)(((x) & (y)) | ((x) & (z)) | ((y) & (z))); + } + + private static uint H(uint x, uint y, uint z) + { + return (uint)((x) ^ (y) ^ (z)); + } + + // FF, GG and HH are transformations for rounds 1, 2 and 3. + // Rotation is separate from addition to prevent recomputation. + private static void FF(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += F(b, c, d) + x; + a = BitOperations.RotateLeft(a, s); + } + + private static void GG(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += G(b, c, d) + x + 0x5a827999; + a = BitOperations.RotateLeft(a, s); + } + + private static void HH(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += H(b, c, d) + x + 0x6ed9eba1; + a = BitOperations.RotateLeft(a, s); + } + + private static void Encode(Span output, Span input) + { + for (int i = 0, j = 0; j < output.Length; i++, j += 4) + { + BinaryPrimitives.WriteUInt32LittleEndian(output.Slice(j), input[i]); + } + } + + private static void Decode(Span output, ReadOnlySpan input) + { + for (int i = 0, j = 0; i < output.Length; i++, j += 4) + { + output[i] = BinaryPrimitives.ReadUInt32LittleEndian(input.Slice(j)); + } + } + + private static void MD4Transform(Span state, ReadOnlySpan block) + { + uint a = state[0]; + uint b = state[1]; + uint c = state[2]; + uint d = state[3]; + Span x = stackalloc uint[16]; + + Decode(x, block); + + // Round 1 + FF(ref a, b, c, d, x[0], S11); // 1 + FF(ref d, a, b, c, x[1], S12); // 2 + FF(ref c, d, a, b, x[2], S13); // 3 + FF(ref b, c, d, a, x[3], S14); // 4 + FF(ref a, b, c, d, x[4], S11); // 5 + FF(ref d, a, b, c, x[5], S12); // 6 + FF(ref c, d, a, b, x[6], S13); // 7 + FF(ref b, c, d, a, x[7], S14); // 8 + FF(ref a, b, c, d, x[8], S11); // 9 + FF(ref d, a, b, c, x[9], S12); // 10 + FF(ref c, d, a, b, x[10], S13); // 11 + FF(ref b, c, d, a, x[11], S14); // 12 + FF(ref a, b, c, d, x[12], S11); // 13 + FF(ref d, a, b, c, x[13], S12); // 14 + FF(ref c, d, a, b, x[14], S13); // 15 + FF(ref b, c, d, a, x[15], S14); // 16 + + // Round 2 + GG(ref a, b, c, d, x[0], S21); // 17 + GG(ref d, a, b, c, x[4], S22); // 18 + GG(ref c, d, a, b, x[8], S23); // 19 + GG(ref b, c, d, a, x[12], S24); // 20 + GG(ref a, b, c, d, x[1], S21); // 21 + GG(ref d, a, b, c, x[5], S22); // 22 + GG(ref c, d, a, b, x[9], S23); // 23 + GG(ref b, c, d, a, x[13], S24); // 24 + GG(ref a, b, c, d, x[2], S21); // 25 + GG(ref d, a, b, c, x[6], S22); // 26 + GG(ref c, d, a, b, x[10], S23); // 27 + GG(ref b, c, d, a, x[14], S24); // 28 + GG(ref a, b, c, d, x[3], S21); // 29 + GG(ref d, a, b, c, x[7], S22); // 30 + GG(ref c, d, a, b, x[11], S23); // 31 + GG(ref b, c, d, a, x[15], S24); // 32 + + HH(ref a, b, c, d, x[0], S31); // 33 + HH(ref d, a, b, c, x[8], S32); // 34 + HH(ref c, d, a, b, x[4], S33); // 35 + HH(ref b, c, d, a, x[12], S34); // 36 + HH(ref a, b, c, d, x[2], S31); // 37 + HH(ref d, a, b, c, x[10], S32); // 38 + HH(ref c, d, a, b, x[6], S33); // 39 + HH(ref b, c, d, a, x[14], S34); // 40 + HH(ref a, b, c, d, x[1], S31); // 41 + HH(ref d, a, b, c, x[9], S32); // 42 + HH(ref c, d, a, b, x[5], S33); // 43 + HH(ref b, c, d, a, x[13], S34); // 44 + HH(ref a, b, c, d, x[3], S31); // 45 + HH(ref d, a, b, c, x[11], S32); // 46 + HH(ref c, d, a, b, x[7], S33); // 47 + HH(ref b, c, d, a, x[15], S34); // 48 + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + } + } +} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs index 3690837e33f67..9e1a445d9dc75 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs @@ -130,6 +130,7 @@ private static SafeSslHandle CreateSslContext(SafeFreeSslCredentials credential, SetCertificate(sslContext, credential.CertificateContext); } + Interop.AppleCrypto.SslBreakOnCertRequested(sslContext, true); Interop.AppleCrypto.SslBreakOnServerAuth(sslContext, true); Interop.AppleCrypto.SslBreakOnClientAuth(sslContext, true); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs index 6a2135616f1d5..e3363ddc1c34a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs @@ -295,62 +295,24 @@ private string[] GetRequestCertificateAuthorities() return issuers; } - /*++ - AcquireCredentials - Attempts to find Client Credential - Information, that can be sent to the server. In our case, - this is only Client Certificates, that we have Credential Info. - - How it works: - case 0: Cert Selection delegate is present - Always use its result as the client cert answer. - Try to use cached credential handle whenever feasible. - Do not use cached anonymous creds if the delegate has returned null - and the collection is not empty (allow responding with the cert later). - - case 1: Certs collection is empty - Always use the same statically acquired anonymous SSL Credential - - case 2: Before our Connection with the Server - If we have a cached credential handle keyed by first X509Certificate - **content** in the passed collection, then we use that cached - credential and hoping to restart a session. - - Otherwise create a new anonymous (allow responding with the cert later). - - case 3: After our Connection with the Server (i.e. during handshake or re-handshake) - The server has requested that we send it a Certificate then - we Enumerate a list of server sent Issuers trying to match against - our list of Certificates, the first match is sent to the server. - - Once we got a cert we again try to match cached credential handle if possible. - This will not restart a session but helps minimizing the number of handles we create. - - In the case of an error getting a Certificate or checking its private Key we fall back - to the behavior of having no certs, case 1. - - Returns: True if cached creds were used, false otherwise. - - --*/ - - private bool AcquireClientCredentials(ref byte[]? thumbPrint) + internal X509Certificate2? SelectClientCertificate(out bool sessionRestartAttempt) { - // Acquire possible Client Certificate information and set it on the handle. - X509Certificate? clientCertificate = null; // This is a candidate that can come from the user callback or be guessed when targeting a session restart. - List? filteredCerts = null; // This is an intermediate client certs collection that try to use if no selectedCert is available yet. - string[] issuers; // This is a list of issuers sent by the server, only valid is we do know what the server cert is. + sessionRestartAttempt = false; - bool sessionRestartAttempt = false; // If true and no cached creds we will use anonymous creds. + X509Certificate? clientCertificate = null; // candidate certificate that can come from the user callback or be guessed when targeting a session restart. + X509Certificate2? selectedCert = null; // final selected cert (ensured that it does have private key with it). + List? filteredCerts = null; // This is an intermediate client certs collection that try to use if no selectedCert is available yet. + string[] issuers; // This is a list of issuers sent by the server, only valid if we do know what the server cert is. if (_sslAuthenticationOptions.CertSelectionDelegate != null) { - issuers = GetRequestCertificateAuthorities(); - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "Calling CertificateSelectionCallback"); X509Certificate2? remoteCert = null; try { + issuers = GetRequestCertificateAuthorities(); remoteCert = CertificateValidationPal.GetRemoteCertificate(_securityContext!); if (_sslAuthenticationOptions.ClientCertificates == null) { @@ -363,7 +325,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) remoteCert?.Dispose(); } - if (clientCertificate != null) { if (_credentialsHandle == null) @@ -505,9 +466,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) } } - bool cachedCred = false; // This is a return result from this method. - X509Certificate2? selectedCert = null; // This is a final selected cert (ensured that it does have private key with it). - clientCertificate = null; if (NetEventSource.Log.IsEnabled()) @@ -550,6 +508,56 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Selected cert = {selectedCert}"); + _selectedClientCertificate = clientCertificate; + return selectedCert; + } + + /*++ + AcquireCredentials - Attempts to find Client Credential + Information, that can be sent to the server. In our case, + this is only Client Certificates, that we have Credential Info. + + How it works: + case 0: Cert Selection delegate is present + Always use its result as the client cert answer. + Try to use cached credential handle whenever feasible. + Do not use cached anonymous creds if the delegate has returned null + and the collection is not empty (allow responding with the cert later). + + case 1: Certs collection is empty + Always use the same statically acquired anonymous SSL Credential + + case 2: Before our Connection with the Server + If we have a cached credential handle keyed by first X509Certificate + **content** in the passed collection, then we use that cached + credential and hoping to restart a session. + + Otherwise create a new anonymous (allow responding with the cert later). + + case 3: After our Connection with the Server (i.e. during handshake or re-handshake) + The server has requested that we send it a Certificate then + we Enumerate a list of server sent Issuers trying to match against + our list of Certificates, the first match is sent to the server. + + Once we got a cert we again try to match cached credential handle if possible. + This will not restart a session but helps minimizing the number of handles we create. + + In the case of an error getting a Certificate or checking its private Key we fall back + to the behavior of having no certs, case 1. + + Returns: True if cached creds were used, false otherwise. + + --*/ + + private bool AcquireClientCredentials(ref byte[]? thumbPrint) + { + // Acquire possible Client Certificate information and set it on the handle. + + bool sessionRestartAttempt; // If true and no cached creds we will use anonymous creds. + bool cachedCred = false; // this is a return result from this method. + + X509Certificate2? selectedCert = SelectClientCertificate(out sessionRestartAttempt); + try { // Try to locate cached creds first. @@ -574,14 +582,14 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) // So we don't want to reuse **anonymous** cached credential for a new SSL connection if the client has passed some certificate. // The following block happens if client did specify a certificate but no cached creds were found in the cache. // Since we don't restart a session the server side can still challenge for a client cert. - if ((object?)clientCertificate != (object?)selectedCert) + if ((object?)_selectedClientCertificate != (object?)selectedCert) { selectedCert.Dispose(); } guessedThumbPrint = null; selectedCert = null; - clientCertificate = null; + _selectedClientCertificate = null; } if (cachedCredentialHandle != null) @@ -589,7 +597,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.UsingCachedCredential(this); _credentialsHandle = cachedCredentialHandle; - _selectedClientCertificate = clientCertificate; cachedCred = true; if (selectedCert != null) { @@ -607,7 +614,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.EncryptionPolicy, _sslAuthenticationOptions.IsServer); thumbPrint = guessedThumbPrint; // Delay until here in case something above threw. - _selectedClientCertificate = clientCertificate; } } finally @@ -792,6 +798,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte if (_sslAuthenticationOptions.IsServer) { status = SslStreamPal.AcceptSecurityContext( + this, ref _credentialsHandle!, ref _securityContext, inputBuffer, @@ -801,6 +808,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte else { status = SslStreamPal.InitializeSecurityContext( + this, ref _credentialsHandle!, ref _securityContext, _sslAuthenticationOptions.TargetHost, @@ -841,6 +849,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte internal SecurityStatusPal Renegotiate(out byte[]? output) { return SslStreamPal.Renegotiate( + this, ref _credentialsHandle!, ref _securityContext, _sslAuthenticationOptions, diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 9e6ad7475d766..58156e3d76a94 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -21,18 +21,6 @@ public partial class SslStream private int _nestedAuth; private bool _isRenego; - private enum Framing - { - Unknown = 0, // Initial before any frame is processed. - BeforeSSL3, // SSlv2 - SinceSSL3, // SSlv3 & TLS - Unified, // Intermediate on first frame until response is processes. - Invalid // Something is wrong. - } - - // This is set on the first packet to figure out the framing style. - private Framing _framing = Framing.Unknown; - private TlsFrameHelper.TlsFrameInfo _lastFrame; private object _handshakeLock => _sslAuthenticationOptions!; @@ -270,7 +258,7 @@ private async Task RenegotiateAsync(TIOAdapter adapter) try { - if (_decryptedBytesCount is not 0) + if ((_decryptedBytesCount | _internalBufferCount) != 0) { throw new InvalidOperationException(SR.net_ssl_renegotiate_buffer); } @@ -460,27 +448,12 @@ private async ValueTask ReceiveBlobAsync(TIOAdapter a where TIOAdapter : IReadWriteAdapter { await FillHandshakeBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); - if (_framing == Framing.Unified || _framing == Framing.Unknown) - { - _framing = DetectFraming(_handshakeBuffer.ActiveReadOnlySpan); - } - - if (_framing != Framing.SinceSSL3) - { -#pragma warning disable 0618 - _lastFrame.Header.Version = SslProtocols.Ssl2; -#pragma warning restore 0618 - _lastFrame.Header.Length = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan) - TlsFrameHelper.HeaderSize; - } - else - { - TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); - } + TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); if (_lastFrame.Header.Length < 0) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, "invalid TLS frame size"); - throw new IOException(SR.net_frame_read_size); + throw new AuthenticationException(SR.net_frame_read_size); } // Header length is content only so we must add header size as well. @@ -560,29 +533,26 @@ private ProtocolToken ProcessBlob(int frameSize) // ActiveSpan will exclude the "discarded" data. _handshakeBuffer.Discard(frameSize); - if (_framing == Framing.SinceSSL3) + // Often more TLS messages fit into same packet. Get as many complete frames as we can. + while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) { - // Often more TLS messages fit into same packet. Get as many complete frames as we can. - while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) - { - TlsFrameHeader nextHeader = default; - - if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) - { - break; - } + TlsFrameHeader nextHeader = default; - frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; - // Can process more handshake frames in single step, but we should avoid processing too much so as to preserve API boundary between handshake and I/O. - if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) || frameSize > _handshakeBuffer.ActiveLength) - { - // We don't have full frame left or we already have app data which needs to be processed by decrypt. - break; - } + if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) + { + break; + } - chunkSize += frameSize; - _handshakeBuffer.Discard(frameSize); + frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; + // Can process more handshake frames in single step, but we should avoid processing too much so as to preserve API boundary between handshake and I/O. + if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) || frameSize > _handshakeBuffer.ActiveLength) + { + // We don't have full frame left or we already have app data which needs to be processed by decrypt. + break; } + + chunkSize += frameSize; + _handshakeBuffer.Discard(frameSize); } return _context!.NextMessage(availableData.Slice(0, chunkSize)); @@ -1199,204 +1169,15 @@ private void ResetReadBuffer() } } - // We need at least 5 bytes to determine what we have. - private Framing DetectFraming(ReadOnlySpan bytes) - { - /* PCTv1.0 Hello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * PCT1_CLIENT_HELLO (must be equal) - * PCT1_CLIENT_VERSION_MSB (if version greater than PCTv1) - * PCT1_CLIENT_VERSION_LSB (if version greater than PCTv1) - * - * ... PCT hello ... - */ - - /* Microsoft Unihello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 Compatible Hello ... - */ - - /* SSLv2 CLIENT_HELLO starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 CLIENT_HELLO ... - */ - - /* SSLv2 SERVER_HELLO starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_SERVER_HELLO (must be equal) - * SSL2_SESSION_ID_HIT (ignore) - * SSL2_CERTIFICATE_TYPE (ignore) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 SERVER_HELLO ... - */ - - /* SSLv3 Type 2 Hello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv3) - * - * ... SSLv2 Compatible Hello ... - */ - - /* SSLv3 Type 3 Hello starts with - * 22 (HANDSHAKE MESSAGE) - * VERSION MSB - * VERSION LSB - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * HS TYPE (CLIENT_HELLO) - * 3 bytes HS record length - * HS Version - * HS Version - */ - - /* SSLv2 message codes - * SSL_MT_ERROR 0 - * SSL_MT_CLIENT_HELLO 1 - * SSL_MT_CLIENT_MASTER_KEY 2 - * SSL_MT_CLIENT_FINISHED 3 - * SSL_MT_SERVER_HELLO 4 - * SSL_MT_SERVER_VERIFY 5 - * SSL_MT_SERVER_FINISHED 6 - * SSL_MT_REQUEST_CERTIFICATE 7 - * SSL_MT_CLIENT_CERTIFICATE 8 - */ - - int version = -1; - - Debug.Assert(bytes.Length != 0, "Header buffer is not allocated."); - - // If the first byte is SSL3 HandShake, then check if we have a SSLv3 Type3 client hello. - if (bytes[0] == (byte)TlsContentType.Handshake || bytes[0] == (byte)TlsContentType.AppData - || bytes[0] == (byte)TlsContentType.Alert) - { - if (bytes.Length < 3) - { - return Framing.Invalid; - } - - version = (bytes[1] << 8) | bytes[2]; - if (version < 0x300 || version >= 0x500) - { - return Framing.Invalid; - } - - // - // This is an SSL3 Framing - // - return Framing.SinceSSL3; - } - - if (bytes.Length < 3) - { - return Framing.Invalid; - } - - if (bytes[2] > 8) - { - return Framing.Invalid; - } - - if (bytes[2] == 0x1) // SSL_MT_CLIENT_HELLO - { - if (bytes.Length >= 5) - { - version = (bytes[3] << 8) | bytes[4]; - } - } - else if (bytes[2] == 0x4) // SSL_MT_SERVER_HELLO - { - if (bytes.Length >= 7) - { - version = (bytes[5] << 8) | bytes[6]; - } - } - - if (version != -1) - { - // If this is the first packet, the client may start with an SSL2 packet - // but stating that the version is 3.x, so check the full range. - // For the subsequent packets we assume that an SSL2 packet should have a 2.x version. - if (_framing == Framing.Unknown) - { - if (version != 0x0002 && (version < 0x200 || version >= 0x500)) - { - return Framing.Invalid; - } - } - else - { - if (version != 0x0002) - { - return Framing.Invalid; - } - } - } - - // When server has replied the framing is already fixed depending on the prior client packet - if (!_context!.IsServer || _framing == Framing.Unified) - { - return Framing.BeforeSSL3; - } - - return Framing.Unified; // Will use Ssl2 just for this frame. - } - - // Returns TLS Frame size. + // Returns TLS Frame size including header size. private int GetFrameSize(ReadOnlySpan buffer) { - int payloadSize; - switch (_framing) + if (buffer.Length < SecureChannel.ReadHeaderSize) { - case Framing.Unified: - case Framing.BeforeSSL3: - if (buffer.Length < 2) - { - throw new IOException(SR.net_ssl_io_frame); - } - // Note: Cannot detect version mismatch for <= SSL2 - - if ((buffer[0] & 0x80) != 0) - { - // Two bytes - payloadSize = (((buffer[0] & 0x7f) << 8) | buffer[1]) + 2; - } - else - { - // Three bytes - payloadSize = (((buffer[0] & 0x3f) << 8) | buffer[1]) + 3; - } - - break; - case Framing.SinceSSL3: - if (buffer.Length < 5) - { - throw new IOException(SR.net_ssl_io_frame); - } - - payloadSize = ((buffer[3] << 8) | buffer[4]) + 5; - break; - default: - throw new IOException(SR.net_frame_read_size); + throw new IOException(SR.net_ssl_io_frame); } - return payloadSize; + return ((buffer[3] << 8) | buffer[4]) + SecureChannel.ReadHeaderSize; } } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs index 27c854c99168e..54187a60c6c29 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs @@ -25,6 +25,7 @@ public static void VerifyPackageInfo() } public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, @@ -35,6 +36,7 @@ public static SecurityStatusPal AcceptSecurityContext( } public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, string? targetName, @@ -45,7 +47,12 @@ public static SecurityStatusPal InitializeSecurityContext( return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { throw new PlatformNotSupportedException(); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs index 7043b7afe19f4..6b1b13ca9f2a7 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs @@ -20,7 +20,7 @@ public static Exception GetException(SecurityStatusPal status) return status.Exception ?? new Win32Exception((int)status.ErrorCode); } - internal const bool StartMutualAuthAsAnonymous = false; + internal const bool StartMutualAuthAsAnonymous = true; // SecureTransport is okay with a 0 byte input, but it produces a 0 byte output. // Since ST is not producing the framed empty message just call this false and avoid the @@ -32,16 +32,18 @@ public static void VerifyPackageInfo() } public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, string? targetName, @@ -49,10 +51,15 @@ public static SecurityStatusPal InitializeSecurityContext( ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { throw new PlatformNotSupportedException(); } @@ -224,6 +231,7 @@ public static void QueryContextConnectionInfo( } private static SecurityStatusPal HandshakeInternal( + SecureChannel secureChannel, SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, @@ -268,28 +276,11 @@ private static SecurityStatusPal HandshakeInternal( SecurityStatusPal status = PerformHandshake(sslHandle); if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { - // we should not be here if CertSelectionDelegate is null but better check before dereferencing.. - if (sslAuthenticationOptions.CertSelectionDelegate != null) + X509Certificate2? clientCertificate = secureChannel.SelectClientCertificate(out _); + if (clientCertificate != null) { - X509Certificate2? remoteCert = null; - try - { - string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context); - remoteCert = CertificateValidationPal.GetRemoteCertificate(context); - if (sslAuthenticationOptions.ClientCertificates == null) - { - sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection(); - } - X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost!, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers); - if (clientCertificate != null) - { - SafeDeleteSslContext.SetCertificate(sslContext.SslContext, SslStreamCertificateContext.Create(clientCertificate)); - } - } - finally - { - remoteCert?.Dispose(); - } + sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); + SafeDeleteSslContext.SetCertificate(sslContext.SslContext, sslAuthenticationOptions.CertificateContext); } // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK. diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs index f4c4c5424e18e..a9192681444be 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs @@ -17,23 +17,34 @@ public static Exception GetException(SecurityStatusPal status) return status.Exception ?? new Interop.OpenSsl.SslException((int)status.ErrorCode); } - internal const bool StartMutualAuthAsAnonymous = false; + internal const bool StartMutualAuthAsAnonymous = true; internal const bool CanEncryptEmptyMessage = false; public static void VerifyPackageInfo() { } - public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, - ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credential, + ref SafeDeleteSslContext? context, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, string? targetName, - ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credential, + ref SafeDeleteSslContext? context, + string? targetName, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } public static SafeFreeCredentials AcquireCredentialsHandle(SslStreamCertificateContext? certificateContext, @@ -116,7 +127,12 @@ Interop.Ssl.SslErrorCode.SSL_ERROR_NONE or return bindingHandle; } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? securityContext, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? securityContext, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { var sslContext = ((SafeDeleteSslContext)securityContext!).SslContext; SecurityStatusPal status = Interop.OpenSsl.SslRenegotiate(sslContext, out _); @@ -126,7 +142,7 @@ public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentials { return status; } - return HandshakeInternal(credentialsHandle!, ref securityContext, null, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credentialsHandle!, ref securityContext, null, ref outputBuffer, sslAuthenticationOptions); } public static void QueryContextStreamSizes(SafeDeleteContext? securityContext, out StreamSizes streamSizes) @@ -139,12 +155,7 @@ public static void QueryContextConnectionInfo(SafeDeleteSslContext securityConte connectionInfo = new SslConnectionInfo(securityContext.SslContext); } - public static byte[] ConvertAlpnProtocolListToByteArray(List applicationProtocols) - { - return Interop.Ssl.ConvertAlpnProtocolListToByteArray(applicationProtocols); - } - - private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteSslContext? context, + private static SecurityStatusPal HandshakeInternal(SecureChannel secureChannel, SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Debug.Assert(!credential.IsInvalid); @@ -163,34 +174,17 @@ private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credentia if (errorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { - if (sslAuthenticationOptions.CertSelectionDelegate != null) + X509Certificate2? clientCertificate = secureChannel.SelectClientCertificate(out _); + if (clientCertificate != null) { - X509Certificate2? remoteCert = null; - string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context); - try - { - remoteCert = CertificateValidationPal.GetRemoteCertificate(context); - if (sslAuthenticationOptions.ClientCertificates == null) - { - sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection(); - } - X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost!, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers); - if (clientCertificate != null && clientCertificate.HasPrivateKey) - { - sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); - } - } - finally - { - remoteCert?.Dispose(); - } + sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); } Interop.OpenSsl.UpdateClientCertiticate(((SafeDeleteSslContext)context).SslContext, sslAuthenticationOptions); errorCode = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, out output, out outputSize); } - // sometimes during renegotiation processing messgae does not yield new output. + // sometimes during renegotiation processing message does not yield new output. // That seems to be flaw in OpenSSL state machine and we have workaround to peek it and try it again. if (outputSize == 0 && Interop.Ssl.IsSslRenegotiatePending(((SafeDeleteSslContext)context).SslContext)) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 2fb36e595b20d..2cb0f2ec14e66 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -52,7 +52,13 @@ public static byte[] ConvertAlpnProtocolListToByteArray(List inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; @@ -82,7 +88,14 @@ public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials? c return SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode); } - public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, string? targetName, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + string? targetName, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; @@ -112,10 +125,15 @@ public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredential return SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer ) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer ) { byte[]? output = Array.Empty(); - SecurityStatusPal status = AcceptSecurityContext(ref credentialsHandle, ref context, Span.Empty, ref output, sslAuthenticationOptions); + SecurityStatusPal status = AcceptSecurityContext(secureChannel, ref credentialsHandle, ref context, Span.Empty, ref output, sslAuthenticationOptions); outputBuffer = output; return status; } diff --git a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs index 43260e11d3e7d..88d8087c42c35 100644 --- a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs +++ b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs @@ -135,10 +135,7 @@ private void AddIfNew(IList serviceNames) /// private void AddIfNew(string serviceName) { - if (string.IsNullOrEmpty(serviceName)) - { - throw new ArgumentException(SR.security_ServiceNameCollection_EmptyServiceName); - } + ArgumentException.ThrowIfNullOrEmpty(serviceName); serviceName = NormalizeServiceName(serviceName); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 50dd158345ff7..a0e76e49354fb 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -52,20 +52,6 @@ public async Task ClientAsyncAuthenticate_EachSupportedProtocol_Success(SslProto await ClientAsyncSslHelper(protocol, protocol); } - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public async Task ClientAsyncAuthenticate_Ssl2WithSelf_Success() - { - // Test Ssl2 against itself. This is a standalone test as even on versions where Windows supports Ssl2, - // it appears to have rules around not using it when other protocols are mentioned. - if (PlatformDetection.SupportsSsl2) - { -#pragma warning disable 0618 - await ClientAsyncSslHelper(SslProtocols.Ssl2, SslProtocols.Ssl2); -#pragma warning restore 0618 - } - } - [Theory] [MemberData(nameof(ProtocolMismatchData))] public async Task ClientAsyncAuthenticate_MismatchProtocols_Fails( diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx b/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx index c747b327c487e..232060e5f8317 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx @@ -72,15 +72,6 @@ NTLM authentication requires the GSSAPI plugin 'gss-ntlmssp'. - - GSSAPI security context establishment failed with status: {0} (Minor status: {1}) - - - GSSAPI encryption or signing failed with status: {0} (Minor status: {1}) - - - GSSAPI decryption or signature verification failed with status: {0} (Minor status: {1}) - Insufficient buffer space. Required: {0} Actual: {1} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 6edcace7d85a5..1e01be34ca3de 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -317,14 +317,7 @@ public async Task ServerAsyncAuthenticate_InvalidHello_Throws(bool close) await t2.WaitAsync(TestConfiguration.PassingTestTimeout); } - if (close) - { - await Assert.ThrowsAsync(() => t1); - } - else - { - await Assert.ThrowsAsync(() => t1); - } + await Assert.ThrowsAsync(() => t1); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs index 0fe53d560a4bf..95458836321cd 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs @@ -17,14 +17,16 @@ public void Constructor_NullParam_Throws() Assert.Throws(() => new ServiceNameCollection(null)); } - [Theory] - [InlineData(null)] - [InlineData("")] - public void Constructor_CollectionContainsNullOrEmpty_Throws(string item) + [Fact] + public void Constructor_CollectionContainsNullOrEmpty_Throws() { - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { item })); - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { "first", item })); - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { item, "second" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { (string)null })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "first", null })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { null, "second" })); + + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "first", "" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "", "second" })); } [Fact] @@ -184,8 +186,8 @@ public void Enumerator_BehavesAsExpected() public void Merge_NullOrEmptyString_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge((string)null)); - AssertExtensions.Throws(null, () => collection.Merge(string.Empty)); + AssertExtensions.Throws("serviceName", () => collection.Merge((string)null)); + AssertExtensions.Throws("serviceName", () => collection.Merge(string.Empty)); } [Fact] @@ -220,22 +222,22 @@ public void Merge_NullEnumerable_Throws() Assert.Throws(() => collection.Merge((IEnumerable)null)); } - [Theory] - [InlineData(null)] - [InlineData("")] - public void Merge_EnumerableContainingNullOrEmpty_Throws(string item) + [Fact] + public void Merge_EnumerableContainingNullOrEmpty_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge(new[] { item })); - AssertExtensions.Throws(null, () => collection.Merge(new[] { "third", item })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { (string)null })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "third", null })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "" })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "third", "" })); } [Fact] public void Merge_NonStringEnumerable_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge(new[] { 3 })); - AssertExtensions.Throws(null, () => collection.Merge(new[] { new object() })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { 3 })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { new object() })); } public static object[][] MergeCollectionsTestData = diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs new file mode 100644 index 0000000000000..adf161fabd49f --- /dev/null +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Threading.Tasks; +using System.Net.Test.Common; +using System.Security.Cryptography.X509Certificates; + +using Xunit; + +namespace System.Net.Security.Tests +{ + using Configuration = System.Net.Test.Common.Configuration; + + public class SslStreamMutualAuthenticationTest + { + private readonly X509Certificate2 _clientCertificate; + private readonly X509Certificate2 _serverCertificate; + + public SslStreamMutualAuthenticationTest() + { + _serverCertificate = Configuration.Certificates.GetServerCertificate(); + _clientCertificate = Configuration.Certificates.GetClientCertificate(); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public async Task SslStream_RequireClientCert_IsMutuallyAuthenticated_ReturnsTrue(bool clientCertificateRequired, bool useClientSelectionCallback) + { + (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); + using (var client = new SslStream(stream1, false, AllowAnyCertificate)) + using (var server = new SslStream(stream2, false, AllowAnyCertificate)) + { + Task t2 = client.AuthenticateAsClientAsync(new SslClientAuthenticationOptions + { + ClientCertificates = useClientSelectionCallback ? null : new X509CertificateCollection() { _clientCertificate }, + LocalCertificateSelectionCallback = useClientSelectionCallback ? ClientCertSelectionCallback : null, + TargetHost = _clientCertificate.GetNameInfo(X509NameType.SimpleName, false) + }); + Task t1 = server.AuthenticateAsServerAsync(new SslServerAuthenticationOptions + { + ServerCertificate = _serverCertificate, + ClientCertificateRequired = clientCertificateRequired + }); + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); + + if (Capability.IsTrustedRootCertificateInstalled()) + { + // https://technet.microsoft.com/en-us/library/hh831771.aspx#BKMK_Changes2012R2 + // Starting with Windows 8, the "Management of trusted issuers for client authentication" has changed: + // The behavior to send the Trusted Issuers List by default is off. + // + // In Windows 7 the Trusted Issuers List is sent within the Server Hello TLS record. This list is built + // by the server using certificates from the Trusted Root Authorities certificate store. + // The client side will use the Trusted Issuers List, if not empty, to filter proposed certificates. + + if (clientCertificateRequired) + { + Assert.True(client.IsMutuallyAuthenticated, "client.IsMutuallyAuthenticated"); + Assert.True(server.IsMutuallyAuthenticated, "server.IsMutuallyAuthenticated"); + } + else + { + // Even though the certificate was provided, it was not requested by the server and thus the client + // was not authenticated. + Assert.False(client.IsMutuallyAuthenticated, "client.IsMutuallyAuthenticated"); + Assert.False(server.IsMutuallyAuthenticated, "server.IsMutuallyAuthenticated"); + } + } + } + } + + private static bool AllowAnyCertificate( + object sender, + X509Certificate certificate, + X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + return true; + } + private X509Certificate ClientCertSelectionCallback( + object sender, + string targetHost, + X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, + string[] acceptableIssuers) + { + return _clientCertificate; + } + } +} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index ce44c04792979..aec32cd84a418 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -352,21 +352,25 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( // Send application data instead of Client hello. await client.WriteAsync(new byte[500], cts.Token); - // Fail as it is not allowed to receive non hnadshake frames during handshake. + // Fail as it is not allowed to receive non handshake frames during handshake. await Assert.ThrowsAsync(()=> t); } } [ConditionalFact(nameof(SupportsRenegotiation))] [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] - public async Task SslStream_NegotiateClientCertificateAsync_ServerDontDrainClientData() + public async Task SslStream_NegotiateClientCertificateAsync_IncompleteIncomingTlsFrame_Throws() { using CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(TestConfiguration.PassingTestTimeout); - (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); - using (client) - using (server) + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); + + // use ManualChunkingStream in the middle to enforce partial TLS frame receive later + ManualChunkingStream clientChunkingStream = new ManualChunkingStream(clientStream, false); + + using (SslStream server = new SslStream(serverStream)) + using (SslStream client = new SslStream(clientChunkingStream)) { using X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate(); using X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate(); @@ -386,26 +390,86 @@ public async Task SslStream_NegotiateClientCertificateAsync_ServerDontDrainClien await TestConfiguration.WhenAllOrAnyFailedWithTimeout( client.AuthenticateAsClientAsync(clientOptions, cts.Token), server.AuthenticateAsServerAsync(serverOptions, cts.Token)); - Assert.Null(server.RemoteCertificate); - // Send application data instead of Client hello. - await client.WriteAsync(new byte[500], cts.Token); - // Server don't drain the client data - await server.ReadAsync(new byte[1]); - // Fail as it is not allowed to receive non hnadshake frames during handshake. + // manually approve all future writes + clientChunkingStream.SetWriteChunking(true); + + // TLS packets are maximum 16 kB, sending 20 kB of data guarantees at least 2 packets to be sent + byte[] buffer = new byte[20 * 1024]; + client.Write(buffer); + + // delay receiving last few B so that only an incomplete TLS frame is received + await clientChunkingStream.CommitWriteAsync(clientChunkingStream.PendingWriteLength - 100); + int read = await server.ReadAsync(buffer, cts.Token); + + // Fail as there are still some undrained data (incomplete incoming TLS frame) await Assert.ThrowsAsync(()=> server.NegotiateClientCertificateAsync(cts.Token) ); - // Drain client data. - await server.ReadAsync(new byte[499]); + // no more delaying needed, drain client data. + clientChunkingStream.SetWriteChunking(false); + while (read < buffer.Length) + { + read += await server.ReadAsync(buffer); + } + // Verify that the session is usable even renego request failed. await TestHelper.PingPong(client, server, cts.Token); await TestHelper.PingPong(server, client, cts.Token); } } + [ConditionalFact(nameof(SupportsRenegotiation))] + [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] + public async Task SslStream_NegotiateClientCertificateAsync_PendingDecryptedData_Throws() + { + using CancellationTokenSource cts = new CancellationTokenSource(); + cts.CancelAfter(TestConfiguration.PassingTestTimeout); + + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + { + using X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate(); + using X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate(); + + SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() + { + TargetHost = Guid.NewGuid().ToString("N"), + ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate }) + }; + clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; + + SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() { ServerCertificate = serverCertificate }; + serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + client.AuthenticateAsClientAsync(clientOptions, cts.Token), + server.AuthenticateAsServerAsync(serverOptions, cts.Token)); + + await TestHelper.PingPong(client, server, cts.Token); + Assert.Null(server.RemoteCertificate); + + // This should go out in single TLS frame + await client.WriteAsync(new byte[200], cts.Token); + byte[] readBuffer = new byte[10]; + // when we read part of the frame, remaining part should left decrypted + int read = await server.ReadAsync(readBuffer, cts.Token); + + await Assert.ThrowsAsync(() => server.NegotiateClientCertificateAsync(cts.Token)); + + while (read < 200) + { + read += await server.ReadAsync(readBuffer, cts.Token); + } + + // verify that the session is usable with or without client's certificate + await TestHelper.PingPong(client, server, cts.Token); + await TestHelper.PingPong(server, client, cts.Token); + } + } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsTls13))] [InlineData(true)] @@ -587,46 +651,6 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( } } - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public async Task NegotiateClientCertificateAsync_PendingData_Throws() - { - using CancellationTokenSource cts = new CancellationTokenSource(); - cts.CancelAfter(TestConfiguration.PassingTestTimeout); - - (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); - using (client) - using (server) - using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate()) - using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate()) - { - SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() - { - TargetHost = Guid.NewGuid().ToString("N"), - ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate }) - }; - clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; - - SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() { ServerCertificate = serverCertificate }; - serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; - - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - client.AuthenticateAsClientAsync(clientOptions, cts.Token), - server.AuthenticateAsServerAsync(serverOptions, cts.Token)); - - await TestHelper.PingPong(client, server, cts.Token); - Assert.Null(server.RemoteCertificate); - - // This should go out in single TLS frame - await client.WriteAsync(new byte[200], cts.Token); - byte[] readBuffer = new byte[10]; - // when we read part of the frame, remaining part should left decrypted - await server.ReadAsync(readBuffer, cts.Token); - - await Assert.ThrowsAsync(() => server.NegotiateClientCertificateAsync(cts.Token)); - } - } - [Fact] public async Task SslStream_NestedAuth_Throws() { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index a6a21cc91e155..72ef0e0c58132 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -28,6 +28,7 @@ + @@ -52,6 +53,8 @@ Link="Common\System\Net\SslStreamCertificatePolicy.cs" /> + input = new byte[0]; + ReadOnlySpan expected = new byte[] { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }; + Verify(input, expected); + } + + // // MD4("a") = bde52cb31de33e46245e05fbdbd6fb24 + [Fact] + public void TryEncrypt_SingleLetter() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("a")); + ReadOnlySpan expected = new byte[] { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }; + Verify(input, expected); + } + + // MD4("abc") = a448017aaf21d8525fc10ae87aa6729d + [Fact] + public void TryEncrypt_ThreeLetters() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("abc")); + ReadOnlySpan expected = new byte[] { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }; + Verify(input, expected); + } + + // MD4("message digest") = d9130a8164549fe818874806e1c7014b + [Fact] + public void TryEncrypt_Phrase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("message digest")); + ReadOnlySpan expected = new byte[] { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }; + Verify(input, expected); + } + + // MD4("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 + [Fact] + public void TryEncrypt_AlphabetInLowercase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("abcdefghijklmnopqrstuvwxyz")); + ReadOnlySpan expected = new byte[] { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 + [Fact] + public void TryEncrypt_AlphabetInUpperLowerCasesAndNumbers() + { + ReadOnlySpan input = new ReadOnlySpan((Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))); + ReadOnlySpan expected = new byte[] { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }; + Verify(input, expected); + } + + // MD4("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 + [Fact] + public void TryEncrypt_RepeatedSequenceOfNumbers() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); + ReadOnlySpan expected = new byte[] { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012") = 14fdf2056bf88b3491c385d8ac4f48e6 + // 55 bytes (padLen == 56 - 55 => 1) + [Fact] + public void TryEncrypt_55bytes_HitsEdgeCaseForPaddingLength() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012")); + ReadOnlySpan expected = new byte[] { 0x14, 0xfd, 0xf2, 0x05, 0x6b, 0xf8, 0x8b, 0x34, 0x91, 0xc3, 0x85, 0xd8, 0xac, 0x4f, 0x48, 0xe6 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123") = db837dbb6098a50a2d3974bc1cc76133 + // 56 bytes (padLen == 120 - 56 => 64) + [Fact] + public void TryEncrypt_56bytes_HitsEdgeCaseForPaddingLength() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123")); + ReadOnlySpan expected = new byte[] { 0xdb, 0x83, 0x7d, 0xbb, 0x60, 0x98, 0xa5, 0x0a, 0x2d, 0x39, 0x74, 0xbc, 0x1c, 0xc7, 0x61, 0x33 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890") = ce64c40ecfbe896462f3c1a925884624 + [Fact] + public void TryEncrypt_63bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890")); + ReadOnlySpan expected = new byte[] { 0xce, 0x64, 0xc4, 0x0e, 0xcf, 0xbe, 0x89, 0x64, 0x62, 0xf3, 0xc1, 0xa9, 0x25, 0x88, 0x46, 0x24 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901") = 4b0e77758d2ede1eb21d267d492ae70b + [Fact] + public void TryEncrypt_64bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901")); + ReadOnlySpan expected = new byte[] { 0x4b, 0x0e, 0x77, 0x75, 0x8d, 0x2e, 0xde, 0x1e, 0xb2, 0x1d, 0x26, 0x7d, 0x49, 0x2a, 0xe7, 0x0b }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012") = 3b46ad159b3fd800d254e3c4cc71fe36 + [Fact] + public void TryEncrypt_65bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012")); + ReadOnlySpan expected = new byte[] { 0x3b, 0x46, 0xad, 0x15, 0x9b, 0x3f, 0xd8, 0x00, 0xd2, 0x54, 0xe3, 0xc4, 0xcc, 0x71, 0xfe, 0x36 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890") = a3e23048e4ade47a0f00fa8aed2a0248 + [Fact] + public void TryEncrypt_127bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890")); + ReadOnlySpan expected = new byte[] { 0xa3, 0xe2, 0x30, 0x48, 0xe4, 0xad, 0xe4, 0x7a, 0x0f, 0x00, 0xfa, 0x8a, 0xed, 0x2a, 0x02, 0x48 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901") = de49da96c105be37b242f2bee86c4759 + [Fact] + public void TryEncrypt_128bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901")); + ReadOnlySpan expected = new byte[] { 0xde, 0x49, 0xda, 0x96, 0xc1, 0x05, 0xbe, 0x37, 0xb2, 0x42, 0xf2, 0xbe, 0xe8, 0x6c, 0x47, 0x59 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012") = a6c10c320f8827d08248a2d8b124b040 + [Fact] + public void TryEncrypt_129bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012")); + ReadOnlySpan expected = new byte[] { 0xa6, 0xc1, 0x0c, 0x32, 0x0f, 0x88, 0x27, 0xd0, 0x82, 0x48, 0xa2, 0xd8, 0xb1, 0x24, 0xb0, 0x40 }; + Verify(input, expected); + } + + private void Verify(ReadOnlySpan input, ReadOnlySpan expected) + { + Span output = stackalloc byte[expected.Length]; + MD4.HashData(input, output); + Assert.Equal(expected.ToArray(), output.ToArray()); + } + } +} diff --git a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj index da4dde4e192b9..28b3f81b02b3d 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj @@ -10,13 +10,17 @@ 436 $(NoWarn);3021 - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-Android annotations true + + + + diff --git a/src/libraries/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj b/src/libraries/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj index 54aae96735715..b67c9ae2f0d41 100644 --- a/src/libraries/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj +++ b/src/libraries/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj @@ -18,6 +18,6 @@ - + diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 212c063b3b330..e813cca044ee0 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -74,13 +74,14 @@ public enum IOControlCode : long [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] AddressListSort = (long)3355443225, } - public partial struct IPPacketInformation + public partial struct IPPacketInformation : System.IEquatable { private object _dummy; private int _dummyPrimitive; public System.Net.IPAddress Address { get { throw null; } } public int Interface { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? comparand) { throw null; } + public bool Equals(System.Net.Sockets.IPPacketInformation other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } public static bool operator !=(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } diff --git a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx index 69eff9dbb985e..57d1a94b6ae6b 100644 --- a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx @@ -324,9 +324,6 @@ System.Net.Sockets is not supported on this platform. - - This platform does not support receiving data with Socket.BeginAccept/EndAccept. Instead, make a separate call to ReceiveAsync or BeginReceive/EndReceive. - Handle is already used by another Socket. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs index 06d4eca31750b..b0597b626c480 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs @@ -5,7 +5,7 @@ namespace System.Net.Sockets { - public struct IPPacketInformation + public struct IPPacketInformation : IEquatable { private readonly IPAddress _address; private readonly int _networkInterface; @@ -16,41 +16,27 @@ internal IPPacketInformation(IPAddress address, int networkInterface) _networkInterface = networkInterface; } - public IPAddress Address - { - get - { - return _address; - } - } + public IPAddress Address => _address; - public int Interface - { - get - { - return _networkInterface; - } - } + public int Interface => _networkInterface; - public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return packetInformation1._networkInterface == packetInformation2._networkInterface && - ((packetInformation1._address == null && packetInformation2._address == null) || - (packetInformation1._address != null && packetInformation1._address.Equals(packetInformation2._address))); - } + public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + packetInformation1.Equals(packetInformation2); - public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return !(packetInformation1 == packetInformation2); - } + public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + !packetInformation1.Equals(packetInformation2); public override bool Equals([NotNullWhen(true)] object? comparand) => - comparand is IPPacketInformation other && this == other; + comparand is IPPacketInformation other && Equals(other); - public override int GetHashCode() - { - return unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + - (_address == null ? 0 : _address.GetHashCode()); - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(IPPacketInformation other) => + _networkInterface == other._networkInterface && + (_address is null ? other._address is null : _address.Equals(other._address)); + + public override int GetHashCode() => + unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + (_address?.GetHashCode() ?? 0); } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs index 6c79043631eb7..faf0d9f204c7c 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs @@ -153,7 +153,7 @@ public IList>? BufferList if (!_buffer.Equals(default)) { // Can't have both set - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(Buffer))); + throw new ArgumentException(SR.net_ambiguousbuffers); } // Copy the user-provided list into our internal buffer list, @@ -358,7 +358,7 @@ public void SetBuffer(byte[]? buffer, int offset, int count) // Can't have both Buffer and BufferList. if (_bufferList != null) { - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + throw new ArgumentException(SR.net_ambiguousbuffers); } // Offset and count can't be negative and the @@ -391,7 +391,7 @@ public void SetBuffer(Memory buffer) { if (buffer.Length != 0 && _bufferList != null) { - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + throw new ArgumentException(SR.net_ambiguousbuffers); } _buffer = buffer; @@ -559,7 +559,7 @@ internal void StartOperationAccept() // Caller specified a buffer - see if it is large enough if (_count < _acceptAddressBufferCount) { - throw new ArgumentException(SR.Format(SR.net_buffercounttoosmall, nameof(Count))); + throw new ArgumentException(SR.net_buffercounttoosmall, nameof(Count)); } } else diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs index 443924b66d2b4..19dbc7f470d00 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs @@ -13,7 +13,10 @@ public class IPPacketInformationTest public void Equals_DefaultValues_Success() { Assert.Equal(default(IPPacketInformation), default(IPPacketInformation)); + Assert.True(default(IPPacketInformation) == default(IPPacketInformation)); + Assert.True(default(IPPacketInformation).Equals(default(IPPacketInformation))); + Assert.False(default(IPPacketInformation) != default(IPPacketInformation)); } @@ -31,10 +34,14 @@ public void Equals_NonDefaultValue_Success() Assert.Equal(packetInfo, packetInfoCopy); Assert.True(packetInfo == packetInfoCopy); + Assert.True(packetInfo.Equals(packetInfoCopy)); + Assert.True(packetInfo.Equals((object)packetInfoCopy)); Assert.False(packetInfo != packetInfoCopy); Assert.NotEqual(default, packetInfo); Assert.False(packetInfo == default(IPPacketInformation)); + Assert.False(packetInfo.Equals(default(IPPacketInformation))); + Assert.False(packetInfo.Equals((object)default(IPPacketInformation))); Assert.True(packetInfo != default(IPPacketInformation)); int ignored = packetInfo.Interface; // just make sure it doesn't throw, nothing else to verify diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs index 8e257352fd18c..b59c5ebd92a33 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Drawing.Drawing2D; using System.IO; using System.IO.Pipes; using System.Runtime.Serialization.Formatters.Binary; diff --git a/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx b/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx index eb1e5a6487164..86b29067c6aa9 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -63,9 +64,6 @@ This collection holds request headers and cannot contain the specified response header. - - The parameter '{0}' cannot be an empty string. - Specified value has invalid Control characters. diff --git a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs index 1a97af3ccfb4f..99563163a1ec7 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs +++ b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs @@ -344,14 +344,7 @@ public void Add(string header) public override void Add(string name, string? value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptyStringCall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); name = HttpValidationHelpers.CheckBadHeaderNameChars(name); value = HttpValidationHelpers.CheckBadHeaderValueChars(value); diff --git a/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.cs b/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.cs index 99b154b7d4c6f..5c19b271bc2cb 100644 --- a/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.cs +++ b/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.cs @@ -18,13 +18,13 @@ public WebProxy() { } protected WebProxy(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } public WebProxy(string? Address) { } public WebProxy(string? Address, bool BypassOnLocal) { } - public WebProxy(string? Address, bool BypassOnLocal, string[]? BypassList) { } - public WebProxy(string? Address, bool BypassOnLocal, string[]? BypassList, System.Net.ICredentials? Credentials) { } + public WebProxy(string? Address, bool BypassOnLocal, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant)] string[]? BypassList) { } + public WebProxy(string? Address, bool BypassOnLocal, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant)] string[]? BypassList, System.Net.ICredentials? Credentials) { } public WebProxy(string Host, int Port) { } public WebProxy(System.Uri? Address) { } public WebProxy(System.Uri? Address, bool BypassOnLocal) { } - public WebProxy(System.Uri? Address, bool BypassOnLocal, string[]? BypassList) { } - public WebProxy(System.Uri? Address, bool BypassOnLocal, string[]? BypassList, System.Net.ICredentials? Credentials) { } + public WebProxy(System.Uri? Address, bool BypassOnLocal, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant)] string[]? BypassList) { } + public WebProxy(System.Uri? Address, bool BypassOnLocal, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant)] string[]? BypassList, System.Net.ICredentials? Credentials) { } public System.Uri? Address { get { throw null; } set { } } public System.Collections.ArrayList BypassArrayList { get { throw null; } } [System.Diagnostics.CodeAnalysis.AllowNullAttribute] diff --git a/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.csproj b/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.csproj index 477ecb4cfa2a3..43de764895500 100644 --- a/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.csproj +++ b/src/libraries/System.Net.WebProxy/ref/System.Net.WebProxy.csproj @@ -11,5 +11,6 @@ + - \ No newline at end of file + diff --git a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs index 7e1b3fbe01f1a..a8b9d60651d8b 100644 --- a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs +++ b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs @@ -20,9 +20,9 @@ public WebProxy(Uri? Address) : this(Address, false, null, null) { } public WebProxy(Uri? Address, bool BypassOnLocal) : this(Address, BypassOnLocal, null, null) { } - public WebProxy(Uri? Address, bool BypassOnLocal, string[]? BypassList) : this(Address, BypassOnLocal, BypassList, null) { } + public WebProxy(Uri? Address, bool BypassOnLocal, [StringSyntax(StringSyntaxAttribute.Regex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] string[]? BypassList) : this(Address, BypassOnLocal, BypassList, null) { } - public WebProxy(Uri? Address, bool BypassOnLocal, string[]? BypassList, ICredentials? Credentials) + public WebProxy(Uri? Address, bool BypassOnLocal, [StringSyntax(StringSyntaxAttribute.Regex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] string[]? BypassList, ICredentials? Credentials) { this.Address = Address; this.Credentials = Credentials; @@ -49,12 +49,12 @@ public WebProxy(string? Address, bool BypassOnLocal) { } - public WebProxy(string? Address, bool BypassOnLocal, string[]? BypassList) + public WebProxy(string? Address, bool BypassOnLocal, [StringSyntax(StringSyntaxAttribute.Regex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] string[]? BypassList) : this(CreateProxyUri(Address), BypassOnLocal, BypassList, null) { } - public WebProxy(string? Address, bool BypassOnLocal, string[]? BypassList, ICredentials? Credentials) + public WebProxy(string? Address, bool BypassOnLocal, [StringSyntax(StringSyntaxAttribute.Regex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] string[]? BypassList, ICredentials? Credentials) : this(CreateProxyUri(Address), BypassOnLocal, BypassList, Credentials) { } diff --git a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx index 7b4718b554a15..360d9f9a337e1 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx @@ -123,21 +123,6 @@ The requested security protocol is not supported. - - Client certificates in UWP are unsupported in Windows 10 version 1703 and earlier versions. Please upgrade Windows 10 to a later release. - - - Client certificate was not found in the personal (\"MY\") certificate store. In UWP, client certificates are only supported if they have been added to that certificate store. - - - ClientWebSocketOptions.RemoteCertificateValidationCallback is not supported on this platform. - - - Connection was aborted. - - - WebSocket binary type '{0}' not supported. - The WebSocket failed to negotiate max server window bits. The client requested {0} but the server responded with {1}. diff --git a/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs index 209a6f10ff23b..a5d97a9a42188 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs @@ -17,6 +17,7 @@ public AbortTest(ITestOutputHelper output) : base(output) { } [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63673", TestPlatforms.Browser)] public async Task Abort_ConnectAndAbort_ThrowsWebSocketExceptionWithmessage(Uri server) { using (var cws = new ClientWebSocket()) diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs index 31c375a9cd499..75b378f505636 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs @@ -170,6 +170,7 @@ public async Task ConnectAsync_CookieHeaders_Success(Uri server) [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63681", TestPlatforms.Browser)] public async Task ConnectAsync_PassNoSubProtocol_ServerRequires_ThrowsWebSocketException(Uri server) { const string AcceptedProtocol = "CustomProtocol"; @@ -256,6 +257,7 @@ public async Task ConnectAndCloseAsync_UseProxyServer_ExpectedClosedState(Uri se } [ConditionalFact(nameof(WebSocketsSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63672", TestPlatforms.Browser)] public async Task ConnectAsync_CancellationRequestedBeforeConnect_ThrowsOperationCanceledException() { using (var clientSocket = new ClientWebSocket()) @@ -268,6 +270,7 @@ public async Task ConnectAsync_CancellationRequestedBeforeConnect_ThrowsOperatio } [ConditionalFact(nameof(WebSocketsSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63672", TestPlatforms.Browser)] public async Task ConnectAsync_CancellationRequestedInflightConnect_ThrowsOperationCanceledException() { using (var clientSocket = new ClientWebSocket()) @@ -281,6 +284,7 @@ public async Task ConnectAsync_CancellationRequestedInflightConnect_ThrowsOperat [ConditionalFact(nameof(WebSocketsSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34690", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63671", TestPlatforms.Browser)] public async Task ConnectAsync_CancellationRequestedAfterConnect_ThrowsOperationCanceledException() { var releaseServer = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj index 956ee4d414612..c553a385144b3 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj +++ b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj @@ -6,14 +6,35 @@ + WasmTestOnBrowser - $(TestArchiveRoot)browseronly/ + $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Net.WebSockets.Client/tests/WebSocketHelper.cs b/src/libraries/System.Net.WebSockets.Client/tests/WebSocketHelper.cs index 1f0ccd5591321..0782f9d5232e4 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/WebSocketHelper.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/WebSocketHelper.cs @@ -125,7 +125,7 @@ public static async Task Retry(ITestOutputHelper output, Func> fun private static bool InitWebSocketSupported() { ClientWebSocket cws = null; - if (PlatformDetection.IsBrowser && !PlatformDetection.IsBrowserDomSupported) + if (PlatformDetection.IsBrowser && !PlatformDetection.IsWebSocketSupported) { return false; } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/package-lock.json b/src/libraries/System.Net.WebSockets.Client/tests/package-lock.json new file mode 100644 index 0000000000000..55a66ba4d40f9 --- /dev/null +++ b/src/libraries/System.Net.WebSockets.Client/tests/package-lock.json @@ -0,0 +1,44 @@ +{ + "name": "system.net.websockets.client.tests", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "system.net.websockets.client.tests", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "ws": "^8.4.0" + } + }, + "node_modules/ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "requires": {} + } + } +} diff --git a/src/libraries/System.Net.WebSockets.Client/tests/package.json b/src/libraries/System.Net.WebSockets.Client/tests/package.json new file mode 100644 index 0000000000000..cb5a738db17e5 --- /dev/null +++ b/src/libraries/System.Net.WebSockets.Client/tests/package.json @@ -0,0 +1,7 @@ +{ + "name": "system.net.websockets.client.tests", + "private": true, + "dependencies": { + "ws": "8.4.0" + } +} diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index 8106173a6378e..13a4c44616993 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -873,8 +873,8 @@ public void Vector2ConstructorTest2() public void Vector2ConstructorTest3() { Vector2 target = new Vector2(float.NaN, float.MaxValue); - Assert.Equal(target.X, float.NaN); - Assert.Equal(target.Y, float.MaxValue); + Assert.Equal(float.NaN, target.X); + Assert.Equal(float.MaxValue, target.Y); } // A test for Vector2f (float) diff --git a/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs b/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs new file mode 100644 index 0000000000000..a1f427d0af7f1 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs @@ -0,0 +1,24 @@ +// 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.Runtime.InteropServices; + +namespace Internal +{ + public static partial class Console + { + public static unsafe void Write(string s) + { + Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Debug, "DOTNET", s ?? string.Empty); + } + + public static partial class Error + { + public static unsafe void Write(string s) + { + Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Error, "DOTNET", s ?? string.Empty); + } + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs index 32e242e0d8e4c..8a601345ee00a 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs @@ -57,6 +57,12 @@ internal bool SupportsRandomAccess internal void EnsureThreadPoolBindingInitialized() { /* nop */ } + internal bool TryGetCachedLength(out long cachedLength) + { + cachedLength = -1; + return false; + } + private static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode, Func? createOpenException) { @@ -180,7 +186,7 @@ internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess a { long fileLength; Interop.Sys.Permissions filePermissions; - return Open(fullPath, mode, access, share, options, preallocationSize, openPermissions, out fileLength, out filePermissions, null); + return Open(fullPath, mode, access, share, options, preallocationSize, openPermissions, out fileLength, out filePermissions, createOpenException); } private static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize, @@ -504,6 +510,13 @@ private bool GetCanSeek() return canSeek == NullableBool.True; } + internal long GetFileLength() + { + int result = Interop.Sys.FStat(this, out Interop.Sys.FileStatus status); + FileStreamHelpers.CheckFileCall(result, Path); + return status.Size; + } + private enum NullableBool { Undefined = 0, diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs index 3352f0194e73b..d6bbfdd166bf0 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.IO; -using System.IO.Strategies; using System.Runtime.InteropServices; using System.Threading; @@ -13,6 +12,8 @@ namespace Microsoft.Win32.SafeHandles public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid { internal const FileOptions NoBuffering = (FileOptions)0x20000000; + private long _length = -1; // negative means that hasn't been fetched. + private bool _lengthCanBeCached; // file has been opened for reading and not shared for writing. private volatile FileOptions _fileOptions = (FileOptions)(-1); private volatile int _fileType = -1; @@ -22,10 +23,18 @@ public SafeFileHandle() : base(true) public bool IsAsync => (GetFileOptions() & FileOptions.Asynchronous) != 0; + internal bool IsNoBuffering => (GetFileOptions() & NoBuffering) != 0; + internal bool CanSeek => !IsClosed && GetFileType() == Interop.Kernel32.FileTypes.FILE_TYPE_DISK; internal ThreadPoolBoundHandle? ThreadPoolBinding { get; set; } + internal bool TryGetCachedLength(out long cachedLength) + { + cachedLength = _length; + return _lengthCanBeCached && cachedLength >= 0; + } + internal static unsafe SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize) { using (DisableMediaInsertionPrompt.Create()) @@ -103,6 +112,7 @@ private static unsafe SafeFileHandle CreateFile(string fullPath, FileMode mode, fileHandle._path = fullPath; fileHandle._fileOptions = options; + fileHandle._lengthCanBeCached = (share & FileShare.Write) == 0 && (access & FileAccess.Write) == 0; return fileHandle; } @@ -252,5 +262,34 @@ internal int GetFileType() return fileType; } + + internal long GetFileLength() + { + if (!_lengthCanBeCached) + { + return GetFileLengthCore(); + } + + // On Windows, when the file is locked for writes we can cache file length + // in memory and avoid subsequent native calls which are expensive. + if (_length < 0) + { + _length = GetFileLengthCore(); + } + + return _length; + + unsafe long GetFileLengthCore() + { + Interop.Kernel32.FILE_STANDARD_INFO info; + + if (!Interop.Kernel32.GetFileInformationByHandleEx(this, Interop.Kernel32.FileStandardInfo, &info, (uint)sizeof(Interop.Kernel32.FILE_STANDARD_INFO))) + { + throw Win32Marshal.GetExceptionForLastWin32Error(Path); + } + + return info.EndOfFile; + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index f98789424343b..4c95e4d31c954 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -528,6 +528,9 @@ Type passed must be an interface. + + Object must be of type NFloat. + Type must be a Pointer. @@ -786,6 +789,9 @@ Unknown TypeCode value. + + The program executed an instruction that was thought to be unreachable. + Missing parameter does not have a default value. @@ -903,9 +909,6 @@ Cannot use function evaluation to create a TypedReference object. - - Cannot get TypeToken for a ByRef type. - Cannot set parent to an interface. @@ -1002,18 +1005,12 @@ EmitWriteLine does not support this field or local type. - - Decimal separator cannot be the empty string. - Empty file name is not legal. Empty name is not legal. - - Empty path name is not legal. - Waithandle array may not be empty. @@ -1056,6 +1053,9 @@ Must be an array type. + + The handle has no associated path. + Left to right characters may not be mixed with right to left characters in IDN labels. @@ -1107,8 +1107,8 @@ Target array type is not compatible with the type of items in the collection. - - Assembly names may not begin with whitespace or contain the characters '/', or '\\' or ':'. + + The given assembly name or codebase was invalid. Not a valid calendar for the given culture. @@ -1480,9 +1480,6 @@ The first char in the string is the null character. - - String cannot be of zero length. - The structure must not be a value class. @@ -3880,9 +3877,6 @@ A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property. - - The given assembly name or codebase was invalid - Invalid assembly public key. diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 6232e26da4781..b2ddfac32f143 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -57,8 +57,8 @@ - - + + @@ -254,15 +254,17 @@ - - - - + + + + + + @@ -284,6 +286,7 @@ + @@ -561,6 +564,8 @@ + + @@ -712,6 +717,7 @@ + @@ -743,6 +749,7 @@ + @@ -1059,6 +1066,7 @@ + @@ -2123,7 +2131,14 @@ Common\System\IO\PathInternal.Unix.cs - + + + + Common\Interop\Android\Interop.Logcat.cs + + + Common\Interop\Android\Interop.Libraries.cs + @@ -2132,7 +2147,7 @@ - + @@ -2177,10 +2192,8 @@ - - + + Common\Interop\Unix\System.Native\Interop.GetPwUid.cs @@ -2193,12 +2206,13 @@ - + - + + @@ -2364,4 +2378,4 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 6b28c7b2a561d..87488c1dfe280 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -94,10 +94,7 @@ internal static void OnProcessExit() /// A return value of true represents that the switch was set and contains the value of the switch public static bool TryGetSwitch(string switchName, out bool isEnabled) { - if (switchName == null) - throw new ArgumentNullException(nameof(switchName)); - if (switchName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(switchName)); + ArgumentException.ThrowIfNullOrEmpty(switchName); if (s_switches != null) { @@ -124,10 +121,7 @@ public static bool TryGetSwitch(string switchName, out bool isEnabled) /// The value to assign public static void SetSwitch(string switchName, bool isEnabled) { - if (switchName == null) - throw new ArgumentNullException(nameof(switchName)); - if (switchName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(switchName)); + ArgumentException.ThrowIfNullOrEmpty(switchName); if (s_switches == null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index 3e4e8a2317e4d..cff98ca55ee2f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -80,13 +80,10 @@ public event EventHandler? ProcessExit public string ApplyPolicy(string assemblyName) { - if (assemblyName == null) - { - throw new ArgumentNullException(nameof(assemblyName)); - } - if (assemblyName.Length == 0 || assemblyName[0] == '\0') + ArgumentException.ThrowIfNullOrEmpty(assemblyName); + if (assemblyName[0] == '\0') { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(assemblyName)); + throw new ArgumentException(SR.Argument_EmptyString, nameof(assemblyName)); } return assemblyName; diff --git a/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs b/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs index ed537c244392b..1511f8db1bd7a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs @@ -12,10 +12,9 @@ public sealed class ApplicationId public ApplicationId(byte[] publicKeyToken, string name, Version version, string? processorArchitecture, string? culture) { - if (name == null) throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) throw new ArgumentException(SR.Argument_EmptyString, nameof(name)); - if (version == null) throw new ArgumentNullException(nameof(version)); - if (publicKeyToken == null) throw new ArgumentNullException(nameof(publicKeyToken)); + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentNullException.ThrowIfNull(version); + ArgumentNullException.ThrowIfNull(publicKeyToken); _publicKeyToken = (byte[])publicKeyToken.Clone(); Name = name; diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs index 3e223bd4789fd..0e898e511a46c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs @@ -10,6 +10,8 @@ ** =============================================================================*/ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -97,5 +99,24 @@ private void SetMessageField() } public virtual string? ParamName => _paramName; + + /// Throws an exception if is null or empty. + /// The string argument to validate as non-null and non-empty. + /// The name of the parameter with which corresponds. + /// is null. + /// is empty. + public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression("argument")] string? paramName = null) + { + if (string.IsNullOrEmpty(argument)) + { + ThrowNullOrEmptyException(argument, paramName); + } + } + + [DoesNotReturn] + private static void ThrowNullOrEmptyException(string? argument, string? paramName) => + throw (argument is null ? + new ArgumentNullException(paramName) : + new ArgumentException(SR.Argument_EmptyString, paramName)); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs index 06c31c4d6e009..2d6c817b87268 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs @@ -26,8 +26,16 @@ namespace System // (ie, users could assign a new value to the old location). [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] +#pragma warning disable CA1066 // adding IEquatable implementation could change semantics of code like that in xunit that queries for IEquatable vs enumerating contents public readonly struct ArraySegment : IList, IReadOnlyList +#pragma warning restore CA1066 { + // ArraySegment doesn't implement IEquatable, even though it provides a strongly-typed + // Equals(T), as that results in different comparison semantics than comparing item-by-item + // the elements returned from its IEnumerable implementation. This then is a breaking change + // for usage like that in xunit's Assert.Equal, which will prioritize using an instance's IEquatable + // over its IEnumerable. + // Do not replace the array allocation with Array.Empty. We don't want to have the overhead of // instantiating another generic type in addition to ArraySegment for new type parameters. #pragma warning disable CA1825 @@ -120,7 +128,7 @@ public void CopyTo(ArraySegment destination) } public override bool Equals([NotNullWhen(true)] object? obj) => - obj is ArraySegment && Equals((ArraySegment)obj); + obj is ArraySegment other && Equals(other); public bool Equals(ArraySegment obj) => obj._array == _array && obj._offset == _offset && obj._count == _count; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs index 01b9cdb3c737a..d311cd0c94bbd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs @@ -260,7 +260,7 @@ public Hashtable(int capacity, float loadFactor) if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum); if (!(loadFactor >= 0.1f && loadFactor <= 1.0f)) - throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.Format(SR.ArgumentOutOfRange_HashtableLoadFactor, .1, 1.0)); + throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.ArgumentOutOfRange_HashtableLoadFactor); // Based on perf work, .72 is the optimal load factor for this table. _loadFactor = 0.72f * loadFactor; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index e6fbd54165329..25bd0d15bb8b3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -817,15 +817,13 @@ public string ToString(string? format, IFormatProvider? provider) return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); default: - charsWritten = 0; - return false; + throw new FormatException(SR.Argument_BadFormatSpecifier); } } if (!DateTimeFormat.IsValidCustomDateFormat(format, throwOnError: false)) { - charsWritten = 0; - return false; + throw new FormatException(SR.Format(SR.Format_DateTimeOnlyContainsNoneDateParts, format.ToString(), nameof(DateOnly))); } return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index 1783d197b8ab8..53a7b278fd212 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -1134,7 +1134,7 @@ public static DateTime Parse(ReadOnlySpan s, IFormatProvider? provider = n // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTime ParseExact(string s, string format, IFormatProvider? provider) + public static DateTime ParseExact(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format); @@ -1145,7 +1145,7 @@ public static DateTime ParseExact(string s, string format, IFormatProvider? prov // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTime ParseExact(string s, string format, IFormatProvider? provider, DateTimeStyles style) + public static DateTime ParseExact(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format, IFormatProvider? provider, DateTimeStyles style) { DateTimeFormatInfo.ValidateStyles(style); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); @@ -1153,20 +1153,20 @@ public static DateTime ParseExact(string s, string format, IFormatProvider? prov return DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style); } - public static DateTime ParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) + public static DateTime ParseExact(ReadOnlySpan s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) { DateTimeFormatInfo.ValidateStyles(style); return DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style); } - public static DateTime ParseExact(string s, string[] formats, IFormatProvider? provider, DateTimeStyles style) + public static DateTime ParseExact(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats, IFormatProvider? provider, DateTimeStyles style) { DateTimeFormatInfo.ValidateStyles(style); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style); } - public static DateTime ParseExact(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) + public static DateTime ParseExact(ReadOnlySpan s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) { DateTimeFormatInfo.ValidateStyles(style); return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style); @@ -1282,7 +1282,7 @@ public override string ToString() return DateTimeFormat.Format(this, null, null); } - public string ToString(string? format) + public string ToString([StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format) { return DateTimeFormat.Format(this, format, null); } @@ -1292,12 +1292,12 @@ public string ToString(IFormatProvider? provider) return DateTimeFormat.Format(this, null, provider); } - public string ToString(string? format, IFormatProvider? provider) + public string ToString([StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format, IFormatProvider? provider) { return DateTimeFormat.Format(this, format, provider); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) => + public bool TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format = default, IFormatProvider? provider = null) => DateTimeFormat.TryFormat(this, destination, out charsWritten, format, provider); public DateTime ToUniversalTime() @@ -1339,7 +1339,7 @@ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, Dat return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result); } - public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string? format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style); @@ -1352,13 +1352,13 @@ public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(tru return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(ReadOnlySpan s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style); return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style); @@ -1371,7 +1371,7 @@ public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(tru return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style); return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs index 1d4dc7dcfa3ff..d0778363fb34f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs @@ -544,7 +544,7 @@ public static DateTimeOffset Parse(ReadOnlySpan input, IFormatProvider? fo // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTimeOffset ParseExact(string input, string format, IFormatProvider? formatProvider) + public static DateTimeOffset ParseExact(string input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format); @@ -555,7 +555,7 @@ public static DateTimeOffset ParseExact(string input, string format, IFormatProv // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTimeOffset ParseExact(string input, string format, IFormatProvider? formatProvider, DateTimeStyles styles) + public static DateTimeOffset ParseExact(string input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format, IFormatProvider? formatProvider, DateTimeStyles styles) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -569,14 +569,14 @@ public static DateTimeOffset ParseExact(string input, string format, IFormatProv return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) + public static DateTimeOffset ParseExact(ReadOnlySpan input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) { styles = ValidateStyles(styles, nameof(styles)); DateTime dateResult = DateTimeParse.ParseExact(input, format, DateTimeFormatInfo.GetInstance(formatProvider), styles, out TimeSpan offset); return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(string input, string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles) + public static DateTimeOffset ParseExact(string input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -589,7 +589,7 @@ public static DateTimeOffset ParseExact(string input, string[] formats, IFormatP return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(ReadOnlySpan input, string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) + public static DateTimeOffset ParseExact(ReadOnlySpan input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) { styles = ValidateStyles(styles, nameof(styles)); DateTime dateResult = DateTimeParse.ParseExactMultiple(input, formats, DateTimeFormatInfo.GetInstance(formatProvider), styles, out TimeSpan offset); @@ -658,16 +658,16 @@ private static DateTimeOffset ToLocalTime(DateTime utcDateTime, bool throwOnOver public override string ToString() => DateTimeFormat.Format(ClockDateTime, null, null, Offset); - public string ToString(string? format) => + public string ToString([StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format) => DateTimeFormat.Format(ClockDateTime, format, null, Offset); public string ToString(IFormatProvider? formatProvider) => DateTimeFormat.Format(ClockDateTime, null, formatProvider, Offset); - public string ToString(string? format, IFormatProvider? formatProvider) => + public string ToString([StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format, IFormatProvider? formatProvider) => DateTimeFormat.Format(ClockDateTime, format, formatProvider, Offset); - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? formatProvider = null) => + public bool TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format = default, IFormatProvider? formatProvider = null) => DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, formatProvider, Offset); public DateTimeOffset ToUniversalTime() => @@ -717,7 +717,7 @@ public static bool TryParse(ReadOnlySpan input, IFormatProvider? formatPro return parsed; } - public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen(true)] string? format, IFormatProvider? formatProvider, DateTimeStyles styles, + public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string? format, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); @@ -738,7 +738,7 @@ public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen } public static bool TryParseExact( - ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) + ReadOnlySpan input, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); bool parsed = DateTimeParse.TryParseExact(input, format, DateTimeFormatInfo.GetInstance(formatProvider), styles, out DateTime dateResult, out TimeSpan offset); @@ -746,7 +746,7 @@ public static bool TryParseExact( return parsed; } - public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen(true)] string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, + public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); @@ -767,7 +767,7 @@ public static bool TryParseExact([NotNullWhen(true)] string? input, [NotNullWhen } public static bool TryParseExact( - ReadOnlySpan input, [NotNullWhen(true)] string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) + ReadOnlySpan input, [NotNullWhen(true), StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); bool parsed = DateTimeParse.TryParseExactMultiple(input, formats, DateTimeFormatInfo.GetInstance(formatProvider), styles, out DateTime dateResult, out TimeSpan offset); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs new file mode 100644 index 0000000000000..f776dd576c84e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, and callers + /// do not need to set any required members themselves. + /// + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class SetsRequiredMembersAttribute : Attribute + { } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs new file mode 100644 index 0000000000000..5341f9d295d1a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis +{ + /// Specifies the syntax used in a string. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class StringSyntaxAttribute : Attribute + { + /// Initializes the with the identifier of the syntax used. + /// The syntax identifier. + public StringSyntaxAttribute(string syntax) + { + Syntax = syntax; + Arguments = Array.Empty(); + } + + /// Initializes the with the identifier of the syntax used. + /// The syntax identifier. + /// Optional arguments associated with the specific syntax employed. + public StringSyntaxAttribute(string syntax, params object?[] arguments) + { + Syntax = syntax; + Arguments = arguments; + } + + /// Gets the identifier of the syntax used. + public string Syntax { get; } + + /// Optional arguments associated with the specific syntax employed. + public object?[] Arguments { get; } + + /// The syntax identifier for strings containing date and time format specifiers. + public const string DateTimeFormat = nameof(DateTimeFormat); + + /// The syntax identifier for strings containing JavaScript Object Notation (JSON). + public const string Json = nameof(Json); + + /// The syntax identifier for strings containing regular expressions. + public const string Regex = nameof(Regex); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs index c3994e613a316..b1aaccd7f7f7c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs @@ -15,7 +15,7 @@ namespace System.Diagnostics.Tracing #if ES_BUILD_STANDALONE [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] #endif - internal struct EventDescriptor + internal readonly struct EventDescriptor : IEquatable { #region private [FieldOffset(0)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index f8d6e9c6ff114..b54a5a50ba62e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -3280,7 +3280,7 @@ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAt } else if (eventAttribute.EventId <= 0) { - manifest.ManifestError(SR.Format(SR.EventSource_NeedPositiveId, method.Name), true); + manifest.ManifestError(SR.EventSource_NeedPositiveId, true); continue; // don't validate anything else for this event } if (method.Name.LastIndexOf('.') >= 0) @@ -3501,7 +3501,7 @@ private static void AddProviderEnumKind(ManifestBuilder manifest, FieldInfo stat #endif return; Error: - manifest.ManifestError(SR.Format(SR.EventSource_EnumKindMismatch, staticField.Name, staticField.FieldType.Name, providerEnumKind)); + manifest.ManifestError(SR.Format(SR.EventSource_EnumKindMismatch, staticField.FieldType.Name, providerEnumKind)); } // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method @@ -3630,7 +3630,7 @@ private static void DebugCheckEvent(ref Dictionary? eventsByName if (evtId < eventData.Length && eventData[evtId].Descriptor.EventId != 0) { - manifest.ManifestError(SR.Format(SR.EventSource_EventIdReused, evtName, evtId, eventData[evtId].Name), true); + manifest.ManifestError(SR.Format(SR.EventSource_EventIdReused, evtName, evtId), true); } // We give a task to things if they don't have one. diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs new file mode 100644 index 0000000000000..be8ff08940eeb --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics +{ + /// + /// Exception thrown when the program executes an instruction that was thought to be unreachable. + /// + public sealed class UnreachableException : Exception + { + /// + /// Initializes a new instance of the class with the default error message. + /// + public UnreachableException() + : base(SR.Arg_UnreachableException) + { + } + + /// + /// Initializes a new instance of the + /// class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public UnreachableException(string? message) + : base(message) + { + } + + /// + /// Initializes a new instance of the + /// class with a specified error message and a reference to the inner exception that is the cause of + /// this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception. + public UnreachableException(string? message, Exception? innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 5a05ee1f33c71..414db07d199e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -77,12 +77,7 @@ public static string CurrentDirectory get => CurrentDirectoryCore; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); - - if (value.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(value)); - + ArgumentException.ThrowIfNullOrEmpty(value); CurrentDirectoryCore = value; } } @@ -239,11 +234,7 @@ private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget t private static void ValidateVariableAndValue(string variable, ref string? value) { - if (variable == null) - throw new ArgumentNullException(nameof(variable)); - - if (variable.Length == 0) - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable)); + ArgumentException.ThrowIfNullOrEmpty(variable); if (variable[0] == '\0') throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs new file mode 100644 index 0000000000000..90512ca598bd8 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace System +{ + public static partial class Environment + { + // iOS/tvOS aren't allowed to call libproc APIs so return 0 here, this also matches what we returned in earlier releases + public static long WorkingSet => 0; + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index 048ad3b125ca0..bdee108ba076f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -2094,7 +2094,7 @@ private static string GetSeparator(string format, string timeParts) private static int IndexOfTimePart(string format, int startIndex, string timeParts) { Debug.Assert(startIndex >= 0, "startIndex cannot be negative"); - Debug.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) < 0, "timeParts cannot include quote characters"); + Debug.Assert(timeParts.AsSpan().IndexOfAny('\'', '\\') < 0, "timeParts cannot include quote characters"); bool inQuote = false; for (int i = startIndex; i < format.Length; ++i) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index e72e788556640..f8c1745c1e499 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -62,8 +62,8 @@ Patterns Format Description Example "M" "0" month w/o leading zero 2 "MM" "00" month with leading zero 02 "MMM" short month name (abbreviation) Feb - "MMMM" full month name Febuary - "MMMM*" full month name Febuary + "MMMM" full month name February + "MMMM*" full month name February "y" "0" two digit year (year % 100) w/o leading zero 0 "yy" "00" two digit year (year % 100) with leading zero 00 @@ -734,7 +734,7 @@ private static StringBuilder FormatCustomized( break; case '\\': // Escaped character. Can be used to insert a character into the format string. - // For exmple, "\d" will insert the character 'd' into the string. + // For example, "\d" will insert the character 'd' into the string. // // NOTENOTE : we can remove this format character if we enforce the enforced quote // character rule. @@ -966,7 +966,7 @@ private static string ExpandPredefinedFormat(ReadOnlySpan format, ref Date // This format is not supported by DateTimeOffset throw new FormatException(SR.Format_InvalidString); } - // Universal time is always in Greogrian calendar. + // Universal time is always in Gregorian calendar. // // Change the Calendar to be Gregorian Calendar. // diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index 78ca2a731f3d2..8387dd024d17f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -80,27 +80,6 @@ public NumberFormatInfo() { } - private static void VerifyDecimalSeparator(string decSep, string propertyName) - { - if (decSep == null) - { - throw new ArgumentNullException(propertyName); - } - - if (decSep.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyDecString, propertyName); - } - } - - private static void VerifyGroupSeparator(string groupSep, string propertyName) - { - if (groupSep == null) - { - throw new ArgumentNullException(propertyName); - } - } - private static void VerifyNativeDigits(string[] nativeDig, string propertyName) { if (nativeDig == null) @@ -264,7 +243,7 @@ public string CurrencyDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _currencyDecimalSeparator = value; } } @@ -355,7 +334,7 @@ public string CurrencyGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _currencyGroupSeparator = value; } } @@ -542,7 +521,7 @@ public string NumberDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _numberDecimalSeparator = value; } } @@ -553,7 +532,7 @@ public string NumberGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _numberGroupSeparator = value; } } @@ -631,7 +610,7 @@ public string PercentDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _percentDecimalSeparator = value; } } @@ -642,7 +621,7 @@ public string PercentGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _percentGroupSeparator = value; } } @@ -652,11 +631,7 @@ public string PercentSymbol get => _percentSymbol; set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - + ArgumentNullException.ThrowIfNull(value); VerifyWritable(); _percentSymbol = value; } diff --git a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs index d9735f05b4434..f40830e416d36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs @@ -47,6 +47,8 @@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { // xxHash32 is used for the hash code. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs index c7c1434d69cba..5c25031957d45 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs @@ -48,16 +48,14 @@ public sealed class BufferedStream : Stream private const int MaxShadowBufferSize = 81920; // Make sure not to get to the Large Object Heap. private const int DefaultBufferSize = 4096; - private Stream? _stream; // Underlying stream. Close sets _stream to null. - private byte[]? _buffer; // Shared read/write buffer. Alloc on first use. - private readonly int _bufferSize; // Length of internal buffer (not counting the shadow buffer). - private int _readPos; // Read pointer within shared buffer. - private int _readLen; // Number of bytes read in buffer from _stream. - private int _writePos; // Write pointer within shared buffer. - private Task? _lastSyncCompletedReadTask; // The last successful Task returned from ReadAsync - // (perf optimization for successive reads of the same size) - // Removing a private default constructor is a breaking change for the DataDebugSerializer. - // Because this ctor was here previously we need to keep it around. + private Stream? _stream; // Underlying stream. Close sets _stream to null. + private byte[]? _buffer; // Shared read/write buffer. Alloc on first use. + private readonly int _bufferSize; // Length of internal buffer (not counting the shadow buffer). + private int _readPos; // Read pointer within shared buffer. + private int _readLen; // Number of bytes read in buffer from _stream. + private int _writePos; // Write pointer within shared buffer. + private CachedCompletedInt32Task _lastSyncCompletedReadTask; // The last successful Task returned from ReadAsync + // (perf optimization for successive reads of the same size) public BufferedStream(Stream stream) : this(stream, DefaultBufferSize) @@ -571,19 +569,6 @@ public override int Read(Span destination) } } - private Task LastSyncCompletedReadTask(int val) - { - Task? t = _lastSyncCompletedReadTask; - Debug.Assert(t == null || t.IsCompletedSuccessfully); - - if (t != null && t.Result == val) - return t; - - t = Task.FromResult(val); - _lastSyncCompletedReadTask = t; - return t; - } - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { ValidateBufferArguments(buffer, offset, count); @@ -622,7 +607,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel { return (error == null) - ? LastSyncCompletedReadTask(bytesFromBuffer) + ? _lastSyncCompletedReadTask.GetTask(bytesFromBuffer) : Task.FromException(error); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs index 2bfcd01604047..eea2cda3f8c97 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs @@ -13,11 +13,7 @@ public static partial class Directory { public static DirectoryInfo? GetParent(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); string fullPath = Path.GetFullPath(path); @@ -29,10 +25,7 @@ public static partial class Directory public static DirectoryInfo CreateDirectory(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); string fullPath = Path.GetFullPath(path); @@ -228,25 +221,15 @@ public static string GetDirectoryRoot(string path) public static void SetCurrentDirectory(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); Environment.CurrentDirectory = Path.GetFullPath(path); } public static void Move(string sourceDirName, string destDirName) { - if (sourceDirName == null) - throw new ArgumentNullException(nameof(sourceDirName)); - if (sourceDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceDirName)); - - if (destDirName == null) - throw new ArgumentNullException(nameof(destDirName)); - if (destDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName)); + ArgumentException.ThrowIfNullOrEmpty(sourceDirName); + ArgumentException.ThrowIfNullOrEmpty(destDirName); string fullsourceDirName = Path.GetFullPath(sourceDirName); string sourcePath = PathInternal.EnsureTrailingSeparator(fullsourceDirName); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs index 1aeef2f7501a8..771b5e69a05cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs @@ -188,10 +188,7 @@ private IEnumerable InternalEnumerateInfos( public void MoveTo(string destDirName) { - if (destDirName == null) - throw new ArgumentNullException(nameof(destDirName)); - if (destDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName)); + ArgumentException.ThrowIfNullOrEmpty(destDirName); string destination = Path.GetFullPath(destDirName); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs index 1be3942011b2f..3c7fb6504473e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs @@ -11,6 +11,7 @@ namespace System.IO.Enumeration public unsafe ref partial struct FileSystemEntry { private Interop.Sys.DirectoryEntry _directoryEntry; + private bool _isDirectory; private FileStatus _status; private Span _pathBuffer; private ReadOnlySpan _fullPath; @@ -32,8 +33,8 @@ internal static FileAttributes Initialize( entry._pathBuffer = pathBuffer; entry._fullPath = ReadOnlySpan.Empty; entry._fileName = ReadOnlySpan.Empty; + entry._isDirectory = false; entry._status.InvalidateCaches(); - entry._status.InitiallyDirectory = false; bool isDirectory = directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR; bool isSymlink = directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK; @@ -41,15 +42,15 @@ internal static FileAttributes Initialize( if (isDirectory) { - entry._status.InitiallyDirectory = true; + entry._isDirectory = true; } else if (isSymlink) { - entry._status.InitiallyDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); + entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); } else if (isUnknown) { - entry._status.InitiallyDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); + entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); if (entry._status.IsSymbolicLink(entry.FullPath, continueOnError: true)) { entry._directoryEntry.InodeType = Interop.Sys.NodeType.DT_LNK; @@ -145,16 +146,17 @@ public FileAttributes Attributes public DateTimeOffset CreationTimeUtc => _status.GetCreationTime(FullPath, continueOnError: true); public DateTimeOffset LastAccessTimeUtc => _status.GetLastAccessTime(FullPath, continueOnError: true); public DateTimeOffset LastWriteTimeUtc => _status.GetLastWriteTime(FullPath, continueOnError: true); - public bool IsHidden => _status.IsHidden(FullPath, FileName, continueOnError: true); + + public bool IsHidden => _status.IsFileSystemEntryHidden(FullPath, FileName); internal bool IsReadOnly => _status.IsReadOnly(FullPath, continueOnError: true); - public bool IsDirectory => _status.InitiallyDirectory; + public bool IsDirectory => _isDirectory; internal bool IsSymbolicLink => _directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK; public FileSystemInfo ToFileSystemInfo() { string fullPath = ToFullPath(); - return FileSystemInfo.Create(fullPath, new string(FileName), ref _status); + return FileSystemInfo.Create(fullPath, new string(FileName), _isDirectory, ref _status); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 64379283e6a09..148182db5644c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -49,14 +49,8 @@ public static void Copy(string sourceFileName, string destFileName) /// public static void Copy(string sourceFileName, string destFileName, bool overwrite) { - if (sourceFileName == null) - throw new ArgumentNullException(nameof(sourceFileName), SR.ArgumentNull_FileName); - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (sourceFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(sourceFileName); + ArgumentException.ThrowIfNullOrEmpty(destFileName); FileSystem.CopyFile(Path.GetFullPath(sourceFileName), Path.GetFullPath(destFileName), overwrite); } @@ -298,7 +292,7 @@ public static byte[] ReadAllBytes(string path) using (SafeFileHandle sfh = OpenHandle(path, FileMode.Open, FileAccess.Read, FileShare.Read, options)) { long fileLength = 0; - if (sfh.CanSeek && (fileLength = RandomAccess.GetFileLength(sfh)) > Array.MaxLength) + if (sfh.CanSeek && (fileLength = sfh.GetFileLength()) > Array.MaxLength) { throw new IOException(SR.IO_FileTooLong2GB); } @@ -334,12 +328,8 @@ public static byte[] ReadAllBytes(string path) public static void WriteAllBytes(string path, byte[] bytes) { - if (path == null) - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - if (bytes == null) - throw new ArgumentNullException(nameof(bytes)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read); RandomAccess.WriteAtOffset(sfh, bytes, 0); @@ -460,14 +450,8 @@ public static void Move(string sourceFileName, string destFileName) public static void Move(string sourceFileName, string destFileName, bool overwrite) { - if (sourceFileName == null) - throw new ArgumentNullException(nameof(sourceFileName), SR.ArgumentNull_FileName); - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (sourceFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(sourceFileName); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string fullSourceFileName = Path.GetFullPath(sourceFileName); string fullDestFileName = Path.GetFullPath(destFileName); @@ -572,7 +556,7 @@ private static async Task InternalReadAllTextAsync(string path, Encoding SafeFileHandle sfh = OpenHandle(path, FileMode.Open, FileAccess.Read, FileShare.Read, options); long fileLength = 0L; - if (sfh.CanSeek && (fileLength = RandomAccess.GetFileLength(sfh)) > Array.MaxLength) + if (sfh.CanSeek && (fileLength = sfh.GetFileLength()) > Array.MaxLength) { sfh.Dispose(); return Task.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(new IOException(SR.IO_FileTooLong2GB))); @@ -651,12 +635,8 @@ private static async Task InternalReadAllBytesUnknownLengthAsync(SafeFil public static Task WriteAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - if (bytes == null) - throw new ArgumentNullException(nameof(bytes)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -691,7 +671,7 @@ private static async Task InternalReadAllLinesAsync(string path, Encod cancellationToken.ThrowIfCancellationRequested(); string? line; List lines = new List(); - while ((line = await sr.ReadLineAsync().ConfigureAwait(false)) != null) + while ((line = await sr.ReadLineAsync(cancellationToken).ConfigureAwait(false)) != null) { lines.Add(line); cancellationToken.ThrowIfCancellationRequested(); @@ -806,12 +786,8 @@ public static FileSystemInfo CreateSymbolicLink(string path, string pathToTarget private static void Validate(string path, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); } private static byte[] ReadAllBytesUnknownLength(SafeFileHandle sfh) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs index 2ce33d996d61e..0d9db030f900d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs @@ -89,10 +89,7 @@ public StreamWriter AppendText() public FileInfo CopyTo(string destFileName, bool overwrite) { - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string destinationPath = Path.GetFullPath(destFileName); FileSystem.CopyFile(FullPath, destinationPath, overwrite); @@ -139,10 +136,7 @@ public void MoveTo(string destFileName) // This method does work across volumes. public void MoveTo(string destFileName, bool overwrite) { - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string fullDestFileName = Path.GetFullPath(destFileName); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs index 23c46bae4a012..05b70f1356b51 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs @@ -2,12 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; namespace System.IO { internal partial struct FileStatus { - internal void SetCreationTime(string path, DateTimeOffset time) + internal void SetCreationTime(string path, DateTimeOffset time, bool asDirectory) + => SetCreationTime(handle: null, path, time, asDirectory); + + internal void SetCreationTime(SafeFileHandle handle, DateTimeOffset time, bool asDirectory) + => SetCreationTime(handle, handle.Path, time, asDirectory); + + private void SetCreationTime(SafeFileHandle? handle, string path, DateTimeOffset time, bool asDirectory) { // Try to set the attribute on the file system entry using setattrlist, // if we get ENOTSUP then it means that "The volume does not support @@ -19,7 +26,7 @@ internal void SetCreationTime(string path, DateTimeOffset time) // great care. long seconds = time.ToUnixTimeSeconds(); long nanoseconds = UnixTimeSecondsToNanoseconds(time, seconds); - Interop.Error error = SetCreationTimeCore(path, seconds, nanoseconds); + Interop.Error error = SetCreationTimeCore(handle, path, seconds, nanoseconds); if (error == Interop.Error.SUCCESS) { @@ -27,15 +34,15 @@ internal void SetCreationTime(string path, DateTimeOffset time) } else if (error == Interop.Error.ENOTSUP) { - SetAccessOrWriteTimeCore(path, time, isAccessTime: false, checkCreationTime: false); + SetAccessOrWriteTimeCore(handle, path, time, isAccessTime: false, checkCreationTime: false, asDirectory); } else { - Interop.CheckIo(error, path, InitiallyDirectory); + Interop.CheckIo(error, path, asDirectory); } } - private unsafe Interop.Error SetCreationTimeCore(string path, long seconds, long nanoseconds) + private unsafe Interop.Error SetCreationTimeCore(SafeFileHandle? handle, string path, long seconds, long nanoseconds) { Interop.Sys.TimeSpec timeSpec = default; @@ -46,15 +53,18 @@ private unsafe Interop.Error SetCreationTimeCore(string path, long seconds, long attrList.bitmapCount = Interop.libc.AttrList.ATTR_BIT_MAP_COUNT; attrList.commonAttr = Interop.libc.AttrList.ATTR_CMN_CRTIME; + // Follow links when using SafeFileHandle API. + int flags = handle is null ? new CULong(Interop.libc.FSOPT_NOFOLLOW) : 0; + Interop.Error error = - Interop.libc.setattrlist(path, &attrList, &timeSpec, sizeof(Interop.Sys.TimeSpec), new CULong(Interop.libc.FSOPT_NOFOLLOW)) == 0 ? + Interop.libc.setattrlist(path, &attrList, &timeSpec, sizeof(Interop.Sys.TimeSpec), flags) == 0 ? Interop.Error.SUCCESS : Interop.Sys.GetLastErrorInfo().Error; return error; } - private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime) => - SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: true); + private void SetAccessOrWriteTime(SafeFileHandle? handle, string path, DateTimeOffset time, bool isAccessTime, bool asDirectory) => + SetAccessOrWriteTimeCore(handle, path, time, isAccessTime, checkCreationTime: true, asDirectory); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs index d9d9b1eeb7c92..90bafee097a7d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs @@ -2,19 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; namespace System.IO { internal partial struct FileStatus { - internal void SetCreationTime(string path, DateTimeOffset time) => - SetLastWriteTime(path, time); + internal void SetCreationTime(string path, DateTimeOffset time, bool asDirectory) => + SetLastWriteTime(path, time, asDirectory); - private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime) => - SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: false); + internal void SetCreationTime(SafeFileHandle handle, DateTimeOffset time, bool asDirectory) => + SetLastWriteTime(handle, time, asDirectory); + + private void SetAccessOrWriteTime(SafeFileHandle? handle, string path, DateTimeOffset time, bool isAccessTime, bool asDirectory) => + SetAccessOrWriteTimeCore(handle, path, time, isAccessTime, checkCreationTime: false, asDirectory); // This is not used on these platforms, but is needed for source compat - private Interop.Error SetCreationTimeCore(string path, long seconds, long nanoseconds) => + private Interop.Error SetCreationTimeCore(SafeFileHandle? handle, string path, long seconds, long nanoseconds) => throw new InvalidOperationException(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs index 05b4bbcff6a2a..571cede66789a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; namespace System.IO { @@ -10,44 +11,44 @@ internal partial struct FileStatus { private const int NanosecondsPerTick = 100; - // The last cached lstat information about the file + private const int InitializedExistsDir = -3; // target is directory. + private const int InitializedExistsFile = -2; // target is file. + private const int InitializedNotExists = -1; // entry does not exist. + private const int Uninitialized = 0; // uninitialized, '0' to make default(FileStatus) uninitialized. + + // Tracks the initialization state. + // < 0 : initialized succesfully. Value is InitializedNotExists, InitializedExistsFile or InitializedExistsDir. + // 0 : uninitialized. + // > 0 : initialized with error. Value is raw errno. + private int _state; + + // The last cached lstat information about the file. + // Must only be used after calling EnsureCachesInitialized and checking EntryExists is true. private Interop.Sys.FileStatus _fileCache; - // -1: if the file cache isn't initialized - Refresh should always change this value - // 0: if the file cache was initialized with no errors - // Positive number: the error code returned by the lstat call - private int _initializedFileCache; - - // We track intent of creation to know whether or not we want to (1) create a - // DirectoryInfo around this status struct or (2) actually are part of a DirectoryInfo. - // Set to true during initialization when the DirectoryEntry's INodeType describes a directory - internal bool InitiallyDirectory { get; set; } - - // Is a directory as of the last refresh - // Its value can come from either the main path or the symbolic link path - private bool _isDirectory; - - // Exists as of the last refresh - private bool _exists; - - private bool IsFileCacheInitialized => _initializedFileCache == 0; - - // Check if the main path (without following symlinks) has the hidden attribute set - // Ideally, use this if Refresh has been successfully called at least once. - // But since it is also used for soft retrieval during FileSystemEntry initialization, - // we return false early if the cache has not been initialized - internal bool HasHiddenFlag => IsFileCacheInitialized && - (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN; - - // Checks if the main path (without following symlinks) has the read-only attribute set - // Ideally, use this if Refresh has been successfully called at least once. - // But since it is also used for soft retrieval during FileSystemEntry initialization, - // we return false early if the cache has not been initialized - internal bool HasReadOnlyFlag + private bool EntryExists => _state <= InitializedExistsFile; + + private bool IsDir => _state == InitializedExistsDir; + + // Check if the main path (without following symlinks) has the hidden attribute set. + private bool HasHiddenFlag + { + get + { + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + return EntryExists && (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN; + } + } + + // Checks if the main path (without following symlinks) has the read-only attribute set. + private bool HasReadOnlyFlag { get { - if (!IsFileCacheInitialized) + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + if (!EntryExists) { return false; } @@ -78,6 +79,7 @@ internal bool HasReadOnlyFlag #if !TARGET_BROWSER // HasReadOnlyFlag cache. + // Must only be used after calling EnsureCachesInitialized. private int _isReadOnlyCache; private bool IsModeReadOnlyCore() @@ -123,20 +125,20 @@ private bool IsModeReadOnlyCore() #endif // Checks if the main path is a symbolic link - // Only call if Refresh has been successfully called at least once private bool HasSymbolicLinkFlag { get { - Debug.Assert(IsFileCacheInitialized); - return (_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK; + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + return EntryExists && (_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK; } } - // Sets the cache initialization flags to -1, which means the caches are now uninitialized + // Sets the cache initialization flags to 0, which means the caches are now uninitialized internal void InvalidateCaches() { - _initializedFileCache = -1; + _state = Uninitialized; } internal bool IsReadOnly(ReadOnlySpan path, bool continueOnError = false) @@ -145,14 +147,20 @@ internal bool IsReadOnly(ReadOnlySpan path, bool continueOnError = false) return HasReadOnlyFlag; } - internal bool IsHidden(ReadOnlySpan path, ReadOnlySpan fileName, bool continueOnError = false) + internal bool IsFileSystemEntryHidden(ReadOnlySpan path, ReadOnlySpan fileName) { - // Avoid disk hit first + // Because this is called for FileSystemEntry we can assume the entry exists and + // avoid initialization in some cases. if (IsNameHidden(fileName)) { return true; } - EnsureCachesInitialized(path, continueOnError); + if (!Interop.Sys.SupportsHiddenFlag) + { + return false; + } + + EnsureCachesInitialized(path, continueOnError: true); return HasHiddenFlag; } @@ -163,7 +171,7 @@ internal bool IsHidden(ReadOnlySpan path, ReadOnlySpan fileName, boo internal bool IsDirectory(ReadOnlySpan path, bool continueOnError = false) { EnsureCachesInitialized(path, continueOnError); - return _isDirectory; + return IsDir; } internal bool IsSymbolicLink(ReadOnlySpan path, bool continueOnError = false) @@ -173,10 +181,20 @@ internal bool IsSymbolicLink(ReadOnlySpan path, bool continueOnError = fal } internal FileAttributes GetAttributes(ReadOnlySpan path, ReadOnlySpan fileName, bool continueOnError = false) + => GetAttributes(handle: null, path, fileName, continueOnError); + + internal FileAttributes GetAttributes(SafeFileHandle handle, bool continueOnError = false) { - EnsureCachesInitialized(path, continueOnError); + ReadOnlySpan path = handle.Path; + ReadOnlySpan fileName = Path.GetFileName(path); + return GetAttributes(handle, path, fileName, continueOnError); + } - if (!_exists) + private FileAttributes GetAttributes(SafeFileHandle? handle, ReadOnlySpan path, ReadOnlySpan fileName, bool continueOnError = false) + { + EnsureCachesInitialized(handle, path, continueOnError); + + if (!EntryExists) return (FileAttributes)(-1); FileAttributes attributes = default; @@ -187,7 +205,7 @@ internal FileAttributes GetAttributes(ReadOnlySpan path, ReadOnlySpan path, ReadOnlySpan SetAttributes(handle: null, path, attributes, asDirectory); + + internal void SetAttributes(SafeFileHandle handle, FileAttributes attributes, bool asDirectory) + => SetAttributes(handle, GetHandlePath(handle), attributes, asDirectory); + + private void SetAttributes(SafeFileHandle? handle, string path, FileAttributes attributes, bool asDirectory) { // Validate that only flags from the attribute are being provided. This is an // approximation for the validation done by the Win32 function. @@ -213,22 +237,21 @@ internal void SetAttributes(string path, FileAttributes attributes) throw new ArgumentException(SR.Arg_InvalidFileAttrs, "Attributes"); } - EnsureCachesInitialized(path); + EnsureCachesInitialized(handle, path); - if (!_exists) + if (!EntryExists) FileSystemInfo.ThrowNotFound(path); if (Interop.Sys.CanSetHiddenFlag) { - if ((attributes & FileAttributes.Hidden) != 0 && (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == 0) - { - // If Hidden flag is set and cached file status does not have the flag set then set it - Interop.CheckIo(Interop.Sys.LChflags(path, (_fileCache.UserFlags | (uint)Interop.Sys.UserFlags.UF_HIDDEN)), path, InitiallyDirectory); - } - else if (HasHiddenFlag) + bool hidden = (attributes & FileAttributes.Hidden) != 0; + if (hidden ^ HasHiddenFlag) { - // If Hidden flag is not set and cached file status does have the flag set then remove it - Interop.CheckIo(Interop.Sys.LChflags(path, (_fileCache.UserFlags & ~(uint)Interop.Sys.UserFlags.UF_HIDDEN)), path, InitiallyDirectory); + uint flags = hidden ? _fileCache.UserFlags | (uint)Interop.Sys.UserFlags.UF_HIDDEN : + _fileCache.UserFlags & ~(uint)Interop.Sys.UserFlags.UF_HIDDEN; + int rv = handle is not null ? Interop.Sys.FChflags(handle, flags) : + Interop.Sys.LChflags(path!, flags); + Interop.CheckIo(rv, path, asDirectory); } } @@ -249,22 +272,31 @@ internal void SetAttributes(string path, FileAttributes attributes) // Change the permissions on the file if (newMode != _fileCache.Mode) { - Interop.CheckIo(Interop.Sys.ChMod(path, newMode), path, InitiallyDirectory); + int rv = handle is not null ? Interop.Sys.FChMod(handle, newMode) : + Interop.Sys.ChMod(path!, newMode); + Interop.CheckIo(rv, path, asDirectory); } - _initializedFileCache = -1; + InvalidateCaches(); } - internal bool GetExists(ReadOnlySpan path) + internal bool GetExists(ReadOnlySpan path, bool asDirectory) { EnsureCachesInitialized(path, continueOnError: true); - return _exists && InitiallyDirectory == _isDirectory; + return EntryExists && asDirectory == IsDir; } internal DateTimeOffset GetCreationTime(ReadOnlySpan path, bool continueOnError = false) + => GetCreationTime(handle: null, path, continueOnError); + + internal DateTimeOffset GetCreationTime(SafeFileHandle handle, bool continueOnError = false) + => GetCreationTime(handle, GetHandlePath(handle), continueOnError); + + private DateTimeOffset GetCreationTime(SafeFileHandle? handle, ReadOnlySpan path, bool continueOnError = false) { - EnsureCachesInitialized(path, continueOnError); - if (!_exists) + EnsureCachesInitialized(handle, path, continueOnError); + + if (!EntryExists) return new DateTimeOffset(DateTime.FromFileTimeUtc(0)); if ((_fileCache.Flags & Interop.Sys.FileStatusFlags.HasBirthTime) != 0) @@ -279,31 +311,61 @@ internal DateTimeOffset GetCreationTime(ReadOnlySpan path, bool continueOn } internal DateTimeOffset GetLastAccessTime(ReadOnlySpan path, bool continueOnError = false) + => GetLastAccessTime(handle: null, path, continueOnError); + + internal DateTimeOffset GetLastAccessTime(SafeFileHandle handle, bool continueOnError = false) + => GetLastAccessTime(handle, handle.Path, continueOnError); + + private DateTimeOffset GetLastAccessTime(SafeFileHandle? handle, ReadOnlySpan path, bool continueOnError = false) { - EnsureCachesInitialized(path, continueOnError); - if (!_exists) + EnsureCachesInitialized(handle, path, continueOnError); + + if (!EntryExists) return new DateTimeOffset(DateTime.FromFileTimeUtc(0)); + return UnixTimeToDateTimeOffset(_fileCache.ATime, _fileCache.ATimeNsec); } - internal void SetLastAccessTime(string path, DateTimeOffset time) => SetAccessOrWriteTime(path, time, isAccessTime: true); + internal void SetLastAccessTime(string path, DateTimeOffset time, bool asDirectory) + => SetLastAccessTime(handle: null, path, time, asDirectory); + + internal void SetLastAccessTime(SafeFileHandle handle, DateTimeOffset time, bool asDirectory) + => SetLastAccessTime(handle, GetHandlePath(handle), time, asDirectory); + + private void SetLastAccessTime(SafeFileHandle? handle, string path, DateTimeOffset time, bool asDirectory) + => SetAccessOrWriteTime(handle, path, time, isAccessTime: true, asDirectory); internal DateTimeOffset GetLastWriteTime(ReadOnlySpan path, bool continueOnError = false) + => GetLastWriteTime(handle: null, path, continueOnError); + + internal DateTimeOffset GetLastWriteTime(SafeFileHandle handle, bool continueOnError = false) + => GetLastWriteTime(handle, handle.Path, continueOnError); + + private DateTimeOffset GetLastWriteTime(SafeFileHandle? handle, ReadOnlySpan path, bool continueOnError = false) { - EnsureCachesInitialized(path, continueOnError); - if (!_exists) + EnsureCachesInitialized(handle, path, continueOnError); + + if (!EntryExists) return new DateTimeOffset(DateTime.FromFileTimeUtc(0)); + return UnixTimeToDateTimeOffset(_fileCache.MTime, _fileCache.MTimeNsec); } - internal void SetLastWriteTime(string path, DateTimeOffset time) => SetAccessOrWriteTime(path, time, isAccessTime: false); + internal void SetLastWriteTime(string path, DateTimeOffset time, bool asDirectory) + => SetLastWriteTime(handle: null, path, time, asDirectory); + + internal void SetLastWriteTime(SafeFileHandle handle, DateTimeOffset time, bool asDirectory) + => SetLastWriteTime(handle, GetHandlePath(handle), time, asDirectory); + + internal void SetLastWriteTime(SafeFileHandle? handle, string path, DateTimeOffset time, bool asDirectory) + => SetAccessOrWriteTime(handle, path, time, isAccessTime: false, asDirectory); private DateTimeOffset UnixTimeToDateTimeOffset(long seconds, long nanoseconds) { return DateTimeOffset.FromUnixTimeSeconds(seconds).AddTicks(nanoseconds / NanosecondsPerTick); } - private unsafe void SetAccessOrWriteTimeCore(string path, DateTimeOffset time, bool isAccessTime, bool checkCreationTime) + private unsafe void SetAccessOrWriteTimeCore(SafeFileHandle? handle, string path, DateTimeOffset time, bool isAccessTime, bool checkCreationTime, bool asDirectory) { // This api is used to set creation time on non OSX platforms, and as a fallback for OSX platforms. // The reason why we use it to set 'creation time' is the below comment: @@ -319,7 +381,10 @@ private unsafe void SetAccessOrWriteTimeCore(string path, DateTimeOffset time, b // force a refresh so that we have an up-to-date times for values not being overwritten InvalidateCaches(); - EnsureCachesInitialized(path); + EnsureCachesInitialized(handle, path); + + if (!EntryExists) + FileSystemInfo.ThrowNotFound(path); // we use utimes()/utimensat() to set the accessTime and writeTime Interop.Sys.TimeSpec* buf = stackalloc Interop.Sys.TimeSpec[2]; @@ -348,7 +413,9 @@ private unsafe void SetAccessOrWriteTimeCore(string path, DateTimeOffset time, b buf[1].TvNsec = nanoseconds; } #endif - Interop.CheckIo(Interop.Sys.UTimensat(path, buf), path, InitiallyDirectory); + int rv = handle is not null ? Interop.Sys.FUTimens(handle, buf) : + Interop.Sys.UTimensat(path!, buf); + Interop.CheckIo(rv, path, asDirectory); // On OSX-like platforms, when the modification time is less than the creation time (including // when the modification time is already less than but access time is being set), the creation @@ -365,10 +432,10 @@ private unsafe void SetAccessOrWriteTimeCore(string path, DateTimeOffset time, b if (updateCreationTime) { - Interop.Error error = SetCreationTimeCore(path, _fileCache.BirthTime, _fileCache.BirthTimeNsec); + Interop.Error error = SetCreationTimeCore(handle, path, _fileCache.BirthTime, _fileCache.BirthTimeNsec); if (error != Interop.Error.SUCCESS && error != Interop.Error.ENOTSUP) { - Interop.CheckIo(error, path, InitiallyDirectory); + Interop.CheckIo(error, path, asDirectory); } } } @@ -379,52 +446,69 @@ internal long GetLength(ReadOnlySpan path, bool continueOnError = false) // On Unix, it returns the length of the path stored in the link. EnsureCachesInitialized(path, continueOnError); - return IsFileCacheInitialized ? _fileCache.Size : 0; + return EntryExists ? _fileCache.Size : 0; } + internal void RefreshCaches(ReadOnlySpan path) + => RefreshCaches(handle: null, path); + // Tries to refresh the lstat cache (_fileCache). // This method should not throw. Instead, we store the results, and we will throw when the user attempts to access any of the properties when there was a failure - internal void RefreshCaches(ReadOnlySpan path) + internal void RefreshCaches(SafeFileHandle? handle, ReadOnlySpan path) { - _isDirectory = false; - path = Path.TrimEndingDirectorySeparator(path); - - // Retrieve the file cache (lstat) to get the details on the object, without following symlinks. - // If it is a symlink, then subsequently get details on the target of the symlink. - // We only report failure if the initial lstat fails, as a broken symlink should still report info on exists, attributes, etc. - if (!TryRefreshFileCache(path)) +#if !TARGET_BROWSER + _isReadOnlyCache = -1; +#endif + int rv; + if (handle is not null) { - _exists = false; - return; + rv = Interop.Sys.FStat(handle, out _fileCache); + } + else + { + path = Path.TrimEndingDirectorySeparator(path); + rv = Interop.Sys.LStat(path, out _fileCache); } - // Do an initial check in case the main path is pointing to a directory - _isDirectory = CacheHasDirectoryFlag(_fileCache); - - // We also need to check if the main path is a symbolic link, - // in which case, we retrieve the symbolic link's target data - if (!_isDirectory && HasSymbolicLinkFlag && Interop.Sys.Stat(path, out Interop.Sys.FileStatus target) == 0) + if (rv < 0) { - // and check again if the symlink path is a directory - _isDirectory = CacheHasDirectoryFlag(target); + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + + if (errorInfo.Error == Interop.Error.ENOENT || // A component of the path does not exist, or path is an empty string + errorInfo.Error == Interop.Error.ENOTDIR) // A component of the path prefix of path is not a directory + { + _state = InitializedNotExists; + } + else + { + Debug.Assert(errorInfo.RawErrno > 0); // Expect a positive integer + _state = errorInfo.RawErrno; // Initialized with error. + } + + return; } - _exists = true; + // Check if the main path is a directory, or a link to a directory. + int fileType = _fileCache.Mode & Interop.Sys.FileTypes.S_IFMT; + bool isDirectory = fileType == Interop.Sys.FileTypes.S_IFDIR || + (handle is null && // Don't follow links for SafeHandle APIs. + fileType == Interop.Sys.FileTypes.S_IFLNK && + Interop.Sys.Stat(path, out Interop.Sys.FileStatus target) == 0 && + (target.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR); - // Checks if the specified cache has the directory attribute set - // Only call if Refresh has been successfully called at least once, and you're - // certain the passed-in cache was successfully retrieved - static bool CacheHasDirectoryFlag(Interop.Sys.FileStatus cache) => - (cache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR; + _state = isDirectory ? InitializedExistsDir : InitializedExistsFile; } - // Checks if the file cache is set to -1 and refreshes it's value. - // If it failed, and continueOnError is set to true, this method will throw. internal void EnsureCachesInitialized(ReadOnlySpan path, bool continueOnError = false) + => EnsureCachesInitialized(handle: null, path, continueOnError); + + // Checks if the file cache is uninitialized and refreshes it's value. + // If it failed, and continueOnError is set to true, this method will throw. + internal void EnsureCachesInitialized(SafeFileHandle? handle, ReadOnlySpan path, bool continueOnError = false) { - if (_initializedFileCache == -1) + if (_state == Uninitialized) { - RefreshCaches(path); + RefreshCaches(handle, path); } if (!continueOnError) @@ -437,9 +521,9 @@ internal void EnsureCachesInitialized(ReadOnlySpan path, bool continueOnEr private void ThrowOnCacheInitializationError(ReadOnlySpan path) { // Lstat should always be initialized by Refresh - if (_initializedFileCache != 0) + int errno = _state; + if (errno > 0) { - int errno = _initializedFileCache; InvalidateCaches(); throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(errno), new string(path)); } @@ -452,40 +536,18 @@ private static long UnixTimeSecondsToNanoseconds(DateTimeOffset time, long secon return (time.UtcDateTime.Ticks - DateTimeOffset.UnixEpoch.Ticks - seconds * TicksPerSecond) * NanosecondsPerTick; } - private bool TryRefreshFileCache(ReadOnlySpan path) + private static string GetHandlePath(SafeFileHandle handle) { -#if !TARGET_BROWSER - _isReadOnlyCache = -1; -#endif - return VerifyStatCall(Interop.Sys.LStat(path, out _fileCache), out _initializedFileCache); - } - - // Receives the return value of a stat or lstat call. - // If the call is unsuccessful, sets the initialized parameter to a positive number representing the last error info. - // If the call is successful, sets the initialized parameter to zero. - // The method returns true if the initialized parameter is set to zero, false otherwise. - private bool VerifyStatCall(int returnValue, out int initialized) - { - initialized = 0; - - // Both stat and lstat return -1 on error, 0 on success - if (returnValue < 0) + if (handle.Path is null) { - Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); - - // This should never set the error if the file can't be found. - // (see the Windows refresh passing returnErrorOnNotFound: false). - if (errorInfo.Error != Interop.Error.ENOENT && // A component of the path does not exist, or path is an empty string - errorInfo.Error != Interop.Error.ENOTDIR) // A component of the path prefix of path is not a directory - { - // Expect a positive integer - initialized = errorInfo.RawErrno; - Debug.Assert(initialized > 0); - } - return false; + ThrowHandleHasNoPath(); } + return handle.Path!; - return true; + static void ThrowHandleHasNoPath() + { + throw new ArgumentException(SR.Arg_HandleHasNoPath); + } } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index b97194b86c5f0..77685bb3b9a6a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -173,19 +173,9 @@ public FileStream(string path, FileMode mode, FileAccess access, FileShare share /// The specified path, file name, or both exceed the system-defined maximum length. public FileStream(string path, FileStreamOptions options) { - if (path is null) - { - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - } - else if (path.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - } - else if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } - else if ((options.Access & FileAccess.Read) != 0 && options.Mode == FileMode.Append) + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(options); + if ((options.Access & FileAccess.Read) != 0 && options.Mode == FileMode.Append) { throw new ArgumentException(SR.Argument_InvalidAppendMode, nameof(options)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs index 5afbb39cc6094..0e62768bf7e54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs @@ -554,282 +554,49 @@ public static FileAttributes GetAttributes(string fullPath) } public static FileAttributes GetAttributes(SafeFileHandle fileHandle) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus fileStatus); - if (result != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - - FileAttributes attributes = default; - - if (IsModeReadOnly(fileStatus)) - attributes |= FileAttributes.ReadOnly; - - if ((fileStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK) - attributes |= FileAttributes.ReparsePoint; - - if ((fileStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR) - attributes |= FileAttributes.Directory; - - if (fileHandle.Path != null && IsNameHidden(fileHandle.Path) || (fileStatus.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN) - attributes |= FileAttributes.Hidden; - - return attributes != default ? attributes : FileAttributes.Normal; - } - - private static bool IsNameHidden(ReadOnlySpan fileName) => fileName.Length > 0 && fileName[0] == '.'; - - private static bool IsModeReadOnly(Interop.Sys.FileStatus status) - { - var mode = (Interop.Sys.Permissions)(status.Mode & (int)Interop.Sys.Permissions.Mask); - - bool isUserReadOnly = (mode & Interop.Sys.Permissions.S_IRUSR) != 0 && // has read permission - (mode & Interop.Sys.Permissions.S_IWUSR) == 0; // but not write permission - bool isGroupReadOnly = (mode & Interop.Sys.Permissions.S_IRGRP) != 0 && // has read permission - (mode & Interop.Sys.Permissions.S_IWGRP) == 0; // but not write permission - bool isOtherReadOnly = (mode & Interop.Sys.Permissions.S_IROTH) != 0 && // has read permission - (mode & Interop.Sys.Permissions.S_IWOTH) == 0; // but not write permission - - // If they are all the same, no need to check user/group. - if ((isUserReadOnly == isGroupReadOnly) && (isGroupReadOnly == isOtherReadOnly)) - { - return isUserReadOnly; - } - - if (status.Uid == Interop.Sys.GetEUid()) - { - // User owns the file. - return isUserReadOnly; - } - - // System files often have the same permissions for group and other (umask 022). - if (isGroupReadOnly == isUserReadOnly) - { - return isGroupReadOnly; - } - - if (Interop.Sys.IsMemberOfGroup(status.Gid)) - { - // User belongs to group that owns the file. - return isGroupReadOnly; - } - else - { - // Other permissions. - return isOtherReadOnly; - } - } + => default(FileStatus).GetAttributes(fileHandle); public static void SetAttributes(string fullPath, FileAttributes attributes) - { - new FileInfo(fullPath, null).Attributes = attributes; - } + => default(FileStatus).SetAttributes(fullPath, attributes, asDirectory: false); public static void SetAttributes(SafeFileHandle fileHandle, FileAttributes attributes) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus output); - if (result != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - - // Validate that only flags from the attribute are being provided. This is an - // approximation for the validation done by the Win32 function. - const FileAttributes allValidFlags = - FileAttributes.Archive | FileAttributes.Compressed | FileAttributes.Device | - FileAttributes.Directory | FileAttributes.Encrypted | FileAttributes.Hidden | - FileAttributes.IntegrityStream | FileAttributes.Normal | FileAttributes.NoScrubData | - FileAttributes.NotContentIndexed | FileAttributes.Offline | FileAttributes.ReadOnly | - FileAttributes.ReparsePoint | FileAttributes.SparseFile | FileAttributes.System | - FileAttributes.Temporary; - if ((attributes & ~allValidFlags) != 0) - { - // Using constant string for argument to match historical throw - throw new ArgumentException(SR.Arg_InvalidFileAttrs, "Attributes"); - } - - if (Interop.Sys.CanSetHiddenFlag) - { - if ((attributes & FileAttributes.Hidden) != 0 && (output.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == 0) - { - Interop.Sys.FChflags(fileHandle, (output.UserFlags | (uint)Interop.Sys.UserFlags.UF_HIDDEN)); - } - } - - // The only thing we can reasonably change is whether the file object is readonly by changing permissions. - - int newMode = output.Mode; - if ((attributes & FileAttributes.ReadOnly) != 0) - { - // Take away all write permissions from user/group/everyone - newMode &= ~(int)(Interop.Sys.Permissions.S_IWUSR | Interop.Sys.Permissions.S_IWGRP | Interop.Sys.Permissions.S_IWOTH); - } - else if ((newMode & (int)Interop.Sys.Permissions.S_IRUSR) != 0) - { - // Give write permission to the owner if the owner has read permission - newMode |= (int)Interop.Sys.Permissions.S_IWUSR; - } - - // Change the permissions on the file - if (newMode != output.Mode) - { - int chModResult = Interop.Sys.FChMod(fileHandle, newMode); - if (chModResult != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(chModResult), fileHandle.Path); - } - } - } + => default(FileStatus).SetAttributes(fileHandle, attributes, asDirectory: false); public static DateTimeOffset GetCreationTime(string fullPath) - { - return new FileInfo(fullPath, null).CreationTimeUtc; - } + => default(FileStatus).GetCreationTime(fullPath).UtcDateTime; public static DateTimeOffset GetCreationTime(SafeFileHandle fileHandle) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus output); - if (result == 0) - { - return DateTimeOffset.FromUnixTimeSeconds(output.CTime); - } - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } + => default(FileStatus).GetCreationTime(fileHandle).UtcDateTime; public static void SetCreationTime(string fullPath, DateTimeOffset time, bool asDirectory) - { - FileSystemInfo info = asDirectory ? - (FileSystemInfo)new DirectoryInfo(fullPath, null) : - (FileSystemInfo)new FileInfo(fullPath, null); - - info.CreationTimeCore = time; - } + => default(FileStatus).SetCreationTime(fullPath, time, asDirectory); public static void SetCreationTime(SafeFileHandle fileHandle, DateTimeOffset time) - { - ThrowHelper.ThrowForMissingPath_SafeFileHandle(fileHandle.Path); - SetCreationTime(fileHandle.Path!, time, false); - } + => default(FileStatus).SetCreationTime(fileHandle, time, asDirectory: false); public static DateTimeOffset GetLastAccessTime(string fullPath) - { - return new FileInfo(fullPath, null).LastAccessTimeUtc; - } + => default(FileStatus).GetLastAccessTime(fullPath).UtcDateTime; public static DateTimeOffset GetLastAccessTime(SafeFileHandle fileHandle) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus output); - if (result == 0) - { - return DateTimeOffset.FromUnixTimeSeconds(output.ATime); - } - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } + => default(FileStatus).GetLastAccessTime(fileHandle).UtcDateTime; public static void SetLastAccessTime(string fullPath, DateTimeOffset time, bool asDirectory) - { - FileSystemInfo info = asDirectory ? - (FileSystemInfo)new DirectoryInfo(fullPath, null) : - (FileSystemInfo)new FileInfo(fullPath, null); - - info.LastAccessTimeCore = time; - } + => default(FileStatus).SetLastAccessTime(fullPath, time, asDirectory); public static unsafe void SetLastAccessTime(SafeFileHandle fileHandle, DateTimeOffset time) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus fileStatus); - if (result != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - - // we use futimens() to set the accessTime and writeTime - Interop.Sys.TimeSpec* buf = stackalloc Interop.Sys.TimeSpec[2]; - - long seconds = time.ToUnixTimeSeconds(); - long nanoseconds = UnixTimeSecondsToNanoseconds(time, seconds); - -#if TARGET_BROWSER - buf[0].TvSec = seconds; - buf[0].TvNsec = nanoseconds; - buf[1].TvSec = seconds; - buf[1].TvNsec = nanoseconds; -#else - buf[0].TvSec = seconds; - buf[0].TvNsec = nanoseconds; - buf[1].TvSec = fileStatus.MTime; - buf[1].TvNsec = fileStatus.MTimeNsec; -#endif - int timensResult = Interop.Sys.FUTimens(fileHandle, buf); - if (timensResult != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - } - private static long UnixTimeSecondsToNanoseconds(DateTimeOffset time, long seconds) - { - const long TicksPerMillisecond = 10000; - const long TicksPerSecond = TicksPerMillisecond * 1000; - return (time.UtcDateTime.Ticks - DateTimeOffset.UnixEpoch.Ticks - seconds * TicksPerSecond) * 100; - } + => default(FileStatus).SetLastAccessTime(fileHandle, time, asDirectory: false); public static DateTimeOffset GetLastWriteTime(string fullPath) - { - return new FileInfo(fullPath, null).LastWriteTimeUtc; - } + => default(FileStatus).GetLastWriteTime(fullPath).UtcDateTime; public static DateTimeOffset GetLastWriteTime(SafeFileHandle fileHandle) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus output); - if (result == 0) - { - return DateTimeOffset.FromUnixTimeSeconds(output.MTime); - } - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } + => default(FileStatus).GetLastWriteTime(fileHandle).UtcDateTime; public static void SetLastWriteTime(string fullPath, DateTimeOffset time, bool asDirectory) - { - FileSystemInfo info = asDirectory ? - (FileSystemInfo)new DirectoryInfo(fullPath, null) : - (FileSystemInfo)new FileInfo(fullPath, null); - - info.LastWriteTimeCore = time; - } + => default(FileStatus).SetLastWriteTime(fullPath, time, asDirectory); public static unsafe void SetLastWriteTime(SafeFileHandle fileHandle, DateTimeOffset time) - { - int result = Interop.Sys.FStat(fileHandle, out Interop.Sys.FileStatus fileStatus); - if (result != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - - // we use futimens() to set the accessTime and writeTime - Interop.Sys.TimeSpec* buf = stackalloc Interop.Sys.TimeSpec[2]; - - long seconds = time.ToUnixTimeSeconds(); - long nanoseconds = UnixTimeSecondsToNanoseconds(time, seconds); - -#if TARGET_BROWSER - buf[0].TvSec = seconds; - buf[0].TvNsec = nanoseconds; - buf[1].TvSec = seconds; - buf[1].TvNsec = nanoseconds; -#else - buf[0].TvSec = fileStatus.ATime; - buf[0].TvNsec = fileStatus.ATimeNsec; - buf[1].TvSec = seconds; - buf[1].TvNsec = nanoseconds; -#endif - - int timensResult = Interop.Sys.FUTimens(fileHandle, buf); - if (timensResult != 0) - { - throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), fileHandle.Path); - } - } + => default(FileStatus).SetLastWriteTime(fileHandle, time, asDirectory: false); public static string[] GetLogicalDrives() { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs index 09f6000326111..f475bcbfb59eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs @@ -7,15 +7,8 @@ internal static partial class FileSystem { internal static void VerifyValidPath(string path, string argName) { - if (path == null) - { - throw new ArgumentNullException(argName); - } - else if (path.Length == 0) - { - throw new ArgumentException(SR.Arg_PathEmpty, argName); - } - else if (path.Contains('\0')) + ArgumentException.ThrowIfNullOrEmpty(path, argName); + if (path.Contains('\0')) { throw new ArgumentException(SR.Argument_InvalidPathChars, argName); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs index d59c90f23104f..f74e3c411dd6f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs @@ -7,18 +7,18 @@ namespace System.IO { public partial class FileSystemInfo { + private readonly bool _asDirectory; private FileStatus _fileStatus; protected FileSystemInfo() { - _fileStatus.InitiallyDirectory = this is DirectoryInfo; - _fileStatus.InvalidateCaches(); + _asDirectory = this is DirectoryInfo; } - internal static FileSystemInfo Create(string fullPath, string fileName, ref FileStatus fileStatus) + internal static FileSystemInfo Create(string fullPath, string fileName, bool asDirectory, ref FileStatus fileStatus) { - FileSystemInfo info = fileStatus.InitiallyDirectory - ? (FileSystemInfo)new DirectoryInfo(fullPath, fileName: fileName, isNormalized: true) + FileSystemInfo info = asDirectory + ? new DirectoryInfo(fullPath, fileName: fileName, isNormalized: true) : new FileInfo(fullPath, fileName: fileName, isNormalized: true); Debug.Assert(!PathInternal.IsPartiallyQualified(fullPath), $"'{fullPath}' should be fully qualified when constructed from directory enumeration"); @@ -38,27 +38,27 @@ internal unsafe void Init(ref FileStatus fileStatus) public FileAttributes Attributes { get => _fileStatus.GetAttributes(FullPath, Name); - set => _fileStatus.SetAttributes(FullPath, value); + set => _fileStatus.SetAttributes(FullPath, value, _asDirectory); } - internal bool ExistsCore => _fileStatus.GetExists(FullPath); + internal bool ExistsCore => _fileStatus.GetExists(FullPath, _asDirectory); internal DateTimeOffset CreationTimeCore { get => _fileStatus.GetCreationTime(FullPath); - set => _fileStatus.SetCreationTime(FullPath, value); + set => _fileStatus.SetCreationTime(FullPath, value, _asDirectory); } internal DateTimeOffset LastAccessTimeCore { get => _fileStatus.GetLastAccessTime(FullPath); - set => _fileStatus.SetLastAccessTime(FullPath, value); + set => _fileStatus.SetLastAccessTime(FullPath, value, _asDirectory); } internal DateTimeOffset LastWriteTimeCore { get => _fileStatus.GetLastWriteTime(FullPath); - set => _fileStatus.SetLastWriteTime(FullPath, value); + set => _fileStatus.SetLastWriteTime(FullPath, value, _asDirectory); } internal long LengthCore => _fileStatus.GetLength(FullPath); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs index eb4111efee2b2..26a06b20986f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs @@ -87,7 +87,6 @@ public DateTime CreationTimeUtc set => CreationTimeCore = File.GetUtcDateTimeOffset(value); } - public DateTime LastAccessTime { get => LastAccessTimeUtc.ToLocalTime(); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs index 9677f82426a84..0c1739873f403 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs @@ -32,7 +32,7 @@ public class MemoryStream : Stream private readonly bool _exposable; // Whether the array can be returned to the user. private bool _isOpen; // Is this stream open or closed? - private Task? _lastReadTask; // The last successful task returned from ReadAsync + private CachedCompletedInt32Task _lastReadTask; // The last successful task returned from ReadAsync private const int MemStreamMaxLength = int.MaxValue; @@ -127,7 +127,7 @@ protected override void Dispose(bool disposing) _writable = false; _expandable = false; // Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work. - _lastReadTask = null; + _lastReadTask = default; } } finally @@ -389,10 +389,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel try { int n = Read(buffer, offset, count); - Task? t = _lastReadTask; - Debug.Assert(t == null || t.Status == TaskStatus.RanToCompletion, - "Expected that a stored last task completed successfully"); - return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult(n)); + return _lastReadTask.GetTask(n); } catch (OperationCanceledException oce) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs index f3ec19941c21b..772440a293a52 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs @@ -16,11 +16,7 @@ public static partial class Path // Expands the given path to a fully qualified path. public static string GetFullPath(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - if (path.Length == 0) - throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); if (path.Contains('\0')) throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs index d922e89c13de5..fcbf862ec91c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs @@ -19,12 +19,8 @@ public static partial class RandomAccess // that get stackalloced in the Linux kernel. private const int IovStackThreshold = 8; - internal static long GetFileLength(SafeFileHandle handle) - { - int result = Interop.Sys.FStat(handle, out Interop.Sys.FileStatus status); - FileStreamHelpers.CheckFileCall(result, handle.Path); - return status.Size; - } + internal static unsafe void SetFileLength(SafeFileHandle handle, long length) => + FileStreamHelpers.CheckFileCall(Interop.Sys.FTruncate(handle, length), handle.Path); internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span buffer, long fileOffset) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index 348b0bf4f15a5..2cb2f984904a6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -18,16 +18,25 @@ public static partial class RandomAccess { private static readonly IOCompletionCallback s_callback = AllocateCallback(); - internal static unsafe long GetFileLength(SafeFileHandle handle) + internal static unsafe void SetFileLength(SafeFileHandle handle, long length) { - Interop.Kernel32.FILE_STANDARD_INFO info; + var eofInfo = new Interop.Kernel32.FILE_END_OF_FILE_INFO + { + EndOfFile = length + }; - if (!Interop.Kernel32.GetFileInformationByHandleEx(handle, Interop.Kernel32.FileStandardInfo, &info, (uint)sizeof(Interop.Kernel32.FILE_STANDARD_INFO))) + if (!Interop.Kernel32.SetFileInformationByHandle( + handle, + Interop.Kernel32.FileEndOfFileInfo, + &eofInfo, + (uint)sizeof(Interop.Kernel32.FILE_END_OF_FILE_INFO))) { - throw Win32Marshal.GetExceptionForLastWin32Error(handle.Path); - } + int errorCode = Marshal.GetLastPInvokeError(); - return info.EndOfFile; + throw errorCode == Interop.Errors.ERROR_INVALID_PARAMETER + ? new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_FileLengthTooBig) + : Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path); + } } internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span buffer, long fileOffset) @@ -53,8 +62,8 @@ internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span buffer // "If lpOverlapped is not NULL, then when a synchronous read operation reaches the end of a file, // ReadFile returns FALSE and GetLastError returns ERROR_HANDLE_EOF" return numBytesRead; - case Interop.Errors.ERROR_BROKEN_PIPE: - // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe. + case Interop.Errors.ERROR_BROKEN_PIPE: // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe. + case Interop.Errors.ERROR_INVALID_PARAMETER when IsEndOfFileForNoBuffering(handle, fileOffset): return 0; default: throw Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path); @@ -100,6 +109,7 @@ private static unsafe int ReadSyncUsingAsyncHandle(SafeFileHandle handle, Span fileHandle.IsNoBuffering && fileHandle.CanSeek && fileOffset >= fileHandle.GetFileLength(); + // We need to store the reference count (see the comment in FreeNativeOverlappedIfItIsSafe) and an EventHandle to signal the completion. // We could keep these two things separate, but since ManualResetEvent is sealed and we want to avoid any extra allocations, this type has been created. // It's basically ManualResetEvent with reference count. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs index 04b59ae472a76..7aaaace1e3e47 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO.Strategies; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; @@ -25,7 +24,29 @@ public static long GetLength(SafeFileHandle handle) { ValidateInput(handle, fileOffset: 0); - return GetFileLength(handle); + return handle.GetFileLength(); + } + + /// + /// Sets the length of the file to the given value. + /// + /// The file handle. + /// A long value representing the length of the file in bytes. + /// is . + /// is invalid. + /// The file is closed. + /// The file does not support seeking (pipe or socket). + /// is negative. + public static void SetLength(SafeFileHandle handle, long length) + { + ValidateInput(handle, fileOffset: 0); + + if (length < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException_NeedNonNegNum(nameof(length)); + } + + SetFileLength(handle, length); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs index 9de42145c00de..c1f62e92e4b25 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs @@ -21,7 +21,7 @@ internal sealed class BufferedFileStreamStrategy : FileStreamStrategy private int _readPos; private int _readLen; // The last successful Task returned from ReadAsync (perf optimization for successive reads of the same size) - private Task? _lastSyncCompletedReadTask; + private CachedCompletedInt32Task _lastSyncCompletedReadTask; internal BufferedFileStreamStrategy(FileStreamStrategy strategy, int bufferSize) { @@ -310,21 +310,8 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel ValueTask readResult = ReadAsync(new Memory(buffer, offset, count), cancellationToken); return readResult.IsCompletedSuccessfully - ? LastSyncCompletedReadTask(readResult.Result) + ? _lastSyncCompletedReadTask.GetTask(readResult.Result) : readResult.AsTask(); - - Task LastSyncCompletedReadTask(int val) - { - Task? t = _lastSyncCompletedReadTask; - Debug.Assert(t == null || t.IsCompletedSuccessfully); - - if (t != null && t.Result == val) - return t; - - t = Task.FromResult(val); - _lastSyncCompletedReadTask = t; - return t; - } } public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs index 0f91702c00cc6..a0aa31bb89713 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs @@ -34,9 +34,6 @@ internal static long Seek(SafeFileHandle handle, long offset, SeekOrigin origin, internal static void ThrowInvalidArgument(SafeFileHandle handle) => throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(Interop.Error.EINVAL), handle.Path); - internal static unsafe void SetFileLength(SafeFileHandle handle, long length) => - CheckFileCall(Interop.Sys.FTruncate(handle, length), handle.Path); - /// Flushes the file's OS buffer. internal static void FlushToDisk(SafeFileHandle handle) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs index b519b32a05ba2..3e90bf225385c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs @@ -121,37 +121,6 @@ internal static void Unlock(SafeFileHandle handle, long position, long length) } } - internal static unsafe void SetFileLength(SafeFileHandle handle, long length) - { - if (!TrySetFileLength(handle, length, out int errorCode)) - { - throw errorCode == Interop.Errors.ERROR_INVALID_PARAMETER - ? new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_FileLengthTooBig) - : Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path); - } - } - - internal static unsafe bool TrySetFileLength(SafeFileHandle handle, long length, out int errorCode) - { - var eofInfo = new Interop.Kernel32.FILE_END_OF_FILE_INFO - { - EndOfFile = length - }; - - if (!Interop.Kernel32.SetFileInformationByHandle( - handle, - Interop.Kernel32.FileEndOfFileInfo, - &eofInfo, - (uint)sizeof(Interop.Kernel32.FILE_END_OF_FILE_INFO))) - { - errorCode = Marshal.GetLastPInvokeError(); - return false; - } - - errorCode = Interop.Errors.ERROR_SUCCESS; - return true; - } - internal static unsafe int ReadFileNative(SafeFileHandle handle, Span bytes, NativeOverlapped* overlapped, out int errorCode) { Debug.Assert(handle != null, "handle != null"); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs index e3b419e278973..5a067fd76ee46 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs @@ -53,14 +53,7 @@ e is NotSupportedException || internal static void ValidateArguments(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) { - if (path == null) - { - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - } - else if (path.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - } + ArgumentException.ThrowIfNullOrEmpty(path); // don't include inheritable in our bounds check for share FileShare tempshare = share & ~FileShare.Inheritable; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs index 0386dfa78d563..80f1427789b6d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using System.Threading.Tasks.Sources; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies @@ -16,9 +15,7 @@ internal abstract class OSFileStreamStrategy : FileStreamStrategy private readonly FileAccess _access; // What file was opened for. protected long _filePosition; - private long _length = -1; // negative means that hasn't been fetched. private long _appendStart; // When appending, prevent overwriting file. - private bool _lengthCanBeCached; // SafeFileHandle hasn't been exposed, file has been opened for reading and not shared for writing. internal OSFileStreamStrategy(SafeFileHandle handle, FileAccess access) { @@ -45,7 +42,6 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil string fullPath = Path.GetFullPath(path); _access = access; - _lengthCanBeCached = (share & FileShare.Write) == 0 && (access & FileAccess.Write) == 0; _fileHandle = SafeFileHandle.Open(fullPath, mode, access, share, options, preallocationSize); @@ -78,34 +74,13 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil public sealed override bool CanWrite => !_fileHandle.IsClosed && (_access & FileAccess.Write) != 0; - public unsafe sealed override long Length - { - get - { - if (!LengthCachingSupported) - { - return RandomAccess.GetFileLength(_fileHandle); - } - - // On Windows, when the file is locked for writes we can cache file length - // in memory and avoid subsequent native calls which are expensive. - - if (_length < 0) - { - _length = RandomAccess.GetFileLength(_fileHandle); - } - - return _length; - } - } + public unsafe sealed override long Length => _fileHandle.GetFileLength(); // in case of concurrent incomplete reads, there can be multiple threads trying to update the position // at the same time. That is why we are using Interlocked here. internal void OnIncompleteOperation(int expectedBytesTransferred, int actualBytesTransferred) => Interlocked.Add(ref _filePosition, actualBytesTransferred - expectedBytesTransferred); - private bool LengthCachingSupported => OperatingSystem.IsWindows() && _lengthCanBeCached; - /// Gets or sets the position within the current stream public sealed override long Position { @@ -129,9 +104,6 @@ internal sealed override SafeFileHandle SafeFileHandle FileStreamHelpers.Seek(_fileHandle, _filePosition, SeekOrigin.Begin); } - _lengthCanBeCached = false; - _length = -1; // invalidate cached length - return _fileHandle; } } @@ -223,11 +195,8 @@ protected unsafe void SetLengthCore(long value) { Debug.Assert(value >= 0, "value >= 0"); - FileStreamHelpers.SetFileLength(_fileHandle, value); - if (LengthCachingSupported) - { - _length = value; - } + RandomAccess.SetFileLength(_fileHandle, value); + Debug.Assert(!_fileHandle.TryGetCachedLength(out _), "If length can be cached (file opened for reading, not shared for writing), it should be impossible to modify file length"); if (_filePosition > value) { @@ -314,7 +283,7 @@ public sealed override ValueTask ReadAsync(Memory destination, Cancel return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); } - if (LengthCachingSupported && _length >= 0 && Volatile.Read(ref _filePosition) >= _length) + if (_fileHandle.TryGetCachedLength(out long cachedLength) && Volatile.Read(ref _filePosition) >= cachedLength) { // We know for sure that the file length can be safely cached and it has already been obtained. // If we have reached EOF we just return here and avoid a sys-call. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index 3b3e03a806ff5..785e2c8e4a0b6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -210,12 +210,9 @@ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteO private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) { - ValidateArgs(path, encoding); - - if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); + ArgumentNullException.ThrowIfNull(options); if ((options.Access & FileAccess.Read) == 0) { throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(options)); @@ -226,23 +223,16 @@ private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, Fi private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, int bufferSize) { - ValidateArgs(path, encoding); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); if (bufferSize <= 0) + { throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + } return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize); } - private static void ValidateArgs(string path, Encoding encoding) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath); - } - public override void Close() { Dispose(true); @@ -845,7 +835,37 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer) return sb.ToString(); } - public override Task ReadLineAsync() + public override Task ReadLineAsync() => + ReadLineAsync(default).AsTask(); + + /// + /// Reads a line of characters asynchronously from the current stream and returns the data as a string. + /// + /// The token to monitor for cancellation requests. + /// A value task that represents the asynchronous read operation. The value of the TResult + /// parameter contains the next line from the stream, or is if all of the characters have been read. + /// The number of characters in the next line is larger than . + /// The stream reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The following example shows how to read and print all lines from the file until the end of the file is reached or the operation timed out. + /// + /// using CancellationTokenSource tokenSource = new (TimeSpan.FromSeconds(1)); + /// using StreamReader reader = File.OpenText("existingfile.txt"); + /// + /// string line; + /// while ((line = await reader.ReadLineAsync(tokenSource.Token)) is not null) + /// { + /// Console.WriteLine(line); + /// } + /// + /// + /// + /// If this method is canceled via , some data + /// that has been read from the current but not stored (by the + /// ) or returned (to the caller) may be lost. + /// + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) { // If we have been inherited into a subclass, the following implementation could be incorrect // since it does not call through to Read() which a subclass might have overridden. @@ -853,21 +873,21 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer) // and delegate to our base class (which will call into Read) when we are not sure. if (GetType() != typeof(StreamReader)) { - return base.ReadLineAsync(); + return base.ReadLineAsync(cancellationToken); } ThrowIfDisposed(); CheckAsyncTaskInProgress(); - Task task = ReadLineAsyncInternal(); + Task task = ReadLineAsyncInternal(cancellationToken); _asyncReadTask = task; - return task; + return new ValueTask(task); } - private async Task ReadLineAsyncInternal() + private async Task ReadLineAsyncInternal(CancellationToken cancellationToken) { - if (_charPos == _charLen && (await ReadBufferAsync(CancellationToken.None).ConfigureAwait(false)) == 0) + if (_charPos == _charLen && (await ReadBufferAsync(cancellationToken).ConfigureAwait(false)) == 0) { return null; } @@ -903,7 +923,7 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer) _charPos = tmpCharPos = i + 1; - if (ch == '\r' && (tmpCharPos < tmpCharLen || (await ReadBufferAsync(CancellationToken.None).ConfigureAwait(false)) > 0)) + if (ch == '\r' && (tmpCharPos < tmpCharLen || (await ReadBufferAsync(cancellationToken).ConfigureAwait(false)) > 0)) { tmpCharPos = _charPos; if (_charBuffer[tmpCharPos] == '\n') @@ -921,12 +941,37 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer) i = tmpCharLen - tmpCharPos; sb ??= new StringBuilder(i + 80); sb.Append(tmpCharBuffer, tmpCharPos, i); - } while (await ReadBufferAsync(CancellationToken.None).ConfigureAwait(false) > 0); + } while (await ReadBufferAsync(cancellationToken).ConfigureAwait(false) > 0); return sb.ToString(); } - public override Task ReadToEndAsync() + public override Task ReadToEndAsync() => ReadToEndAsync(default); + + /// + /// Reads all characters from the current position to the end of the stream asynchronously and returns them as one string. + /// + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous read operation. The value of the TResult parameter contains + /// a string with the characters from the current position to the end of the stream. + /// The number of characters is larger than . + /// The stream reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The following example shows how to read the contents of a file by using the method. + /// + /// using CancellationTokenSource tokenSource = new (TimeSpan.FromSeconds(1)); + /// using StreamReader reader = File.OpenText("existingfile.txt"); + /// + /// Console.WriteLine(await reader.ReadToEndAsync(tokenSource.Token)); + /// + /// + /// + /// If this method is canceled via , some data + /// that has been read from the current but not stored (by the + /// ) or returned (to the caller) may be lost. + /// + public override Task ReadToEndAsync(CancellationToken cancellationToken) { // If we have been inherited into a subclass, the following implementation could be incorrect // since it does not call through to Read() which a subclass might have overridden. @@ -934,19 +979,19 @@ public override Task ReadToEndAsync() // and delegate to our base class (which will call into Read) when we are not sure. if (GetType() != typeof(StreamReader)) { - return base.ReadToEndAsync(); + return base.ReadToEndAsync(cancellationToken); } ThrowIfDisposed(); CheckAsyncTaskInProgress(); - Task task = ReadToEndAsyncInternal(); + Task task = ReadToEndAsyncInternal(cancellationToken); _asyncReadTask = task; return task; } - private async Task ReadToEndAsyncInternal() + private async Task ReadToEndAsyncInternal(CancellationToken cancellationToken) { // Call ReadBuffer, then pull data out of charBuffer. StringBuilder sb = new StringBuilder(_charLen - _charPos); @@ -955,7 +1000,7 @@ private async Task ReadToEndAsyncInternal() int tmpCharPos = _charPos; sb.Append(_charBuffer, tmpCharPos, _charLen - tmpCharPos); _charPos = _charLen; // We consumed these characters - await ReadBufferAsync(CancellationToken.None).ConfigureAwait(false); + await ReadBufferAsync(cancellationToken).ConfigureAwait(false); } while (_charLen > 0); return sb.ToString(); @@ -1331,7 +1376,7 @@ private void ThrowIfDisposed() // No data, class doesn't need to be serializable. // Note this class is threadsafe. - private sealed class NullStreamReader : StreamReader + internal sealed class NullStreamReader : StreamReader { public override Encoding CurrentEncoding => Encoding.Unicode; @@ -1340,35 +1385,46 @@ protected override void Dispose(bool disposing) // Do nothing - this is essentially unclosable. } - public override int Peek() - { - return -1; - } + public override int Peek() => -1; - public override int Read() - { - return -1; - } + public override int Read() => -1; - public override int Read(char[] buffer, int index, int count) - { - return 0; - } + public override int Read(char[] buffer, int index, int count) => 0; - public override string? ReadLine() - { - return null; - } + public override int Read(Span buffer) => 0; - public override string ReadToEnd() - { - return string.Empty; - } + public override Task ReadAsync(char[] buffer, int index, int count) => Task.FromResult(0); - internal override int ReadBuffer() - { - return 0; - } + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : default; + + public override int ReadBlock(char[] buffer, int index, int count) => 0; + + public override int ReadBlock(Span buffer) => 0; + + public override Task ReadBlockAsync(char[] buffer, int index, int count) => Task.FromResult(0); + + public override ValueTask ReadBlockAsync(Memory buffer, CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : default; + + public override string? ReadLine() => null; + + public override Task ReadLineAsync() => Task.FromResult(null); + + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : default; + + public override string ReadToEnd() => ""; + + public override Task ReadToEndAsync() => Task.FromResult(""); + + public override Task ReadToEndAsync(CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : Task.FromResult(""); + + internal override ValueTask ReadAsyncInternal(Memory buffer, CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : default; + + internal override int ReadBuffer() => 0; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index 7ba362604d01c..c591e51f15e23 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -166,12 +166,9 @@ public StreamWriter(string path, Encoding encoding, FileStreamOptions options) private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) { - ValidateArgs(path, encoding); - - if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); + ArgumentNullException.ThrowIfNull(options); if ((options.Access & FileAccess.Write) == 0) { throw new ArgumentException(SR.Argument_StreamNotWritable, nameof(options)); @@ -182,23 +179,16 @@ private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, Fi private static Stream ValidateArgsAndOpenPath(string path, bool append, Encoding encoding, int bufferSize) { - ValidateArgs(path, encoding); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); if (bufferSize <= 0) + { throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + } return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize); } - private static void ValidateArgs(string path, Encoding encoding) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath); - } - public override void Close() { Dispose(true); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StringReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StringReader.cs index 3d50897ec7f38..a8e07ad382d15 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StringReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StringReader.cs @@ -224,11 +224,74 @@ public override string ReadToEnd() return Task.FromResult(ReadLine()); } + /// + /// Reads a line of characters asynchronously from the current string and returns the data as a string. + /// + /// The token to monitor for cancellation requests. + /// A value task that represents the asynchronous read operation. The value of the TResult + /// parameter contains the next line from the string reader, or is if all of the characters have been read. + /// The number of characters in the next line is larger than . + /// The string reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The following example shows how to read one line at a time from a string asynchronously. + /// + /// using System.Text; + /// + /// StringBuilder stringToRead = new(); + /// stringToRead.AppendLine("Characters in 1st line to read"); + /// stringToRead.AppendLine("and 2nd line"); + /// stringToRead.AppendLine("and the end"); + /// + /// string readText; + /// using CancellationTokenSource tokenSource = new (TimeSpan.FromSeconds(1)); + /// using StringReader reader = new (stringToRead.ToString()); + /// while ((readText = await reader.ReadLineAsync(tokenSource.Token)) is not null) + /// { + /// Console.WriteLine(readText); + /// } + /// + /// + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested + ? ValueTask.FromCanceled(cancellationToken) + : new ValueTask(ReadLine()); + public override Task ReadToEndAsync() { return Task.FromResult(ReadToEnd()); } + /// + /// Reads all characters from the current position to the end of the string asynchronously and returns them as a single string. + /// + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous read operation. The value of the TResult parameter contains + /// a string with the characters from the current position to the end of the string. + /// The number of characters is larger than . + /// The string reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The following example shows how to read an entire string asynchronously. + /// + /// using System.Text; + /// + /// StringBuilder stringToRead = new(); + /// stringToRead.AppendLine("Characters in 1st line to read"); + /// stringToRead.AppendLine("and 2nd line"); + /// stringToRead.AppendLine("and the end"); + /// + /// using CancellationTokenSource tokenSource = new (TimeSpan.FromSeconds(1)); + /// using StringReader reader = new (stringToRead.ToString()); + /// var readText = await reader.ReadToEndAsync(tokenSource.Token); + /// Console.WriteLine(readText); + /// + /// + public override Task ReadToEndAsync(CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested + ? Task.FromCanceled(cancellationToken) + : Task.FromResult(ReadToEnd()); + public override Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs index 05211d6dc7a33..a0536bd022e8e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs @@ -19,7 +19,8 @@ namespace System.IO // There are methods on the Stream class for reading bytes. public abstract partial class TextReader : MarshalByRefObject, IDisposable { - public static readonly TextReader Null = new NullTextReader(); + // Create our own instance to avoid static field initialization order problems on Mono. + public static readonly TextReader Null = new StreamReader.NullStreamReader(); protected TextReader() { } @@ -203,18 +204,56 @@ public virtual int ReadBlock(Span buffer) } #region Task based Async APIs - public virtual Task ReadLineAsync() => + public virtual Task ReadLineAsync() => ReadLineCoreAsync(default); + + /// + /// Reads a line of characters asynchronously and returns the data as a string. + /// + /// The token to monitor for cancellation requests. + /// A value task that represents the asynchronous read operation. The value of the TResult + /// parameter contains the next line from the text reader, or is if all of the characters have been read. + /// The number of characters in the next line is larger than . + /// The text reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The class is an abstract class. Therefore, you do not instantiate it in + /// your code. For an example of using the method, see the + /// method. + /// If the current represents the standard input stream returned by + /// the Console.In property, the method + /// executes synchronously rather than asynchronously. + /// + public virtual ValueTask ReadLineAsync(CancellationToken cancellationToken) => + new ValueTask(ReadLineCoreAsync(cancellationToken)); + + private Task ReadLineCoreAsync(CancellationToken cancellationToken) => Task.Factory.StartNew(static state => ((TextReader)state!).ReadLine(), this, - CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - - public virtual async Task ReadToEndAsync() + cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + + public virtual Task ReadToEndAsync() => ReadToEndAsync(default); + + /// + /// Reads all characters from the current position to the end of the text reader asynchronously and returns them as one string. + /// + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous read operation. The value of the TResult parameter contains + /// a string with the characters from the current position to the end of the text reader. + /// The number of characters is larger than . + /// The text reader has been disposed. + /// The reader is currently in use by a previous read operation. + /// + /// The class is an abstract class. Therefore, you do not instantiate it in + /// your code. For an example of using the method, see the + /// method. + /// + public virtual async Task ReadToEndAsync(CancellationToken cancellationToken) { var sb = new StringBuilder(4096); char[] chars = ArrayPool.Shared.Rent(4096); try { int len; - while ((len = await ReadAsyncInternal(chars, default).ConfigureAwait(false)) != 0) + while ((len = await ReadAsyncInternal(chars, cancellationToken).ConfigureAwait(false)) != 0) { sb.Append(chars, 0, len); } @@ -300,21 +339,6 @@ internal async ValueTask ReadBlockAsyncInternal(Memory buffer, Cancel } #endregion - private sealed class NullTextReader : TextReader - { - public NullTextReader() { } - - public override int Read(char[] buffer, int index, int count) - { - return 0; - } - - public override string? ReadLine() - { - return null; - } - } - public static TextReader Synchronized(TextReader reader) { if (reader == null) @@ -368,9 +392,17 @@ protected override void Dispose(bool disposing) [MethodImpl(MethodImplOptions.Synchronized)] public override Task ReadLineAsync() => Task.FromResult(ReadLine()); + [MethodImpl(MethodImplOptions.Synchronized)] + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) + => cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : new ValueTask(ReadLine()); + [MethodImpl(MethodImplOptions.Synchronized)] public override Task ReadToEndAsync() => Task.FromResult(ReadToEnd()); + [MethodImpl(MethodImplOptions.Synchronized)] + public override Task ReadToEndAsync(CancellationToken cancellationToken) + => cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : Task.FromResult(ReadToEnd()); + [MethodImpl(MethodImplOptions.Synchronized)] public override Task ReadBlockAsync(char[] buffer, int index, int count) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs index 0e53df433e78c..78d0dab488a56 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs @@ -319,7 +319,7 @@ public void Read(long position, out T structure) where T : struct } else { - throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToRead, typeof(T)), nameof(position)); + throw new ArgumentException(SR.Argument_NotEnoughBytesToRead, nameof(position)); } } @@ -561,7 +561,7 @@ public void Write(long position, ref T structure) where T : struct } else { - throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToWrite, typeof(T)), nameof(position)); + throw new ArgumentException(SR.Argument_NotEnoughBytesToWrite, nameof(position)); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs index c116c17e69ad8..47b190dde4b49 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs @@ -46,7 +46,7 @@ public class UnmanagedMemoryStream : Stream private long _offset; private FileAccess _access; private bool _isOpen; - private Task? _lastReadTask; // The last successful task returned from ReadAsync + private CachedCompletedInt32Task _lastReadTask; // The last successful task returned from ReadAsync /// /// Creates a closed stream. @@ -437,12 +437,11 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel try { int n = Read(buffer, offset, count); - Task? t = _lastReadTask; - return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult(n)); + return _lastReadTask.GetTask(n); } catch (Exception ex) { - Debug.Assert(!(ex is OperationCanceledException)); + Debug.Assert(ex is not OperationCanceledException); return Task.FromException(ex); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs b/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs index 0998785f780ba..15e7717435d96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs @@ -15,6 +15,7 @@ public interface ISpanFormattable : IFormattable /// /// An implementation of this interface should produce the same string of characters as an implementation of /// on the same type. + /// TryFormat should return false only if there is not enough space in the destination buffer. Any other failures should throw an exception. /// bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index 7fb1803d6f5ab..355578395db40 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -11,6 +11,8 @@ using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + #if TARGET_64BIT using nint_t = System.Int64; #else diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index f242b825fb170..a929322173585 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -49,9 +49,9 @@ public static partial class Math private const double SCALEB_C3 = 9007199254740992; // 0x1p53 - private const int ILogB_NaN = 0x7fffffff; + private const int ILogB_NaN = 0x7FFFFFFF; - private const int ILogB_Zero = (-1 - 0x7fffffff); + private const int ILogB_Zero = (-1 - 0x7FFFFFFF); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short Abs(short value) @@ -133,6 +133,26 @@ public static decimal Abs(decimal value) return decimal.Abs(value); } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Abs(double value) + { + const ulong mask = 0x7FFFFFFFFFFFFFFF; + ulong raw = BitConverter.DoubleToUInt64Bits(value); + + return BitConverter.UInt64BitsToDouble(raw & mask); + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Abs(float value) + { + const uint mask = 0x7FFFFFFF; + uint raw = BitConverter.SingleToUInt32Bits(value); + + return BitConverter.UInt32BitsToSingle(raw & mask); + } + [DoesNotReturn] [StackTraceHidden] private static void ThrowAbsOverflow() diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index b49dea6f3638a..3c7c13fa645f0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -580,12 +580,25 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + } + if (Unsafe.SizeOf() == sizeof(char)) + { + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + } + } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs index 0fa9141483ee2..089f970057dc8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Runtime.Versioning; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { // Because we have special type system support that says a boxed Nullable diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index 6a7141cd01cd4..419a1c9f5f114 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -708,5 +708,25 @@ public static nuint RotateRight(nuint value, int offset) return (nuint)RotateRight((uint)value, offset); #endif } + + /// + /// Reset the lowest significant bit in the given value + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static uint ResetLowestSetBit(uint value) + { + // It's lowered to BLSR on x86 + return value & (value - 1); + } + + /// + /// Reset specific bit in the given value + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static uint ResetBit(uint value, int bitPos) + { + // TODO: Recognize BTR on x86 and LSL+BIC on ARM + return value & ~(uint)(1 << bitPos); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Random.cs b/src/libraries/System.Private.CoreLib/src/System/Random.cs index 05766c724d267..9107044882333 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Random.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Random.cs @@ -192,7 +192,7 @@ protected virtual double Sample() } private static void ThrowMaxValueMustBeNonNegative() => - throw new ArgumentOutOfRangeException("maxValue", SR.Format(SR.ArgumentOutOfRange_NeedNonNegNum, "maxValue")); + throw new ArgumentOutOfRangeException("maxValue", SR.ArgumentOutOfRange_NeedNonNegNum); private static void ThrowMinMaxValueSwapped() => throw new ArgumentOutOfRangeException("minValue", SR.Format(SR.Argument_MinMaxValue, "minValue", "maxValue")); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 198c6804b7e4f..5594d4fdef7f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -25,6 +25,32 @@ public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, private AssemblyVersionCompatibility _versionCompatibility; private AssemblyNameFlags _flags; + public AssemblyName(string assemblyName) + : this() + { + if (assemblyName == null) + throw new ArgumentNullException(nameof(assemblyName)); + if ((assemblyName.Length == 0) || + (assemblyName[0] == '\0')) + throw new ArgumentException(SR.Format_StringZeroLength); + + AssemblyNameParser.AssemblyNameParts parts = AssemblyNameParser.Parse(assemblyName); + _name = parts._name; + _version = parts._version; + _flags = parts._flags; + if ((parts._flags & AssemblyNameFlags.PublicKey) != 0) + { + _publicKey = parts._publicKeyOrToken; + } + else + { + _publicKeyToken = parts._publicKeyOrToken; + } + + if (parts._cultureName != null) + _cultureInfo = new CultureInfo(parts._cultureName); + } + public AssemblyName() { _versionCompatibility = AssemblyVersionCompatibility.SameMachine; @@ -136,6 +162,28 @@ public object Clone() return name; } + private static Func? s_getAssemblyName; + private static Func InitGetAssemblyName() + { + Type? readerType = Type.GetType( + "System.Reflection.Metadata.MetadataReader, System.Reflection.Metadata", + throwOnError: true); + + MethodInfo? getAssemblyNameMethod = readerType!.GetMethod( + "GetAssemblyName", + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, + null, + new Type[] { typeof(string) }, + null); + + if (getAssemblyNameMethod == null) + { + throw new MissingMethodException(readerType.FullName, "GetAssemblyName"); + } + + return s_getAssemblyName = getAssemblyNameMethod.CreateDelegate>(); + } + /* * Get the AssemblyName for a given file. This will only work * if the file contains an assembly manifest. This method causes @@ -143,10 +191,7 @@ public object Clone() */ public static AssemblyName GetAssemblyName(string assemblyFile) { - if (assemblyFile == null) - throw new ArgumentNullException(nameof(assemblyFile)); - - return GetFileInformationCore(assemblyFile); + return (s_getAssemblyName ?? InitGetAssemblyName())(assemblyFile); } public byte[]? GetPublicKey() @@ -166,7 +211,7 @@ public void SetPublicKey(byte[]? publicKey) // The compressed version of the public key formed from a truncated hash. // Will throw a SecurityException if _publicKey is invalid - public byte[]? GetPublicKeyToken() => _publicKeyToken ??= ComputePublicKeyToken(); + public byte[]? GetPublicKeyToken() => _publicKeyToken ??= AssemblyNameHelpers.ComputePublicKeyToken(_publicKey); public void SetPublicKeyToken(byte[]? publicKeyToken) { @@ -219,7 +264,7 @@ public string FullName return string.Empty; // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want. - byte[]? pkt = _publicKeyToken ?? ComputePublicKeyToken(); + byte[]? pkt = _publicKeyToken ?? AssemblyNameHelpers.ComputePublicKeyToken(_publicKey); return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs rename to src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs index 85e437548102e..ef05ef39f8a7e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs @@ -2,12 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers.Binary; -using System.Runtime; using System.Security; namespace System.Reflection { - public static partial class AssemblyNameHelpers + internal static partial class AssemblyNameHelpers { public static byte[]? ComputePublicKeyToken(byte[]? publicKey) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs new file mode 100644 index 0000000000000..ab3be2c8f06d2 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs @@ -0,0 +1,427 @@ +// 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 System.Runtime.CompilerServices; +using System.Text; + +namespace System.Reflection +{ + // + // Parses an assembly name. + // + internal ref struct AssemblyNameParser + { + public struct AssemblyNameParts + { + public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) + { + _name = name; + _version = version; + _cultureName = cultureName; + _flags = flags; + _publicKeyOrToken = publicKeyOrToken; + } + + public string _name; + public Version? _version; + public string? _cultureName; + public AssemblyNameFlags _flags; + public byte[]? _publicKeyOrToken; + } + + // Token categories for the lexer. + private enum Token + { + Equals = 1, + Comma = 2, + String = 3, + End = 4, + } + + private enum AttributeKind + { + Version = 1, + Culture = 2, + PublicKeyOrToken = 4, + ProcessorArchitecture = 8, + Retargetable = 16, + ContentType = 32 + } + + private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' }; + private string _input; + private int _index; + + private AssemblyNameParser(string input) + { + Debug.Assert(input != null); + if (input.Length == 0) + throw new ArgumentException(SR.Format_StringZeroLength); + + _input = input; + _index = 0; + } + + public static AssemblyNameParts Parse(string s) + { + return new AssemblyNameParser(s).Parse(); + } + + private void RecordNewSeenOrThrow(ref AttributeKind seenAttributes, AttributeKind newAttribute) + { + if ((seenAttributes & newAttribute) != 0) + { + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + else + { + seenAttributes |= newAttribute; + } + } + + private AssemblyNameParts Parse() + { + // Name must come first. + string name; + Token token = GetNextToken(out name); + if (token != Token.String) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + Version? version = null; + string? cultureName = null; + byte[]? pkt = null; + AssemblyNameFlags flags = 0; + + AttributeKind alreadySeen = default; + token = GetNextToken(); + while (token != Token.End) + { + if (token != Token.Comma) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + string attributeName; + + token = GetNextToken(out attributeName); + if (token != Token.String) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + token = GetNextToken(); + + if (token != Token.Equals) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + string attributeValue; + token = GetNextToken(out attributeValue); + if (token != Token.String) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + if (attributeName == string.Empty) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Version); + version = ParseVersion(attributeValue); + } + + if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Culture); + cultureName = ParseCulture(attributeValue); + } + + if (attributeName.Equals("PublicKey", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); + pkt = ParsePKT(attributeValue, isToken: false); + flags |= AssemblyNameFlags.PublicKey; + } + + if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); + pkt = ParsePKT(attributeValue, isToken: true); + } + + if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ProcessorArchitecture); + flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4); + } + + if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Retargetable); + if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) + flags |= AssemblyNameFlags.Retargetable; + else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) + { + // nothing to do + } + else + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + + if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase)) + { + RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ContentType); + if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) + flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); + else + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + + // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it. + token = GetNextToken(); + } + + return new AssemblyNameParts(name, version, cultureName, flags, pkt); + } + + private Version ParseVersion(string attributeValue) + { + string[] parts = attributeValue.Split('.'); + if (parts.Length > 4) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + ushort[] versionNumbers = new ushort[4]; + for (int i = 0; i < versionNumbers.Length; i++) + { + if (i >= parts.Length) + versionNumbers[i] = ushort.MaxValue; + else + { + // Desktop compat: TryParse is a little more forgiving than Fusion. + for (int j = 0; j < parts[i].Length; j++) + { + if (!char.IsDigit(parts[i][j])) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + if (!(ushort.TryParse(parts[i], out versionNumbers[i]))) + { + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + } + } + + if (versionNumbers[0] == ushort.MaxValue || versionNumbers[1] == ushort.MaxValue) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + if (versionNumbers[2] == ushort.MaxValue) + return new Version(versionNumbers[0], versionNumbers[1]); + if (versionNumbers[3] == ushort.MaxValue) + return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]); + return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); + } + + private string ParseCulture(string attributeValue) + { + if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) + { + return ""; + } + + return attributeValue; + } + + private byte[] ParsePKT(string attributeValue, bool isToken) + { + if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) + return Array.Empty(); + + if (isToken && attributeValue.Length != 8 * 2) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + byte[] pkt = new byte[attributeValue.Length / 2]; + int srcIndex = 0; + for (int i = 0; i < pkt.Length; i++) + { + char hi = attributeValue[srcIndex++]; + char lo = attributeValue[srcIndex++]; + pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo)); + } + return pkt; + } + + private ProcessorArchitecture ParseProcessorArchitecture(string attributeValue) + { + if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase)) + return ProcessorArchitecture.MSIL; + if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase)) + return ProcessorArchitecture.X86; + if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase)) + return ProcessorArchitecture.IA64; + if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase)) + return ProcessorArchitecture.Amd64; + if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase)) + return ProcessorArchitecture.Arm; + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + return default; // unreachable + } + + private byte ParseHexNybble(char c) + { + if (c >= '0' && c <= '9') + return (byte)(c - '0'); + if (c >= 'a' && c <= 'f') + return (byte)(c - 'a' + 10); + if (c >= 'A' && c <= 'F') + return (byte)(c - 'A' + 10); + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + return default; // unreachable + } + + // + // Return the next token in assembly name. If you expect the result to be Token.String, + // use GetNext(out String) instead. + // + private Token GetNextToken() + { + return GetNextToken(out _); + } + + private static bool IsWhiteSpace(char ch) + { + switch (ch) + { + case '\n': + case '\r': + case ' ': + case '\t': + return true; + default: + return false; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private char GetNextChar() + { + char ch; + if (_index < _input.Length) + { + ch = _input[_index++]; + if (ch == '\0') + { + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + } + else + { + ch = '\0'; + } + + return ch; + } + + // + // Return the next token in assembly name. If the result is Token.String, + // sets "tokenString" to the tokenized string. + // + private Token GetNextToken(out string tokenString) + { + tokenString = string.Empty; + char c; + + while (true) + { + c = GetNextChar(); + switch (c) + { + case ',': + return Token.Comma; + case '=': + return Token.Equals; + case '\0': + return Token.End; + } + + if (!IsWhiteSpace(c)) + { + break; + } + } + + ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); + + char quoteChar = '\0'; + if (c == '\'' || c == '\"') + { + quoteChar = c; + c = GetNextChar(); + } + + for (; ; ) + { + if (c == 0) + { + if (quoteChar != 0) + { + // EOS and unclosed quotes is an error + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + } + else + { + // Reached end of input and therefore of string + break; + } + } + + if (quoteChar != 0 && c == quoteChar) + break; // Terminate: Found closing quote of quoted string. + + if (quoteChar == 0 && (c == ',' || c == '=')) + { + _index--; + break; // Terminate: Found start of a new ',' or '=' token. + } + + if (quoteChar == 0 && (c == '\'' || c == '\"')) + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + + if (c == '\\') + { + c = GetNextChar(); + + switch (c) + { + case '\\': + case ',': + case '=': + case '\'': + case '"': + sb.Append(c); + break; + case 't': + sb.Append('\t'); + break; + case 'r': + sb.Append('\r'); + break; + case 'n': + sb.Append('\n'); + break; + default: + ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input); + return default; //unreachable + } + } + else + { + sb.Append(c); + } + + c = GetNextChar(); + } + + + if (quoteChar == 0) + { + while (sb.Length > 0 && IsWhiteSpace(sb[sb.Length - 1])) + sb.Length--; + } + + tokenString = sb.ToString(); + return Token.String; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs index 9699e14e5d1e5..b2baa777460a6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs @@ -1,9 +1,11 @@ // 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.CodeAnalysis; + namespace System.Reflection { - public readonly partial struct CustomAttributeNamedArgument + public readonly partial struct CustomAttributeNamedArgument : IEquatable { public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right) => left.Equals(right); public static bool operator !=(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right) => !left.Equals(right); @@ -46,10 +48,15 @@ public override int GetHashCode() return base.GetHashCode(); } - public override bool Equals(object? obj) - { - return obj == (object)this; - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is CustomAttributeNamedArgument other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CustomAttributeNamedArgument other) => + _memberInfo == other._memberInfo && + _value == other._value; internal Type ArgumentType => _memberInfo is FieldInfo fi ? diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs index 3198e9fd45802..b0e306af8f838 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace System.Reflection { - public readonly partial struct CustomAttributeTypedArgument + public readonly partial struct CustomAttributeTypedArgument : IEquatable { public static bool operator ==(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right) => left.Equals(right); public static bool operator !=(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right) => !left.Equals(right); @@ -86,7 +87,13 @@ internal string ToString(bool typed) } public override int GetHashCode() => base.GetHashCode(); - public override bool Equals(object? obj) => obj == (object)this; + + public override bool Equals([NotNullWhen(true)] object? obj) => obj is CustomAttributeTypedArgument cata && Equals(cata); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CustomAttributeTypedArgument other) => _value == other._value && _argumentType == other._argumentType; public Type ArgumentType => _argumentType; public object? Value => _value; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs index b09bb83a5a687..1a87dc84ee96b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; namespace System.Reflection { @@ -27,7 +28,7 @@ private enum NotAnnotatedStatus Internal = 0x2 // internal members not annotated } - private NullabilityState GetNullableContext(MemberInfo? memberInfo) + private NullabilityState? GetNullableContext(MemberInfo? memberInfo) { while (memberInfo != null) { @@ -51,7 +52,7 @@ private NullabilityState GetNullableContext(MemberInfo? memberInfo) memberInfo = memberInfo.DeclaringType; } - return NullabilityState.Unknown; + return null; } /// @@ -71,13 +72,11 @@ public NullabilityInfo Create(ParameterInfo parameterInfo) EnsureIsSupported(); - if (parameterInfo.Member is MethodInfo method && IsPrivateOrInternalMethodAndAnnotationDisabled(method)) - { - return new NullabilityInfo(parameterInfo.ParameterType, NullabilityState.Unknown, NullabilityState.Unknown, null, Array.Empty()); - } - IList attributes = parameterInfo.GetCustomAttributesData(); - NullabilityInfo nullability = GetNullabilityInfo(parameterInfo.Member, parameterInfo.ParameterType, attributes); + NullableAttributeStateParser parser = parameterInfo.Member is MethodBase method && IsPrivateOrInternalMethodAndAnnotationDisabled(method) + ? NullableAttributeStateParser.Unknown + : CreateParser(attributes); + NullabilityInfo nullability = GetNullabilityInfo(parameterInfo.Member, parameterInfo.ParameterType, parser); if (nullability.ReadState != NullabilityState.Unknown) { @@ -114,7 +113,7 @@ private void CheckParameterMetadataType(ParameterInfo parameter, NullabilityInfo if (metaParameter != null) { - CheckGenericParameters(nullability, metaMethod, metaParameter.ParameterType); + CheckGenericParameters(nullability, metaMethod, metaParameter.ParameterType, parameter.Member.ReflectedType); } } } @@ -131,40 +130,45 @@ private static MethodInfo GetMethodMetadataDefinition(MethodInfo method) private void CheckNullabilityAttributes(NullabilityInfo nullability, IList attributes) { + var codeAnalysisReadState = NullabilityState.Unknown; + var codeAnalysisWriteState = NullabilityState.Unknown; + foreach (CustomAttributeData attribute in attributes) { if (attribute.AttributeType.Namespace == "System.Diagnostics.CodeAnalysis") { - if (attribute.AttributeType.Name == "NotNullAttribute" && - nullability.ReadState == NullabilityState.Nullable) + if (attribute.AttributeType.Name == "NotNullAttribute") { - nullability.ReadState = NullabilityState.NotNull; - break; + codeAnalysisReadState = NullabilityState.NotNull; } else if ((attribute.AttributeType.Name == "MaybeNullAttribute" || attribute.AttributeType.Name == "MaybeNullWhenAttribute") && - nullability.ReadState == NullabilityState.NotNull && + codeAnalysisReadState == NullabilityState.Unknown && !nullability.Type.IsValueType) { - nullability.ReadState = NullabilityState.Nullable; - break; + codeAnalysisReadState = NullabilityState.Nullable; } - - if (attribute.AttributeType.Name == "DisallowNullAttribute" && - nullability.WriteState == NullabilityState.Nullable) + else if (attribute.AttributeType.Name == "DisallowNullAttribute") { - nullability.WriteState = NullabilityState.NotNull; - break; + codeAnalysisWriteState = NullabilityState.NotNull; } else if (attribute.AttributeType.Name == "AllowNullAttribute" && - nullability.WriteState == NullabilityState.NotNull && + codeAnalysisWriteState == NullabilityState.Unknown && !nullability.Type.IsValueType) { - nullability.WriteState = NullabilityState.Nullable; - break; + codeAnalysisWriteState = NullabilityState.Nullable; } } } + + if (codeAnalysisReadState != NullabilityState.Unknown) + { + nullability.ReadState = codeAnalysisReadState; + } + if (codeAnalysisWriteState != NullabilityState.Unknown) + { + nullability.WriteState = codeAnalysisWriteState; + } } /// @@ -184,17 +188,15 @@ public NullabilityInfo Create(PropertyInfo propertyInfo) EnsureIsSupported(); - NullabilityInfo nullability = GetNullabilityInfo(propertyInfo, propertyInfo.PropertyType, propertyInfo.GetCustomAttributesData()); MethodInfo? getter = propertyInfo.GetGetMethod(true); MethodInfo? setter = propertyInfo.GetSetMethod(true); + bool annotationsDisabled = (getter == null || IsPrivateOrInternalMethodAndAnnotationDisabled(getter)) + && (setter == null || IsPrivateOrInternalMethodAndAnnotationDisabled(setter)); + NullableAttributeStateParser parser = annotationsDisabled ? NullableAttributeStateParser.Unknown : CreateParser(propertyInfo.GetCustomAttributesData()); + NullabilityInfo nullability = GetNullabilityInfo(propertyInfo, propertyInfo.PropertyType, parser); if (getter != null) { - if (IsPrivateOrInternalMethodAndAnnotationDisabled(getter)) - { - nullability.ReadState = NullabilityState.Unknown; - } - CheckNullabilityAttributes(nullability, getter.ReturnParameter.GetCustomAttributesData()); } else @@ -204,12 +206,7 @@ public NullabilityInfo Create(PropertyInfo propertyInfo) if (setter != null) { - if (IsPrivateOrInternalMethodAndAnnotationDisabled(setter)) - { - nullability.WriteState = NullabilityState.Unknown; - } - - CheckNullabilityAttributes(nullability, setter.GetParameters()[0].GetCustomAttributesData()); + CheckNullabilityAttributes(nullability, setter.GetParameters()[^1].GetCustomAttributesData()); } else { @@ -219,7 +216,7 @@ public NullabilityInfo Create(PropertyInfo propertyInfo) return nullability; } - private bool IsPrivateOrInternalMethodAndAnnotationDisabled(MethodInfo method) + private bool IsPrivateOrInternalMethodAndAnnotationDisabled(MethodBase method) { if ((method.IsPrivate || method.IsFamilyAndAssembly || method.IsAssembly) && IsPublicOnly(method.IsPrivate, method.IsFamilyAndAssembly, method.IsAssembly, method.Module)) @@ -247,7 +244,7 @@ public NullabilityInfo Create(EventInfo eventInfo) EnsureIsSupported(); - return GetNullabilityInfo(eventInfo, eventInfo.EventHandlerType!, eventInfo.GetCustomAttributesData()); + return GetNullabilityInfo(eventInfo, eventInfo.EventHandlerType!, CreateParser(eventInfo.GetCustomAttributesData())); } /// @@ -267,13 +264,9 @@ public NullabilityInfo Create(FieldInfo fieldInfo) EnsureIsSupported(); - if (IsPrivateOrInternalFieldAndAnnotationDisabled(fieldInfo)) - { - return new NullabilityInfo(fieldInfo.FieldType, NullabilityState.Unknown, NullabilityState.Unknown, null, Array.Empty()); - } - IList attributes = fieldInfo.GetCustomAttributesData(); - NullabilityInfo nullability = GetNullabilityInfo(fieldInfo, fieldInfo.FieldType, attributes); + NullableAttributeStateParser parser = IsPrivateOrInternalFieldAndAnnotationDisabled(fieldInfo) ? NullableAttributeStateParser.Unknown : CreateParser(attributes); + NullabilityInfo nullability = GetNullabilityInfo(fieldInfo, fieldInfo.FieldType, parser); CheckNullabilityAttributes(nullability, attributes); return nullability; } @@ -341,10 +334,13 @@ private NotAnnotatedStatus PopulateAnnotationInfo(IList cus return NotAnnotatedStatus.None; } - private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, IList customAttributes) => - GetNullabilityInfo(memberInfo, type, customAttributes, 0); + private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser) + { + int index = 0; + return GetNullabilityInfo(memberInfo, type, parser, ref index); + } - private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, IList customAttributes, int index) + private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser, ref int index) { NullabilityState state = NullabilityState.Unknown; NullabilityInfo? elementState = null; @@ -364,17 +360,23 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi underlyingType = type; state = NullabilityState.NotNull; } + + if (underlyingType.IsGenericType) + { + ++index; + } } else { - if (!ParseNullableState(customAttributes, index, ref state)) + if (!parser.ParseNullableState(index++, ref state) + && GetNullableContext(memberInfo) is { } contextState) { - state = GetNullableContext(memberInfo); + state = contextState; } if (type.IsArray) { - elementState = GetNullabilityInfo(memberInfo, type.GetElementType()!, customAttributes, index + 1); + elementState = GetNullabilityInfo(memberInfo, type.GetElementType()!, parser, ref index); } } @@ -383,16 +385,9 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi Type[] genericArguments = underlyingType.GetGenericArguments(); genericArgumentsState = new NullabilityInfo[genericArguments.Length]; - for (int i = 0, offset = 0; i < genericArguments.Length; i++) + for (int i = 0; i < genericArguments.Length; i++) { - Type t = Nullable.GetUnderlyingType(genericArguments[i]) ?? genericArguments[i]; - - if (!t.IsValueType || t.IsGenericType) - { - offset++; - } - - genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], customAttributes, index + offset); + genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], parser, ref index); } } @@ -406,7 +401,7 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi return nullability; } - private static bool ParseNullableState(IList customAttributes, int index, ref NullabilityState state) + private static NullableAttributeStateParser CreateParser(IList customAttributes) { foreach (CustomAttributeData attribute in customAttributes) { @@ -414,26 +409,11 @@ private static bool ParseNullableState(IList customAttribut attribute.AttributeType.Namespace == CompilerServicesNameSpace && attribute.ConstructorArguments.Count == 1) { - object? o = attribute.ConstructorArguments[0].Value; - - if (o is byte b) - { - state = TranslateByte(b); - return true; - } - else if (o is ReadOnlyCollection args && - index < args.Count && - args[index].Value is byte elementB) - { - state = TranslateByte(elementB); - return true; - } - - break; + return new(attribute.ConstructorArguments[0].Value); } } - return false; + return new(null); } private void TryLoadGenericMetaTypeNullability(MemberInfo memberInfo, NullabilityInfo nullability) @@ -451,7 +431,7 @@ private void TryLoadGenericMetaTypeNullability(MemberInfo memberInfo, Nullabilit if (metaType != null) { - CheckGenericParameters(nullability, metaMember!, metaType); + CheckGenericParameters(nullability, metaMember!, metaType, memberInfo.ReflectedType); } } @@ -476,19 +456,14 @@ private static Type GetPropertyMetaType(PropertyInfo property) return property.GetSetMethod(true)!.GetParameters()[0].ParameterType; } - private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo metaMember, Type metaType) + private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo metaMember, Type metaType, Type? reflectedType) { if (metaType.IsGenericParameter) { - NullabilityState state = nullability.ReadState; - - if (state == NullabilityState.NotNull && !ParseNullableState(metaType.GetCustomAttributesData(), 0, ref state)) + if (nullability.ReadState == NullabilityState.NotNull) { - state = GetNullableContext(metaType); + TryUpdateGenericParameterNullability(nullability, metaType, reflectedType); } - - nullability.ReadState = state; - nullability.WriteState = state; } else if (metaType.ContainsGenericParameters) { @@ -498,35 +473,136 @@ private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo meta for (int i = 0; i < genericArguments.Length; i++) { - if (genericArguments[i].IsGenericParameter) - { - NullabilityInfo n = GetNullabilityInfo(metaMember, genericArguments[i], genericArguments[i].GetCustomAttributesData(), i + 1); - nullability.GenericTypeArguments[i].ReadState = n.ReadState; - nullability.GenericTypeArguments[i].WriteState = n.WriteState; - } - else - { - UpdateGenericArrayElements(nullability.GenericTypeArguments[i].ElementType, metaMember, genericArguments[i]); - } + CheckGenericParameters(nullability.GenericTypeArguments[i], metaMember, genericArguments[i], reflectedType); } } - else + else if (nullability.ElementType is { } elementNullability && metaType.IsArray) { - UpdateGenericArrayElements(nullability.ElementType, metaMember, metaType); + CheckGenericParameters(elementNullability, metaMember, metaType.GetElementType()!, reflectedType); } } } - private void UpdateGenericArrayElements(NullabilityInfo? elementState, MemberInfo metaMember, Type metaType) + private bool TryUpdateGenericParameterNullability(NullabilityInfo nullability, Type genericParameter, Type? reflectedType) { - if (metaType.IsArray && elementState != null - && metaType.GetElementType()!.IsGenericParameter) + Debug.Assert(genericParameter.IsGenericParameter); + + if (reflectedType is not null + && !genericParameter.IsGenericMethodParameter + && TryUpdateGenericTypeParameterNullabilityFromReflectedType(nullability, genericParameter, reflectedType, reflectedType)) + { + return true; + } + + var state = NullabilityState.Unknown; + if (CreateParser(genericParameter.GetCustomAttributesData()).ParseNullableState(0, ref state)) + { + nullability.ReadState = state; + nullability.WriteState = state; + return true; + } + + if (GetNullableContext(genericParameter) is { } contextState) { - Type elementType = metaType.GetElementType()!; - NullabilityInfo n = GetNullabilityInfo(metaMember, elementType, elementType.GetCustomAttributesData(), 0); - elementState.ReadState = n.ReadState; - elementState.WriteState = n.WriteState; + nullability.ReadState = contextState; + nullability.WriteState = contextState; + return true; } + + return false; + } + + private bool TryUpdateGenericTypeParameterNullabilityFromReflectedType(NullabilityInfo nullability, Type genericParameter, Type context, Type reflectedType) + { + Debug.Assert(genericParameter.IsGenericParameter && !genericParameter.IsGenericMethodParameter); + + Type contextTypeDefinition = context.IsGenericType && !context.IsGenericTypeDefinition ? context.GetGenericTypeDefinition() : context; + if (genericParameter.DeclaringType == contextTypeDefinition) + { + return false; + } + + Type? baseType = contextTypeDefinition.BaseType; + if (baseType is null) + { + return false; + } + + if (!baseType.IsGenericType + || (baseType.IsGenericTypeDefinition ? baseType : baseType.GetGenericTypeDefinition()) != genericParameter.DeclaringType) + { + return TryUpdateGenericTypeParameterNullabilityFromReflectedType(nullability, genericParameter, baseType, reflectedType); + } + + Type[] genericArguments = baseType.GetGenericArguments(); + Type genericArgument = genericArguments[genericParameter.GenericParameterPosition]; + if (genericArgument.IsGenericParameter) + { + return TryUpdateGenericParameterNullability(nullability, genericArgument, reflectedType); + } + + NullableAttributeStateParser parser = CreateParser(contextTypeDefinition.GetCustomAttributesData()); + int nullabilityStateIndex = 1; // start at 1 since index 0 is the type itself + for (int i = 0; i < genericParameter.GenericParameterPosition; i++) + { + nullabilityStateIndex += CountNullabilityStates(genericArguments[i]); + } + return TryPopulateNullabilityInfo(nullability, parser, ref nullabilityStateIndex); + + static int CountNullabilityStates(Type type) + { + Type underlyingType = Nullable.GetUnderlyingType(type) ?? type; + if (underlyingType.IsGenericType) + { + int count = 1; + foreach (Type genericArgument in underlyingType.GetGenericArguments()) + { + count += CountNullabilityStates(genericArgument); + } + return count; + } + if (underlyingType.IsArray) + { + return 1 + CountNullabilityStates(underlyingType.GetElementType()!); + } + + return type.IsValueType ? 0 : 1; + } + } + + private bool TryPopulateNullabilityInfo(NullabilityInfo nullability, NullableAttributeStateParser parser, ref int index) + { + bool isValueType = nullability.Type.IsValueType; + if (!isValueType) + { + var state = NullabilityState.Unknown; + if (!parser.ParseNullableState(index, ref state)) + { + return false; + } + + nullability.ReadState = state; + nullability.WriteState = state; + } + + if (!isValueType || (Nullable.GetUnderlyingType(nullability.Type) ?? nullability.Type).IsGenericType) + { + index++; + } + + if (nullability.GenericTypeArguments.Length > 0) + { + foreach (NullabilityInfo genericTypeArgumentNullability in nullability.GenericTypeArguments) + { + TryPopulateNullabilityInfo(genericTypeArgumentNullability, parser, ref index); + } + } + else if (nullability.ElementType is { } elementTypeNullability) + { + TryPopulateNullabilityInfo(elementTypeNullability, parser, ref index); + } + + return true; } private static NullabilityState TranslateByte(object? value) @@ -541,5 +617,35 @@ private static NullabilityState TranslateByte(byte b) => 2 => NullabilityState.Nullable, _ => NullabilityState.Unknown }; + + private readonly struct NullableAttributeStateParser + { + private static readonly object UnknownByte = (byte)0; + + private readonly object? _nullableAttributeArgument; + + public NullableAttributeStateParser(object? nullableAttributeArgument) + { + this._nullableAttributeArgument = nullableAttributeArgument; + } + + public static NullableAttributeStateParser Unknown => new(UnknownByte); + + public bool ParseNullableState(int index, ref NullabilityState state) + { + switch (this._nullableAttributeArgument) + { + case byte b: + state = TranslateByte(b); + return true; + case ReadOnlyCollection args + when index < args.Count && args[index].Value is byte elementB: + state = TranslateByte(elementB); + return true; + default: + return false; + } + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DisableRuntimeMarshallingAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DisableRuntimeMarshallingAttribute.cs new file mode 100644 index 0000000000000..6ed3018d2479e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DisableRuntimeMarshallingAttribute.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. + +namespace System.Runtime.CompilerServices +{ + /// + /// Disables the built-in runtime managed/unmanaged marshalling subsystem for + /// P/Invokes, Delegate types, and unmanaged function pointer invocations. + /// + /// + /// The built-in marshalling subsystem has some behaviors that cannot be changed due to + /// backward-compatibility requirements. This attribute allows disabling the built-in + /// subsystem and instead uses the following rules for P/Invokes, Delegates, + /// and unmanaged function pointer invocations: + /// + /// - All value types that do not contain reference type fields recursively (unmanaged in C#) are blittable + /// - Value types that recursively have any fields that have [StructLayout(LayoutKind.Auto)] are disallowed from interop. + /// - All reference types are disallowed from usage in interop scenarios. + /// - SetLastError support in P/Invokes is disabled. + /// - varargs support is disabled. + /// - LCIDConversionAttribute support is disabled. + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + public sealed class DisableRuntimeMarshallingAttribute : Attribute + { + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs new file mode 100644 index 0000000000000..4a17cfc290b2a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.CompilerServices +{ + /// Specifies that a type has required members or that a member is required. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class RequiredMemberAttribute : Attribute + { } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs index a94a0e19d0176..9e0a5ed29e42e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs @@ -27,6 +27,11 @@ public static partial class RuntimeFeature /// public const string CovariantReturnsOfClasses = nameof(CovariantReturnsOfClasses); + /// + /// Represents a runtime feature where types can define ref fields. + /// + public const string ByRefFields = nameof(ByRefFields); + /// /// Indicates that this version of runtime supports virtual static members of interfaces. /// @@ -42,6 +47,7 @@ public static bool IsSupported(string feature) { case PortablePdb: case CovariantReturnsOfClasses: + case ByRefFields: case UnmanagedSignatureCallingConvention: case DefaultImplementationsOfInterfaces: #pragma warning disable CA2252 diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index 8187320ec9768..498055ad6a1c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -117,5 +117,15 @@ internal static bool IsPrimitiveType(this CorElementType et) /// This method is intended for compiler use rather than use directly in code. T must be one of byte, sbyte, char, short, ushort, int, long, ulong, float, or double. [Intrinsic] public static unsafe ReadOnlySpan CreateSpan(RuntimeFieldHandle fldHandle) => new ReadOnlySpan(GetSpanDataFrom(fldHandle, typeof(T).TypeHandle, out int length), length); + + + // The following intrinsics return true if input is a compile-time constant + // Feel free to add more overloads on demand + + [Intrinsic] + internal static bool IsKnownConstant(string? t) => false; + + [Intrinsic] + internal static bool IsKnownConstant(char t) => false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Architecture.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Architecture.cs index 225fec28c763a..4dead88ce4c92 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Architecture.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Architecture.cs @@ -11,6 +11,7 @@ public enum Architecture Arm64, Wasm, S390x, - LoongArch64 + LoongArch64, + Armv6, } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs index 8a80faa9977b6..92d42d6795567 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -6,7 +6,7 @@ namespace System.Runtime.InteropServices { - public readonly struct ArrayWithOffset + public readonly struct ArrayWithOffset : IEquatable { private readonly object? m_array; private readonly int m_offset; @@ -52,7 +52,7 @@ public ArrayWithOffset(object? array, int offset) public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is ArrayWithOffset && Equals((ArrayWithOffset)obj); + return obj is ArrayWithOffset awo && Equals(awo); } public bool Equals(ArrayWithOffset obj) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs index 579633db55caf..a1c849b48c71b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs @@ -23,7 +23,7 @@ namespace System.Runtime.InteropServices /// Pinned - same as Normal, but allows the address of the actual object to be taken. /// [StructLayout(LayoutKind.Sequential)] - public partial struct GCHandle + public partial struct GCHandle : IEquatable { // The actual integer handle value that the EE uses internally. private IntPtr _handle; @@ -163,7 +163,12 @@ public static GCHandle FromIntPtr(IntPtr value) public override int GetHashCode() => _handle.GetHashCode(); - public override bool Equals([NotNullWhen(true)] object? o) => o is GCHandle && _handle == ((GCHandle)o)._handle; + public override bool Equals([NotNullWhen(true)] object? o) => o is GCHandle other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(GCHandle other) => _handle == other._handle; public static bool operator ==(GCHandle a, GCHandle b) => (nint)a._handle == (nint)b._handle; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index e3cb842f2a529..62d9a8d30e1a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -2,7 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // We use our own aliases since they differ per platform #if TARGET_32BIT @@ -13,65 +17,691 @@ namespace System.Runtime.InteropServices { - /// - /// is an immutable value type that represents a floating type that has the same size - /// as the native integer size. - /// It is meant to be used as an exchange type at the managed/unmanaged boundary to accurately represent - /// in managed code unmanaged APIs that use a type alias for C or C++'s float on 32-bit platforms - /// or double on 64-bit platforms, such as the CGFloat type in libraries provided by Apple. - /// + /// Defines an immutable value type that represents a floating type that has the same size as the native integer size. + /// It is meant to be used as an exchange type at the managed/unmanaged boundary to accurately represent in managed code unmanaged APIs that use a type alias for C or C++'s float on 32-bit platforms or double on 64-bit platforms, such as the CGFloat type in libraries provided by Apple. [Intrinsic] - public readonly struct NFloat : IEquatable + public readonly struct NFloat + : IComparable, + IComparable, + IEquatable, + ISpanFormattable { + private const NumberStyles DefaultNumberStyles = NumberStyles.Float | NumberStyles.AllowThousands; + private readonly NativeType _value; - /// - /// Constructs an instance from a 32-bit floating point value. - /// - /// The floating-point vaule. + /// Constructs an instance from a 32-bit floating point value. + /// The floating-point value. + [NonVersionable] public NFloat(float value) { _value = value; } - /// - /// Constructs an instance from a 64-bit floating point value. - /// - /// The floating-point vaule. + /// Constructs an instance from a 64-bit floating point value. + /// The floating-point value. + [NonVersionable] public NFloat(double value) { _value = (NativeType)value; } - /// - /// The underlying floating-point value of this instance. - /// - public double Value => _value; + /// Represents the smallest positive NFloat value that is greater than zero. + public static NFloat Epsilon + { + [NonVersionable] + get => new NFloat(NativeType.Epsilon); + } + + /// Represents the largest finite value of a NFloat. + public static NFloat MaxValue + { + [NonVersionable] + get => new NFloat(NativeType.MaxValue); + } + + /// Represents the smallest finite value of a NFloat. + public static NFloat MinValue + { + [NonVersionable] + get => new NFloat(NativeType.MinValue); + } + + /// Represents a value that is not a number (NaN). + public static NFloat NaN + { + [NonVersionable] + get => new NFloat(NativeType.NaN); + } + + /// Represents negative infinity. + public static NFloat NegativeInfinity + { + [NonVersionable] + get => new NFloat(NativeType.NegativeInfinity); + } + + /// Represents positive infinity. + public static NFloat PositiveInfinity + { + [NonVersionable] + get => new NFloat(NativeType.PositiveInfinity); + } + + /// Gets the size, in bytes, of an NFloat. + public static int Size + { + [NonVersionable] + get => sizeof(NativeType); + } + + /// The underlying floating-point value of this instance. + public double Value + { + [NonVersionable] + get => _value; + } + + // + // Unary Arithmetic + // + + /// Computes the unary plus of a value. + /// The value for which to compute its unary plus. + /// The unary plus of . + [NonVersionable] + public static NFloat operator +(NFloat value) => value; + + /// Computes the unary negation of a value. + /// The value for which to compute its unary negation. + /// The unary negation of . + [NonVersionable] + public static NFloat operator -(NFloat value) => new NFloat(-value._value); + + /// Increments a value. + /// The value to increment. + /// The result of incrementing . + [NonVersionable] + public static NFloat operator ++(NFloat value) => new NFloat(value._value + 1); + + /// Decrements a value. + /// The value to decrement. + /// The result of decrementing . + [NonVersionable] + public static NFloat operator --(NFloat value) => new NFloat(value._value - 1); + + // + // Binary Arithmetic + // + + /// Adds two values together to compute their sum. + /// The value to which is added. + /// The value which is added to . + /// The sum of and . + [NonVersionable] + public static NFloat operator +(NFloat left, NFloat right) => new NFloat(left._value + right._value); + + /// Subtracts two values to compute their difference. + /// The value from which is subtracted. + /// The value which is subtracted from . + /// The difference of subtracted from . + [NonVersionable] + public static NFloat operator -(NFloat left, NFloat right) => new NFloat(left._value - right._value); + + /// Multiplies two values together to compute their product. + /// The value which multiplies. + /// The value which multiplies . + /// The product of divided-by . + [NonVersionable] + public static NFloat operator *(NFloat left, NFloat right) => new NFloat(left._value * right._value); + + /// Divides two values together to compute their quotient. + /// The value which divides. + /// The value which divides . + /// The quotient of divided-by . + [NonVersionable] + public static NFloat operator /(NFloat left, NFloat right) => new NFloat(left._value / right._value); + + /// Divides two values together to compute their remainder. + /// The value which divides. + /// The value which divides . + /// The remainder of divided-by . + [NonVersionable] + public static NFloat operator %(NFloat left, NFloat right) => new NFloat(left._value % right._value); + + // + // Comparisons + // + + /// Compares two values to determine equality. + /// The value to compare with . + /// The value to compare with . + /// true if is equal to ; otherwise, false. + [NonVersionable] + public static bool operator ==(NFloat left, NFloat right) => left._value == right._value; + + /// Compares two values to determine inequality. + /// The value to compare with . + /// The value to compare with . + /// true if is not equal to ; otherwise, false. + [NonVersionable] + public static bool operator !=(NFloat left, NFloat right) => left._value != right._value; + + /// Compares two values to determine which is less. + /// The value to compare with . + /// The value to compare with . + /// true if is less than ; otherwise, false. + [NonVersionable] + public static bool operator <(NFloat left, NFloat right) => left._value < right._value; + + /// Compares two values to determine which is less or equal. + /// The value to compare with . + /// The value to compare with . + /// true if is less than or equal to ; otherwise, false. + [NonVersionable] + public static bool operator <=(NFloat left, NFloat right) => left._value <= right._value; + + /// Compares two values to determine which is greater. + /// The value to compare with . + /// The value to compare with . + /// true if is greater than ; otherwise, false. + [NonVersionable] + public static bool operator >(NFloat left, NFloat right) => left._value > right._value; + + /// Compares two values to determine which is greater or equal. + /// The value to compare with . + /// The value to compare with . + /// true if is greater than or equal to ; otherwise, false. + [NonVersionable] + public static bool operator >=(NFloat left, NFloat right) => left._value >= right._value; + + // + // Explicit Convert To NFloat + // + + /// Explicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static explicit operator NFloat(decimal value) => new NFloat((NativeType)value); + + /// Explicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static explicit operator NFloat(double value) => new NFloat((NativeType)value); + + // + // Explicit Convert From NFloat + // + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator byte(NFloat value) => (byte)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator char(NFloat value) => (char)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator decimal(NFloat value) => (decimal)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator short(NFloat value) => (short)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator int(NFloat value) => (int)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator long(NFloat value) => (long)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator nint(NFloat value) => (nint)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator sbyte(NFloat value) => (sbyte)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator float(NFloat value) => (float)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator ushort(NFloat value) => (ushort)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator uint(NFloat value) => (uint)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator ulong(NFloat value) => (ulong)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator nuint(NFloat value) => (nuint)(value._value); + + // + // Implicit Convert To NFloat + // - /// - /// Returns a value indicating whether this instance is equal to a specified object. - /// - /// An object to compare with this instance. - /// true if is an instance of and equals the value of this instance; otherwise, false. - public override bool Equals([NotNullWhen(true)] object? o) => o is NFloat other && Equals(other); + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(byte value) => new NFloat((NativeType)value); - /// - /// Returns a value indicating whether this instance is equal to a specified value. - /// + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(char value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(short value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(int value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(long value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(nint value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(sbyte value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(float value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(ushort value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(uint value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(ulong value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(nuint value) => new NFloat((NativeType)value); + + // + // Implicit Convert From NFloat + // + + /// Implicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + public static implicit operator double(NFloat value) => (double)(value._value); + + /// Determines whether the specified value is finite (zero, subnormal, or normal). + /// The floating-point value. + /// true if the value is finite (zero, subnormal or normal); false otherwise. + [NonVersionable] + public static bool IsFinite(NFloat value) => NativeType.IsFinite(value._value); + + /// Determines whether the specified value is infinite (positive or negative infinity). + /// The floating-point value. + /// true if the value is infinite (positive or negative infinity); false otherwise. + [NonVersionable] + public static bool IsInfinity(NFloat value) => NativeType.IsInfinity(value._value); + + /// Determines whether the specified value is NaN (not a number). + /// The floating-point value. + /// true if the value is NaN (not a number); false otherwise. + [NonVersionable] + public static bool IsNaN(NFloat value) => NativeType.IsNaN(value._value); + + /// Determines whether the specified value is negative. + /// The floating-point value. + /// true if the value is negative; false otherwise. + [NonVersionable] + public static bool IsNegative(NFloat value) => NativeType.IsNegative(value._value); + + /// Determines whether the specified value is negative infinity. + /// The floating-point value. + /// true if the value is negative infinity; false otherwise. + [NonVersionable] + public static bool IsNegativeInfinity(NFloat value) => NativeType.IsNegativeInfinity(value._value); + + /// Determines whether the specified value is normal. + /// The floating-point value. + /// true if the value is normal; false otherwise. + [NonVersionable] + public static bool IsNormal(NFloat value) => NativeType.IsNormal(value._value); + + /// Determines whether the specified value is positive infinity. + /// The floating-point value. + /// true if the value is positive infinity; false otherwise. + [NonVersionable] + public static bool IsPositiveInfinity(NFloat value) => NativeType.IsPositiveInfinity(value._value); + + /// Determines whether the specified value is subnormal. + /// The floating-point value. + /// true if the value is subnormal; false otherwise. + [NonVersionable] + public static bool IsSubnormal(NFloat value) => NativeType.IsSubnormal(value._value); + + /// Converts the string representation of a number to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s) + { + var result = NativeType.Parse(s); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified style to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, NumberStyles style) + { + var result = NativeType.Parse(s, style); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified culture-specific format to its floating-point number equivalent. + /// A string that contains the number to convert. + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, IFormatProvider? provider) + { + var result = NativeType.Parse(s, provider); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, NumberStyles style, IFormatProvider? provider) + { + var result = NativeType.Parse(s, style, provider); + return new NFloat(result); + } + + /// Converts a character span that contains the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// does not represent a number in a valid format. + public static NFloat Parse(ReadOnlySpan s, NumberStyles style = DefaultNumberStyles, IFormatProvider? provider = null) + { + var result = NativeType.Parse(s, style, provider); + return new NFloat(result); + } + + /// Tries to convert the string representation of a number to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is null, , or is not in a valid format. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + public static bool TryParse([NotNullWhen(true)] string? s, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, out Unsafe.As(ref result)); + } + + /// Tries to convert a character span containing the string representation of a number to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is or is not in a valid format. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan s, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, out Unsafe.As(ref result)); + } + + /// Tries to convert the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is null, , or is not in a format compliant with , or if is not a valid combination of enumeration constants. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + /// + /// is not a value. + /// -or- + /// includes the value. + /// + public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, style, provider, out Unsafe.As(ref result)); + } + + /// Tries to convert a character span containing the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is or is not in a format compliant with , or if is not a valid combination of enumeration constants. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + /// + /// is not a value. + /// -or- + /// includes the value. + /// + public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, style, provider, out Unsafe.As(ref result)); + } + + /// Compares this instance to a specified object and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. + /// An object to compare, or null. + /// + /// A signed number indicating the relative values of this instance and . + /// + /// + /// Return Value + /// Description + /// + /// + /// Less than zero + /// This instance is less than , or this instance is not a number and is a number. + /// + /// + /// Zero + /// This instance is equal to , or both this instance and are not a number. + /// + /// + /// Greater than zero + /// This instance is greater than , or this instance is a number and is not a number or is null. + /// + /// + /// + /// is not a . + public int CompareTo(object? obj) + { + if (obj is NFloat other) + { + if (_value < other._value) return -1; + if (_value > other._value) return 1; + if (_value == other._value) return 0; + + // At least one of the values is NaN. + if (NativeType.IsNaN(_value)) + { + return NativeType.IsNaN(other._value) ? 0 : -1; + } + else + { + return 1; + } + } + else if (obj is null) + { + return 1; + } + + throw new ArgumentException(SR.Arg_MustBeNFloat); + } + + /// Compares this instance to a specified floating-point number and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified floating-point number. + /// A floating-point number to compare. + /// + /// A signed number indicating the relative values of this instance and . + /// + /// + /// Return Value + /// Description + /// + /// + /// Less than zero + /// This instance is less than , or this instance is not a number and is a number. + /// + /// + /// Zero + /// This instance is equal to , or both this instance and are not a number. + /// + /// + /// Greater than zero + /// This instance is greater than , or this instance is a number and is not a number. + /// + /// + /// + public int CompareTo(NFloat other) => _value.CompareTo(other._value); + + /// Returns a value indicating whether this instance is equal to a specified object. + /// An object to compare with this instance. + /// true if is an instance of and equals the value of this instance; otherwise, false. + public override bool Equals([NotNullWhen(true)] object? obj) => (obj is NFloat other) && Equals(other); + + /// Returns a value indicating whether this instance is equal to a specified value. /// An value to compare to this instance. /// true if has the same value as this instance; otherwise, false. public bool Equals(NFloat other) => _value.Equals(other._value); - /// - /// Returns the hash code for this instance. - /// + /// Returns the hash code for this instance. /// A 32-bit signed integer hash code. public override int GetHashCode() => _value.GetHashCode(); - /// - /// Converts the numeric value of this instance to its equivalent string representation. - /// + /// Converts the numeric value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public override string ToString() => _value.ToString(); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified format. + /// A numeric format string. + /// The string representation of the value of this instance as specified by . + /// is invalid. + public string ToString(string? format) => _value.ToString(format); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified culture-specific format information. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by . + public string ToString(IFormatProvider? provider)=> _value.ToString(provider); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information. + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by and . + /// is invalid. + public string ToString(string? format, IFormatProvider? provider) => _value.ToString(format, provider); + + /// Tries to format the value of the current instance into the provided span of characters. + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// true if the formatting was successful; otherwise, false. + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) => _value.TryFormat(destination, out charsWritten, format, provider); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/OSPlatform.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/OSPlatform.cs index cf6c8af7a28ac..09265f93c643f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/OSPlatform.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/OSPlatform.cs @@ -19,9 +19,7 @@ namespace System.Runtime.InteropServices private OSPlatform(string osPlatform) { - if (osPlatform == null) throw new ArgumentNullException(nameof(osPlatform)); - if (osPlatform.Length == 0) throw new ArgumentException(SR.Argument_EmptyString, nameof(osPlatform)); - + ArgumentException.ThrowIfNullOrEmpty(osPlatform); Name = osPlatform; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.ProcessArchitecture.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.ProcessArchitecture.cs index 0da595b95e074..d11391a001ef9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.ProcessArchitecture.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.ProcessArchitecture.cs @@ -10,6 +10,8 @@ public static Architecture ProcessArchitecture => Architecture.X86; #elif TARGET_AMD64 => Architecture.X64; +#elif TARGET_ARMV6 + => Architecture.Armv6; #elif TARGET_ARM => Architecture.Arm; #elif TARGET_ARM64 diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 6d82ccc8aad53..9dba4bcf29c18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -2389,11 +2389,12 @@ public static T Dot(Vector256 left, Vector256 right) { T result = default; - for (int index = 0; index < Vector256.Count; index++) - { - T value = Scalar.Multiply(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); - result = Scalar.Add(result, value); - } + // Doing this as Dot(lower) + Dot(upper) is important for floating-point determinism + // This is because the underlying dpps instruction on x86/x64 will do this equivalently + // and otherwise the software vs accelerated implementations may differ in returned result. + + result = Scalar.Add(result, Vector128.Dot(left.GetLower(), right.GetLower())); + result = Scalar.Add(result, Vector128.Dot(left.GetUpper(), right.GetUpper())); return result; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 289bb93be4b1e..c6b3478cf9bb6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -422,15 +422,7 @@ public Assembly LoadFromStream(Stream assembly, Stream? assemblySymbols) // platform-independent way. The DLL is loaded with default load flags. protected IntPtr LoadUnmanagedDllFromPath(string unmanagedDllPath) { - if (unmanagedDllPath == null) - { - throw new ArgumentNullException(nameof(unmanagedDllPath)); - } - - if (unmanagedDllPath.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyPath, nameof(unmanagedDllPath)); - } + ArgumentException.ThrowIfNullOrEmpty(unmanagedDllPath); if (PathInternal.IsPartiallyQualified(unmanagedDllPath)) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs index 3501457fa82d1..1b3b86c0b9a64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs @@ -3,6 +3,8 @@ using System.Diagnostics.CodeAnalysis; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System.Runtime.Serialization { public readonly struct StreamingContext diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs index c96729d8af4c8..5c492e7657ff1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs @@ -96,20 +96,9 @@ public FrameworkName(string identifier, Version version) public FrameworkName(string identifier, Version version, string? profile) { - if (identifier == null) - { - throw new ArgumentNullException(nameof(identifier)); - } - - identifier = identifier.Trim(); - if (identifier.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyString, nameof(identifier)); - } - if (version == null) - { - throw new ArgumentNullException(nameof(version)); - } + identifier = identifier?.Trim()!; + ArgumentException.ThrowIfNullOrEmpty(identifier); + ArgumentNullException.ThrowIfNull(version); _identifier = identifier; _version = version; @@ -122,14 +111,7 @@ public FrameworkName(string identifier, Version version, string? profile) // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed public FrameworkName(string frameworkName) { - if (frameworkName == null) - { - throw new ArgumentNullException(nameof(frameworkName)); - } - if (frameworkName.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyString, nameof(frameworkName)); - } + ArgumentException.ThrowIfNullOrEmpty(frameworkName); string[] components = frameworkName.Split(ComponentSeparator); diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index 9703d8016eadb..f48c702651fec 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -18,9 +18,6 @@ public sealed class SecurityElement private const int AttributesTypical = 4 * 2; // 4 attributes, times 2 strings per attribute private const int ChildrenTypical = 1; - private static readonly char[] s_tagIllegalCharacters = new char[] { ' ', '<', '>' }; - private static readonly char[] s_textIllegalCharacters = new char[] { '<', '>' }; - private static readonly char[] s_valueIllegalCharacters = new char[] { '<', '>', '\"' }; private static readonly char[] s_escapeChars = new char[] { '<', '>', '\"', '\'', '&' }; private static readonly string[] s_escapeStringPairs = new string[] { @@ -298,34 +295,17 @@ public SecurityElement Copy() return element; } - public static bool IsValidTag([NotNullWhen(true)] string? tag) - { - if (tag == null) - return false; - - return tag.IndexOfAny(s_tagIllegalCharacters) < 0; - } - - public static bool IsValidText([NotNullWhen(true)] string? text) - { - if (text == null) - return false; + public static bool IsValidTag([NotNullWhen(true)] string? tag) => + tag != null && tag.AsSpan().IndexOfAny(' ', '<', '>') < 0; - return text.IndexOfAny(s_textIllegalCharacters) < 0; - } - - public static bool IsValidAttributeName([NotNullWhen(true)] string? name) - { - return IsValidTag(name); - } + public static bool IsValidText([NotNullWhen(true)] string? text) => + text != null && text.AsSpan().IndexOfAny('<', '>') < 0; - public static bool IsValidAttributeValue([NotNullWhen(true)] string? value) - { - if (value == null) - return false; + public static bool IsValidAttributeName([NotNullWhen(true)] string? name) => + IsValidTag(name); - return value.IndexOfAny(s_valueIllegalCharacters) < 0; - } + public static bool IsValidAttributeValue([NotNullWhen(true)] string? value) => + value != null && value.AsSpan().IndexOfAny('<', '>', '\"') < 0; private static string GetEscapeSequence(char c) { diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs index e94b1dfe672b2..ddab1018c7ad4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs @@ -22,12 +22,21 @@ public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - byte valueHead = value; - ref byte valueTail = ref Unsafe.Add(ref value, 1); int valueTailLength = valueLength - 1; - int remainingSearchSpaceLength = searchSpaceLength - valueTailLength; + if (valueTailLength == 0) + return IndexOf(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain IndexOf int offset = 0; + byte valueHead = value; + int searchSpaceMinusValueTailLength = searchSpaceLength - valueTailLength; + if (Vector128.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector128.Count) + { + goto SEARCH_TWO_BYTES; + } + + ref byte valueTail = ref Unsafe.Add(ref value, 1); + int remainingSearchSpaceLength = searchSpaceMinusValueTailLength; + while (remainingSearchSpaceLength > 0) { // Do a quick search for the first element of "value". @@ -42,13 +51,264 @@ public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. // Found the first element of "value". See if the tail matches. - if (SequenceEqual(ref Unsafe.Add(ref searchSpace, offset + 1), ref valueTail, (nuint)valueTailLength)) // The (nuint)-cast is necessary to pick the correct overload + if (SequenceEqual( + ref Unsafe.Add(ref searchSpace, offset + 1), + ref valueTail, (nuint)(uint)valueTailLength)) // The (nuint)-cast is necessary to pick the correct overload return offset; // The tail matched. Return a successful find. remainingSearchSpaceLength--; offset++; } return -1; + + // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła + // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 + SEARCH_TWO_BYTES: + if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength - Vector256.Count >= 0) + { + // Find the last unique (which is not equal to ch1) byte + // the algorithm is fine if both are equal, just a little bit less efficient + byte ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == value && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector256 ch1 = Vector256.Create(value); + Vector256 ch2 = Vector256.Create(ch2Val); + + do + { + Debug.Assert(offset >= 0); + // Make sure we don't go out of bounds + Debug.Assert(offset + ch1ch2Distance + Vector256.Count <= searchSpaceLength); + + Vector256 cmpCh1 = Vector256.Equals(ch1, Vector256.LoadUnsafe(ref searchSpace, (nuint)offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector256.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + int bitPos = BitOperations.TrailingZeroCount(mask); + if (valueLength == 2 || // we already matched two bytes + SequenceEqual( + ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload + { + return offset + bitPos; + } + mask = BitOperations.ResetLowestSetBit(mask); // Clear the lowest set bit + } while (mask != 0); + } + offset += Vector256.Count; + + if (offset == searchSpaceMinusValueTailLength) + return -1; + + // Overlap with the current chunk for trailing elements + if (offset > searchSpaceMinusValueTailLength - Vector256.Count) + offset = searchSpaceMinusValueTailLength - Vector256.Count; + } while (true); + } + else // 128bit vector path (SSE2 or AdvSimd) + { + // Find the last unique (which is not equal to ch1) byte + // the algorithm is fine if both are equal, just a little bit less efficient + byte ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == value && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector128 ch1 = Vector128.Create(value); + Vector128 ch2 = Vector128.Create(ch2Val); + + do + { + Debug.Assert(offset >= 0); + // Make sure we don't go out of bounds + Debug.Assert(offset + ch1ch2Distance + Vector128.Count <= searchSpaceLength); + + Vector128 cmpCh1 = Vector128.Equals(ch1, Vector128.LoadUnsafe(ref searchSpace, (nuint)offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector128.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + int bitPos = BitOperations.TrailingZeroCount(mask); + if (valueLength == 2 || // we already matched two bytes + SequenceEqual( + ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload + { + return offset + bitPos; + } + // Clear the lowest set bit + mask = BitOperations.ResetLowestSetBit(mask); + } while (mask != 0); + } + offset += Vector128.Count; + + if (offset == searchSpaceMinusValueTailLength) + return -1; + + // Overlap with the current chunk for trailing elements + if (offset > searchSpaceMinusValueTailLength - Vector128.Count) + offset = searchSpaceMinusValueTailLength - Vector128.Count; + } while (true); + } + } + + public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) + { + Debug.Assert(searchSpaceLength >= 0); + Debug.Assert(valueLength >= 0); + + if (valueLength == 0) + return searchSpaceLength; // A zero-length sequence is always treated as "found" at the end of the search space. + + int valueTailLength = valueLength - 1; + if (valueTailLength == 0) + return LastIndexOf(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain LastIndexOf + + int offset = 0; + byte valueHead = value; + int searchSpaceMinusValueTailLength = searchSpaceLength - valueTailLength; + if (Vector128.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector128.Count) + { + goto SEARCH_TWO_BYTES; + } + + ref byte valueTail = ref Unsafe.Add(ref value, 1); + + while (true) + { + Debug.Assert(0 <= offset && offset <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength". + int remainingSearchSpaceLength = searchSpaceLength - offset - valueTailLength; + if (remainingSearchSpaceLength <= 0) + break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. + + // Do a quick search for the first element of "value". + int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength); + if (relativeIndex < 0) + break; + + // Found the first element of "value". See if the tail matches. + if (SequenceEqual( + ref Unsafe.Add(ref searchSpace, relativeIndex + 1), + ref valueTail, (nuint)(uint)valueTailLength)) // The (nuint)-cast is necessary to pick the correct overload + return relativeIndex; // The tail matched. Return a successful find. + + offset += remainingSearchSpaceLength - relativeIndex; + } + return -1; + + // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła + // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 + SEARCH_TWO_BYTES: + if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector256.Count) + { + offset = searchSpaceMinusValueTailLength - Vector256.Count; + + // Find the last unique (which is not equal to ch1) byte + // the algorithm is fine if both are equal, just a little bit less efficient + byte ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == value && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector256 ch1 = Vector256.Create(value); + Vector256 ch2 = Vector256.Create(ch2Val); + do + { + Vector256 cmpCh1 = Vector256.Equals(ch1, Vector256.LoadUnsafe(ref searchSpace, (nuint)offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector256.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + // unlike IndexOf, here we use LZCNT to process matches starting from the end + int bitPos = 31 - BitOperations.LeadingZeroCount(mask); + if (valueLength == 2 || // we already matched two bytes + SequenceEqual( + ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload + { + return bitPos + offset; + } + // Clear the highest set bit. + mask = BitOperations.ResetBit(mask, bitPos); + } while (mask != 0); + } + + offset -= Vector256.Count; + if (offset == -Vector256.Count) + return -1; + // Overlap with the current chunk if there is not enough room for the next one + if (offset < 0) + offset = 0; + } while (true); + } + else // 128bit vector path (SSE2 or AdvSimd) + { + offset = searchSpaceMinusValueTailLength - Vector128.Count; + + // Find the last unique (which is not equal to ch1) byte + // the algorithm is fine if both are equal, just a little bit less efficient + byte ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == value && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector128 ch1 = Vector128.Create(value); + Vector128 ch2 = Vector128.Create(ch2Val); + + do + { + Vector128 cmpCh1 = Vector128.Equals(ch1, Vector128.LoadUnsafe(ref searchSpace, (nuint)offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + // it's especially important for ARM where ExtractMostSignificantBits is not cheap + if (cmpAnd != Vector128.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + // unlike IndexOf, here we use LZCNT to process matches starting from the end + int bitPos = 31 - BitOperations.LeadingZeroCount(mask); + if (valueLength == 2 || // we already matched two bytes + SequenceEqual( + ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload + { + return bitPos + offset; + } + // Clear the highest set bit. + mask = BitOperations.ResetBit(mask, bitPos); + } while (mask != 0); + } + + offset -= Vector128.Count; + if (offset == -Vector128.Count) + return -1; + // Overlap with the current chunk if there is not enough room for the next one + if (offset < 0) + offset = 0; + + } while (true); + } } // Adapted from IndexOf(...) @@ -408,40 +668,6 @@ public static unsafe int IndexOf(ref byte searchSpace, byte value, int length) return (int)(offset + 7); } - public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) - { - Debug.Assert(searchSpaceLength >= 0); - Debug.Assert(valueLength >= 0); - - if (valueLength == 0) - return searchSpaceLength; // A zero-length sequence is always treated as "found" at the end of the search space. - - byte valueHead = value; - ref byte valueTail = ref Unsafe.Add(ref value, 1); - int valueTailLength = valueLength - 1; - - int offset = 0; - while (true) - { - Debug.Assert(0 <= offset && offset <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength". - int remainingSearchSpaceLength = searchSpaceLength - offset - valueTailLength; - if (remainingSearchSpaceLength <= 0) - break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. - - // Do a quick search for the first element of "value". - int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength); - if (relativeIndex < 0) - break; - - // Found the first element of "value". See if the tail matches. - if (SequenceEqual(ref Unsafe.Add(ref searchSpace, relativeIndex + 1), ref valueTail, (nuint)(uint)valueTailLength)) // The (nunit)-cast is necessary to pick the correct overload - return relativeIndex; // The tail matched. Return a successful find. - - offset += remainingSearchSpaceLength - relativeIndex; - } - return -1; - } - [MethodImpl(MethodImplOptions.AggressiveOptimization)] public static int LastIndexOf(ref byte searchSpace, byte value, int length) { @@ -1564,13 +1790,11 @@ public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint l // This becomes a conditional jmp foward to not favor it. goto NotEqual; } - // Use Vector128.Size as Vector128.Count doesn't inline at R2R time - // https://github.com/dotnet/runtime/issues/32714 - else if (length >= Vector128.Size) + else if (length >= (nuint)Vector128.Count) { Vector128 vecResult; nuint offset = 0; - nuint lengthToExamine = length - Vector128.Size; + nuint lengthToExamine = length - (nuint)Vector128.Count; // Unsigned, so it shouldn't have overflowed larger than length (rather than negative) Debug.Assert(lengthToExamine < length); if (lengthToExamine != 0) @@ -1584,7 +1808,7 @@ public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint l { goto NotEqual; } - offset += Vector128.Size; + offset += (nuint)Vector128.Count; } while (lengthToExamine > offset); } diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs index 753e5301b503b..c8331dc152336 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs @@ -22,38 +22,315 @@ public static int IndexOf(ref char searchSpace, int searchSpaceLength, ref char if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - char valueHead = value; - ref char valueTail = ref Unsafe.Add(ref value, 1); int valueTailLength = valueLength - 1; - int remainingSearchSpaceLength = searchSpaceLength - valueTailLength; + if (valueTailLength == 0) + { + // for single-char values use plain IndexOf + return IndexOf(ref searchSpace, value, searchSpaceLength); + } + + int offset = 0; + char valueHead = value; + int searchSpaceMinusValueTailLength = searchSpaceLength - valueTailLength; + if (Vector128.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector128.Count) + { + goto SEARCH_TWO_CHARS; + } + + ref byte valueTail = ref Unsafe.As(ref Unsafe.Add(ref value, 1)); + int remainingSearchSpaceLength = searchSpaceMinusValueTailLength; - int index = 0; while (remainingSearchSpaceLength > 0) { // Do a quick search for the first element of "value". - int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, index), valueHead, remainingSearchSpaceLength); + int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueHead, remainingSearchSpaceLength); if (relativeIndex < 0) break; remainingSearchSpaceLength -= relativeIndex; - index += relativeIndex; + offset += relativeIndex; if (remainingSearchSpaceLength <= 0) break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. // Found the first element of "value". See if the tail matches. if (SequenceEqual( - ref Unsafe.As(ref Unsafe.Add(ref searchSpace, index + 1)), - ref Unsafe.As(ref valueTail), - (nuint)(uint)valueTailLength * 2)) + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + 1)), + ref valueTail, + (nuint)(uint)valueTailLength * 2)) { - return index; // The tail matched. Return a successful find. + return offset; // The tail matched. Return a successful find. } remainingSearchSpaceLength--; - index++; + offset++; } return -1; + + // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła + // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 + SEARCH_TWO_CHARS: + if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength - Vector256.Count >= 0) + { + // Find the last unique (which is not equal to ch1) character + // the algorithm is fine if both are equal, just a little bit less efficient + ushort ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == valueHead && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector256 ch1 = Vector256.Create((ushort)valueHead); + Vector256 ch2 = Vector256.Create(ch2Val); + + do + { + // Make sure we don't go out of bounds + Debug.Assert(offset + ch1ch2Distance + Vector256.Count <= searchSpaceLength); + + Vector256 cmpCh1 = Vector256.Equals(ch1, LoadVector256(ref searchSpace, offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, LoadVector256(ref searchSpace, offset + ch1ch2Distance)); + Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector256.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + int bitPos = BitOperations.TrailingZeroCount(mask); + // div by 2 (shr) because we work with 2-byte chars + int charPos = (int)((uint)bitPos / 2); + if (valueLength == 2 || // we already matched two chars + SequenceEqual( + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + charPos)), + ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) + { + return offset + charPos; + } + + // Clear two the lowest set bits + if (Bmi1.IsSupported) + mask = Bmi1.ResetLowestSetBit(Bmi1.ResetLowestSetBit(mask)); + else + mask &= ~(uint)(0b11 << bitPos); + } while (mask != 0); + } + offset += Vector256.Count; + + if (offset == searchSpaceMinusValueTailLength) + return -1; + + // Overlap with the current chunk for trailing elements + if (offset > searchSpaceMinusValueTailLength - Vector256.Count) + offset = searchSpaceMinusValueTailLength - Vector256.Count; + } while (true); + } + else // 128bit vector path (SSE2 or AdvSimd) + { + // Find the last unique (which is not equal to ch1) character + // the algorithm is fine if both are equal, just a little bit less efficient + ushort ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == valueHead && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector128 ch1 = Vector128.Create((ushort)valueHead); + Vector128 ch2 = Vector128.Create(ch2Val); + + do + { + // Make sure we don't go out of bounds + Debug.Assert(offset + ch1ch2Distance + Vector128.Count <= searchSpaceLength); + + Vector128 cmpCh1 = Vector128.Equals(ch1, LoadVector128(ref searchSpace, offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, LoadVector128(ref searchSpace, offset + ch1ch2Distance)); + Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector128.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + int bitPos = BitOperations.TrailingZeroCount(mask); + // div by 2 (shr) because we work with 2-byte chars + int charPos = (int)((uint)bitPos / 2); + if (valueLength == 2 || // we already matched two chars + SequenceEqual( + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + charPos)), + ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) + { + return offset + charPos; + } + + // Clear two lowest set bits + if (Bmi1.IsSupported) + mask = Bmi1.ResetLowestSetBit(Bmi1.ResetLowestSetBit(mask)); + else + mask &= ~(uint)(0b11 << bitPos); + } while (mask != 0); + } + offset += Vector128.Count; + + if (offset == searchSpaceMinusValueTailLength) + return -1; + + // Overlap with the current chunk for trailing elements + if (offset > searchSpaceMinusValueTailLength - Vector128.Count) + offset = searchSpaceMinusValueTailLength - Vector128.Count; + } while (true); + } + } + + public static int LastIndexOf(ref char searchSpace, int searchSpaceLength, ref char value, int valueLength) + { + Debug.Assert(searchSpaceLength >= 0); + Debug.Assert(valueLength >= 0); + + if (valueLength == 0) + return searchSpaceLength; // A zero-length sequence is always treated as "found" at the end of the search space. + + int valueTailLength = valueLength - 1; + if (valueTailLength == 0) + return LastIndexOf(ref searchSpace, value, searchSpaceLength); // for single-char values use plain LastIndexOf + + int offset = 0; + char valueHead = value; + int searchSpaceMinusValueTailLength = searchSpaceLength - valueTailLength; + if (Vector128.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector128.Count) + { + goto SEARCH_TWO_CHARS; + } + + ref byte valueTail = ref Unsafe.As(ref Unsafe.Add(ref value, 1)); + + while (true) + { + Debug.Assert(0 <= offset && offset <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength". + int remainingSearchSpaceLength = searchSpaceLength - offset - valueTailLength; + if (remainingSearchSpaceLength <= 0) + break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. + + // Do a quick search for the first element of "value". + int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength); + if (relativeIndex == -1) + break; + + // Found the first element of "value". See if the tail matches. + if (SequenceEqual( + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, relativeIndex + 1)), + ref valueTail, (nuint)(uint)valueTailLength * 2)) + { + return relativeIndex; // The tail matched. Return a successful find. + } + + offset += remainingSearchSpaceLength - relativeIndex; + } + return -1; + + // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła + // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 + SEARCH_TWO_CHARS: + if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector256.Count) + { + offset = searchSpaceMinusValueTailLength - Vector256.Count; + + // Find the last unique (which is not equal to ch1) char + // the algorithm is fine if both are equal, just a little bit less efficient + char ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == valueHead && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector256 ch1 = Vector256.Create((ushort)valueHead); + Vector256 ch2 = Vector256.Create((ushort)ch2Val); + + do + { + + Vector256 cmpCh1 = Vector256.Equals(ch1, LoadVector256(ref searchSpace, (nuint)offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, LoadVector256(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + if (cmpAnd != Vector256.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + // unlike IndexOf, here we use LZCNT to process matches starting from the end + int bitPos = 30 - BitOperations.LeadingZeroCount(mask); + int charPos = (int)((uint)bitPos / 2); + + if (valueLength == 2 || // we already matched two chars + SequenceEqual( + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + charPos)), + ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) + { + return charPos + offset; + } + mask &= ~(uint)(0b11 << bitPos); // clear two highest set bits. + } while (mask != 0); + } + + offset -= Vector256.Count; + if (offset == -Vector256.Count) + return -1; + // Overlap with the current chunk if there is not enough room for the next one + if (offset < 0) + offset = 0; + } while (true); + } + else // 128bit vector path (SSE2 or AdvSimd) + { + offset = searchSpaceMinusValueTailLength - Vector128.Count; + + // Find the last unique (which is not equal to ch1) char + // the algorithm is fine if both are equal, just a little bit less efficient + char ch2Val = Unsafe.Add(ref value, valueTailLength); + int ch1ch2Distance = valueTailLength; + while (ch2Val == value && ch1ch2Distance > 1) + ch2Val = Unsafe.Add(ref value, --ch1ch2Distance); + + Vector128 ch1 = Vector128.Create((ushort)value); + Vector128 ch2 = Vector128.Create((ushort)ch2Val); + + do + { + Vector128 cmpCh1 = Vector128.Equals(ch1, LoadVector128(ref searchSpace, (nuint)offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, LoadVector128(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); + + // Early out: cmpAnd is all zeros + // it's especially important for ARM where ExtractMostSignificantBits is not cheap + if (cmpAnd != Vector128.Zero) + { + uint mask = cmpAnd.ExtractMostSignificantBits(); + do + { + // unlike IndexOf, here we use LZCNT to process matches starting from the end + int bitPos = 30 - BitOperations.LeadingZeroCount(mask); + int charPos = (int)((uint)bitPos / 2); + + if (valueLength == 2 || // we already matched two chars + SequenceEqual( + ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + charPos)), + ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) + { + return charPos + offset; + } + mask &= ~(uint)(0b11 << bitPos); // clear two the highest set bits. + } while (mask != 0); + } + + offset -= Vector128.Count; + if (offset == -Vector128.Count) + return -1; + // Overlap with the current chunk if there is not enough room for the next one + if (offset < 0) + offset = 0; + } while (true); + } } [MethodImpl(MethodImplOptions.AggressiveOptimization)] diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index 91d2a34a47796..27944aff4876c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -774,11 +774,17 @@ public static int LastIndexOf(ref T searchSpace, int searchSpaceLength, ref T if (valueLength == 0) return searchSpaceLength; // A zero-length sequence is always treated as "found" at the end of the search space. - T valueHead = value; - ref T valueTail = ref Unsafe.Add(ref value, 1); int valueTailLength = valueLength - 1; + if (valueTailLength == 0) + { + return LastIndexOf(ref searchSpace, value, searchSpaceLength); + } int index = 0; + + T valueHead = value; + ref T valueTail = ref Unsafe.Add(ref value, 1); + while (true) { Debug.Assert(0 <= index && index <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength". diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index 9d068b4da0bc9..6a059351f376a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -683,6 +683,18 @@ public bool Equals([NotNullWhen(true)] string? value, StringComparison compariso // Determines whether two Strings match. public static bool Equals(string? a, string? b) { + // Transform 'str == ""' to 'str != null && str.Length == 0' if either a or b are jit-time + // constants. Otherwise, these two blocks are eliminated + if (RuntimeHelpers.IsKnownConstant(a) && a != null && a.Length == 0) + { + return b != null && b.Length == 0; + } + + if (RuntimeHelpers.IsKnownConstant(b) && b != null && b.Length == 0) + { + return a != null && a.Length == 0; + } + if (object.ReferenceEquals(a, b)) { return true; @@ -1013,7 +1025,14 @@ public bool StartsWith(string value, bool ignoreCase, CultureInfo? culture) return referenceCulture.CompareInfo.IsPrefix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None); } - public bool StartsWith(char value) => Length != 0 && _firstChar == value; + public bool StartsWith(char value) + { + if (RuntimeHelpers.IsKnownConstant(value) && value != '\0') + { + return _firstChar == value; + } + return Length != 0 && _firstChar == value; + } internal static void CheckStringComparison(StringComparison comparisonType) { diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 0143c030432f5..0097b92631ff0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -925,15 +925,7 @@ public string Replace(string oldValue, string? newValue, StringComparison compar private string ReplaceCore(string oldValue, string? newValue, CompareInfo? ci, CompareOptions options) { - if (oldValue is null) - { - throw new ArgumentNullException(nameof(oldValue)); - } - - if (oldValue.Length == 0) - { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(oldValue)); - } + ArgumentException.ThrowIfNullOrEmpty(oldValue); // If they asked to replace oldValue with a null, replace all occurrences // with the empty string. AsSpan() will normalize appropriately. @@ -1054,14 +1046,7 @@ public string Replace(char oldChar, char newChar) public string Replace(string oldValue, string? newValue) { - if (oldValue is null) - { - throw new ArgumentNullException(nameof(oldValue)); - } - if (oldValue.Length == 0) - { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(oldValue)); - } + ArgumentException.ThrowIfNullOrEmpty(oldValue); // If newValue is null, treat it as an empty string. Callers use this to remove the oldValue. newValue ??= Empty; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderReplacementFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderReplacementFallback.cs index 8f769f1c45bca..34270ba3c30ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderReplacementFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderReplacementFallback.cs @@ -57,7 +57,7 @@ public DecoderReplacementFallback(string replacement) break; } if (bFoundHigh) - throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement))); + throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement)); _strDefault = replacement; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderReplacementFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderReplacementFallback.cs index 5c93f4cc2cdb7..709695ce36dd1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderReplacementFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderReplacementFallback.cs @@ -58,7 +58,7 @@ public EncoderReplacementFallback(string replacement) break; } if (bFoundHigh) - throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement))); + throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement)); _strDefault = replacement; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index 5957628a6ac84..8a8d6a93b5794 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -408,14 +408,8 @@ public string ToString(int startIndex, int length) AssertInvariants(); string result = string.FastAllocateString(length); - unsafe - { - fixed (char* destinationPtr = result) - { - this.CopyTo(startIndex, new Span(destinationPtr, length), length); - return result; - } - } + CopyTo(startIndex, new Span(ref result.GetRawStringData(), result.Length), result.Length); + return result; } public StringBuilder Clear() @@ -639,7 +633,7 @@ internal ChunkEnumerator(StringBuilder stringBuilder) // are a linked list with each chunk pointing to its PREDECESSOR, walking // the list FORWARD is not efficient. If there are few chunks (< 8) we // simply scan from the start each time, and tolerate the N*N behavior. - // However above this size, we allocate an array to hold pointers to all + // However above this size, we allocate an array to hold reference to all // the chunks and we can be efficient for large N. int chunkCount = ChunkCount(stringBuilder); if (8 < chunkCount) @@ -771,19 +765,12 @@ public StringBuilder Append(char[]? value, int startIndex, int charCount) throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_Index); } - if (charCount == 0) + if (charCount != 0) { - return this; + Append(ref value[startIndex], charCount); } - unsafe - { - fixed (char* valueChars = &value[startIndex]) - { - Append(valueChars, charCount); - return this; - } - } + return this; } /// @@ -792,58 +779,14 @@ public StringBuilder Append(char[]? value, int startIndex, int charCount) /// The string to append. public StringBuilder Append(string? value) { - if (value != null) + if (value is not null) { - // We could have just called AppendHelper here; this is a hand-specialization of that code. - char[] chunkChars = m_ChunkChars; - int chunkLength = m_ChunkLength; - int valueLen = value.Length; - - if (((uint)chunkLength + (uint)valueLen) < (uint)chunkChars.Length) // Use strictly < to avoid issues if count == 0, newIndex == length - { - if (valueLen <= 2) - { - if (valueLen > 0) - { - chunkChars[chunkLength] = value[0]; - } - if (valueLen > 1) - { - chunkChars[chunkLength + 1] = value[1]; - } - } - else - { - Buffer.Memmove( - ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(chunkChars), chunkLength), - ref value.GetRawStringData(), - (nuint)valueLen); - } - - m_ChunkLength = chunkLength + valueLen; - } - else - { - AppendHelper(value); - } + Append(valueCount: value.Length, value: ref value.GetRawStringData()); } return this; } - // We put this fixed in its own helper to avoid the cost of zero-initing `valueChars` in the - // case we don't actually use it. - private void AppendHelper(string value) - { - unsafe - { - fixed (char* valueChars = value) - { - Append(valueChars, value.Length); - } - } - } - /// /// Appends part of a string to the end of this builder. /// @@ -870,24 +813,17 @@ public StringBuilder Append(string? value, int startIndex, int count) throw new ArgumentNullException(nameof(value)); } - if (count == 0) - { - return this; - } - - if (startIndex > value.Length - count) - { - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - } - - unsafe + if (count != 0) { - fixed (char* valueChars = value) + if (startIndex > value.Length - count) { - Append(valueChars + startIndex, count); - return this; + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); } + + Append(ref Unsafe.Add(ref value.GetRawStringData(), startIndex), count); } + + return this; } public StringBuilder Append(StringBuilder? value) @@ -1073,19 +1009,14 @@ public StringBuilder Insert(int index, string? value, int count) Debug.Assert(insertingChars + this.Length < int.MaxValue); MakeRoom(index, (int)insertingChars, out StringBuilder chunk, out int indexInChunk, false); - unsafe - { - fixed (char* valuePtr = value) - { - while (count > 0) - { - ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, valuePtr, value.Length); - --count; - } - return this; - } + while (count > 0) + { + ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, ref value.GetRawStringData(), value.Length); + --count; } + + return this; } /// @@ -1203,31 +1134,17 @@ internal StringBuilder AppendSpanFormattable(T value, string? format, IFormat public StringBuilder Append(char[]? value) { - if (value?.Length > 0) + if (value is not null) { - unsafe - { - fixed (char* valueChars = &value[0]) - { - Append(valueChars, value.Length); - } - } + Append(ref MemoryMarshal.GetArrayDataReference(value), value.Length); } + return this; } public StringBuilder Append(ReadOnlySpan value) { - if (value.Length > 0) - { - unsafe - { - fixed (char* valueChars = &MemoryMarshal.GetReference(value)) - { - Append(valueChars, value.Length); - } - } - } + Append(ref MemoryMarshal.GetReference(value), value.Length); return this; } @@ -1257,51 +1174,42 @@ public StringBuilder Append(ReadOnlySpan value) #region AppendJoin - public unsafe StringBuilder AppendJoin(string? separator, params object?[] values) + public StringBuilder AppendJoin(string? separator, params object?[] values) { separator ??= string.Empty; - fixed (char* pSeparator = separator) - { - return AppendJoinCore(pSeparator, separator.Length, values); - } + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); } - public unsafe StringBuilder AppendJoin(string? separator, IEnumerable values) + public StringBuilder AppendJoin(string? separator, IEnumerable values) { separator ??= string.Empty; - fixed (char* pSeparator = separator) - { - return AppendJoinCore(pSeparator, separator.Length, values); - } + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); } - public unsafe StringBuilder AppendJoin(string? separator, params string?[] values) + public StringBuilder AppendJoin(string? separator, params string?[] values) { separator ??= string.Empty; - fixed (char* pSeparator = separator) - { - return AppendJoinCore(pSeparator, separator.Length, values); - } + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); } - public unsafe StringBuilder AppendJoin(char separator, params object?[] values) + public StringBuilder AppendJoin(char separator, params object?[] values) { - return AppendJoinCore(&separator, 1, values); + return AppendJoinCore(ref separator, 1, values); } - public unsafe StringBuilder AppendJoin(char separator, IEnumerable values) + public StringBuilder AppendJoin(char separator, IEnumerable values) { - return AppendJoinCore(&separator, 1, values); + return AppendJoinCore(ref separator, 1, values); } - public unsafe StringBuilder AppendJoin(char separator, params string?[] values) + public StringBuilder AppendJoin(char separator, params string?[] values) { - return AppendJoinCore(&separator, 1, values); + return AppendJoinCore(ref separator, 1, values); } - private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, IEnumerable values) + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, IEnumerable values) { - Debug.Assert(separator != null); + Debug.Assert(!Unsafe.IsNullRef(ref separator)); Debug.Assert(separatorLength >= 0); if (values == null) @@ -1325,7 +1233,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen while (en.MoveNext()) { - Append(separator, separatorLength); + Append(ref separator, separatorLength); value = en.Current; if (value != null) { @@ -1336,7 +1244,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen return this; } - private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, T[] values) + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, T[] values) { if (values == null) { @@ -1356,7 +1264,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen for (int i = 1; i < values.Length; i++) { - Append(separator, separatorLength); + Append(ref separator, separatorLength); if (values[i] != null) { Append(values[i]!.ToString()); @@ -1376,12 +1284,9 @@ public StringBuilder Insert(int index, string? value) if (value != null) { - unsafe - { - fixed (char* sourcePtr = value) - Insert(index, sourcePtr, value.Length); - } + Insert(index, ref value.GetRawStringData(), value.Length); } + return this; } @@ -1396,10 +1301,7 @@ public StringBuilder Insert(int index, string? value) public StringBuilder Insert(int index, char value) { - unsafe - { - Insert(index, &value, 1); - } + Insert(index, ref value, 1); return this; } @@ -1451,12 +1353,9 @@ public StringBuilder Insert(int index, char[]? value, int startIndex, int charCo if (charCount > 0) { - unsafe - { - fixed (char* sourcePtr = &value[startIndex]) - Insert(index, sourcePtr, charCount); - } + Insert(index, ref value[startIndex], charCount); } + return this; } @@ -1488,14 +1387,11 @@ public StringBuilder Insert(int index, ReadOnlySpan value) throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } - if (value.Length > 0) + if (value.Length != 0) { - unsafe - { - fixed (char* sourcePtr = &MemoryMarshal.GetReference(value)) - Insert(index, sourcePtr, value.Length); - } + Insert(index, ref MemoryMarshal.GetReference(value), value.Length); } + return this; } @@ -1776,7 +1672,7 @@ internal StringBuilder AppendFormatHelper(IFormatProvider? provider, string form if ((uint)charsWritten > (uint)RemainingCurrentChunk.Length) { // Untrusted ISpanFormattable implementations might return an erroneous charsWritten value, - // and m_ChunkLength might end up being used in unsafe code, so fail if we get back an + // and m_ChunkLength might end up being used in Unsafe code, so fail if we get back an // out-of-range charsWritten value. FormatError(); } @@ -1959,14 +1855,7 @@ public StringBuilder Replace(string oldValue, string? newValue, int startIndex, { throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Index); } - if (oldValue == null) - { - throw new ArgumentNullException(nameof(oldValue)); - } - if (oldValue.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(oldValue)); - } + ArgumentException.ThrowIfNullOrEmpty(oldValue); newValue ??= string.Empty; @@ -1979,7 +1868,8 @@ public StringBuilder Replace(string oldValue, string? newValue, int startIndex, while (count > 0) { Debug.Assert(chunk != null, "chunk was null in replace"); - // Look for a match in the chunk,indexInChunk pointer + + // Look for a match in the chunk,indexInChunk reference if (StartsWith(chunk, indexInChunk, count, oldValue)) { // Push it on the replacements array (with growth), we will do all replacements in a @@ -2063,13 +1953,16 @@ public StringBuilder Replace(char oldChar, char newChar, int startIndex, int cou { int curInChunk = Math.Max(startIndexInChunk, 0); int endInChunk = Math.Min(chunk.m_ChunkLength, endIndexInChunk); - while (curInChunk < endInChunk) + + Span span = chunk.m_ChunkChars.AsSpan(curInChunk, endInChunk - curInChunk); + int i; + while ((i = span.IndexOf(oldChar)) >= 0) { - if (chunk.m_ChunkChars[curInChunk] == oldChar) - chunk.m_ChunkChars[curInChunk] = newChar; - curInChunk++; + span[i] = newChar; + span = span.Slice(i + 1); } } + if (startIndexInChunk >= 0) { break; @@ -2097,51 +1990,81 @@ public unsafe StringBuilder Append(char* value, int valueCount) throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_NegativeCount); } - // this is where we can check if the valueCount will put us over m_MaxCapacity - // We are doing the check here to prevent the corruption of the StringBuilder. + Append(ref *value, valueCount); + return this; + } + + /// Appends a specified number of chars starting from the specified reference. + private void Append(ref char value, int valueCount) + { + Debug.Assert(valueCount >= 0, $"Invalid length; should have been validated by caller."); + if (valueCount != 0) + { + char[] chunkChars = m_ChunkChars; + int chunkLength = m_ChunkLength; + + if (((uint)chunkLength + (uint)valueCount) <= (uint)chunkChars.Length) + { + ref char destination = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(chunkChars), chunkLength); + if (valueCount <= 2) + { + destination = value; + if (valueCount == 2) + { + Unsafe.Add(ref destination, 1) = Unsafe.Add(ref value, 1); + } + } + else + { + Buffer.Memmove(ref destination, ref value, (nuint)valueCount); + } + + m_ChunkLength = chunkLength + valueCount; + } + else + { + AppendWithExpansion(ref value, valueCount); + } + } + } + + private void AppendWithExpansion(ref char value, int valueCount) + { + // Check if the valueCount will put us over m_MaxCapacity. + // Doing the check here prevents corruption of the StringBuilder. int newLength = Length + valueCount; if (newLength > m_MaxCapacity || newLength < valueCount) { throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_LengthGreaterThanCapacity); } - // This case is so common we want to optimize for it heavily. - int newIndex = valueCount + m_ChunkLength; - if (newIndex <= m_ChunkChars.Length) + // Copy the first chunk + int firstLength = m_ChunkChars.Length - m_ChunkLength; + if (firstLength > 0) { - new ReadOnlySpan(value, valueCount).CopyTo(m_ChunkChars.AsSpan(m_ChunkLength)); - m_ChunkLength = newIndex; + new ReadOnlySpan(ref value, firstLength).CopyTo(m_ChunkChars.AsSpan(m_ChunkLength)); + m_ChunkLength = m_ChunkChars.Length; } - else - { - // Copy the first chunk - int firstLength = m_ChunkChars.Length - m_ChunkLength; - if (firstLength > 0) - { - new ReadOnlySpan(value, firstLength).CopyTo(m_ChunkChars.AsSpan(m_ChunkLength)); - m_ChunkLength = m_ChunkChars.Length; - } - // Expand the builder to add another chunk. - int restLength = valueCount - firstLength; - ExpandByABlock(restLength); - Debug.Assert(m_ChunkLength == 0, "A new block was not created."); + // Expand the builder to add another chunk. + int restLength = valueCount - firstLength; + ExpandByABlock(restLength); + Debug.Assert(m_ChunkLength == 0, "A new block was not created."); + + // Copy the second chunk + new ReadOnlySpan(ref Unsafe.Add(ref value, firstLength), restLength).CopyTo(m_ChunkChars); + m_ChunkLength = restLength; - // Copy the second chunk - new ReadOnlySpan(value + firstLength, restLength).CopyTo(m_ChunkChars); - m_ChunkLength = restLength; - } AssertInvariants(); - return this; } /// /// Inserts a character buffer into this builder at the specified position. /// /// The index to insert in this builder. - /// The pointer to the start of the buffer. + /// The reference to the start of the buffer. /// The number of characters in the buffer. - private unsafe void Insert(int index, char* value, int valueCount) + private void Insert(int index, ref char value, int valueCount) { if ((uint)index > (uint)Length) { @@ -2151,7 +2074,7 @@ private unsafe void Insert(int index, char* value, int valueCount) if (valueCount > 0) { MakeRoom(index, valueCount, out StringBuilder chunk, out int indexInChunk, false); - ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, value, valueCount); + ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, ref value, valueCount); } } @@ -2172,64 +2095,57 @@ private void ReplaceAllInChunk(ReadOnlySpan replacements, StringBuilder sou return; } - unsafe + // calculate the total amount of extra space or space needed for all the replacements. + long longDelta = (value.Length - removeCount) * (long)replacements.Length; + int delta = (int)longDelta; + if (delta != longDelta) { - fixed (char* valuePtr = value) - { - // calculate the total amount of extra space or space needed for all the replacements. - long longDelta = (value.Length - removeCount) * (long)replacements.Length; - int delta = (int)longDelta; - if (delta != longDelta) - { - throw new OutOfMemoryException(); - } - - StringBuilder targetChunk = sourceChunk; // the target as we copy chars down - int targetIndexInChunk = replacements[0]; + throw new OutOfMemoryException(); + } - // Make the room needed for all the new characters if needed. - if (delta > 0) - { - MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true); - } + StringBuilder targetChunk = sourceChunk; // the target as we copy chars down + int targetIndexInChunk = replacements[0]; - // We made certain that characters after the insertion point are not moved, - int i = 0; - while (true) - { - // Copy in the new string for the ith replacement - ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, valuePtr, value.Length); - int gapStart = replacements[i] + removeCount; - i++; - if ((uint)i >= replacements.Length) - { - break; - } + // Make the room needed for all the new characters if needed. + if (delta > 0) + { + MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true); + } - int gapEnd = replacements[i]; - Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen"); - Debug.Assert(gapStart <= gapEnd, "negative gap size"); - Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big"); - if (delta != 0) // can skip the sliding of gaps if source an target string are the same size. - { - // Copy the gap data between the current replacement and the next replacement - fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart]) - ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, sourcePtr, gapEnd - gapStart); - } - else - { - targetIndexInChunk += gapEnd - gapStart; - Debug.Assert(targetIndexInChunk <= targetChunk.m_ChunkLength, "gap not in chunk"); - } - } + // We made certain that characters after the insertion point are not moved, + int i = 0; + while (true) + { + // Copy in the new string for the ith replacement + ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, ref value.GetRawStringData(), value.Length); + int gapStart = replacements[i] + removeCount; + i++; + if ((uint)i >= replacements.Length) + { + break; + } - // Remove extra space if necessary. - if (delta < 0) - { - Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk); - } + int gapEnd = replacements[i]; + Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen"); + Debug.Assert(gapStart <= gapEnd, "negative gap size"); + Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big"); + if (delta != 0) // can skip the sliding of gaps if source an target string are the same size. + { + // Copy the gap data between the current replacement and the next replacement + ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, ref sourceChunk.m_ChunkChars[gapStart], gapEnd - gapStart); + } + else + { + targetIndexInChunk += gapEnd - gapStart; + Debug.Assert(targetIndexInChunk <= targetChunk.m_ChunkLength, "gap not in chunk"); } } + + // Remove extra space if necessary. + if (delta < 0) + { + Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk); + } } /// @@ -2282,9 +2198,9 @@ private bool StartsWith(StringBuilder chunk, int indexInChunk, int count, string /// The index in to start replacing characters at. /// Receives the index at which character replacement ends. /// - /// The pointer to the start of the character buffer. + /// The reference to the start of the character buffer. /// The number of characters in the buffer. - private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder? chunk, ref int indexInChunk, char* value, int count) + private void ReplaceInPlaceAtChunk(ref StringBuilder? chunk, ref int indexInChunk, ref char value, int count) { if (count != 0) { @@ -2295,7 +2211,7 @@ private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder? chunk, ref int inde Debug.Assert(lengthInChunk >= 0, "Index isn't in the chunk."); int lengthToCopy = Math.Min(lengthInChunk, count); - new ReadOnlySpan(value, lengthToCopy).CopyTo(chunk.m_ChunkChars.AsSpan(indexInChunk)); + new ReadOnlySpan(ref value, lengthToCopy).CopyTo(chunk.m_ChunkChars.AsSpan(indexInChunk)); // Advance the index. indexInChunk += lengthToCopy; @@ -2309,7 +2225,7 @@ private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder? chunk, ref int inde { break; } - value += lengthToCopy; + value = ref Unsafe.Add(ref value, lengthToCopy); } } } @@ -2349,8 +2265,8 @@ private Span RemainingCurrentChunk /// /// The chunk whose successor should be found. /// - /// Each chunk only stores the pointer to its logical predecessor, so this routine has to start - /// from the 'this' pointer (which is assumed to represent the whole StringBuilder) and work its + /// Each chunk only stores the reference to its logical predecessor, so this routine has to start + /// from the 'this' reference (which is assumed to represent the whole StringBuilder) and work its /// way down until it finds the specified chunk (which is O(n)). Thus, it is more expensive than /// a field fetch. /// @@ -2391,7 +2307,7 @@ private void ExpandByABlock(int minBlockCharCount) // Allocate the array before updating any state to avoid leaving inconsistent state behind in case of out of memory exception char[] chunkChars = GC.AllocateUninitializedArray(newBlockLength); - // Move all of the data from this chunk to a new one, via a few O(1) pointer adjustments. + // Move all of the data from this chunk to a new one, via a few O(1) reference adjustments. // Then, have this chunk point to the new one as its predecessor. m_ChunkPrevious = new StringBuilder(this); m_ChunkOffset += m_ChunkLength; @@ -2709,7 +2625,7 @@ public void AppendFormatted(T value) if ((uint)charsWritten > (uint)destination.Length) { // Protect against faulty ISpanFormattable implementations returning invalid charsWritten values. - // Other code in _stringBuilder uses unsafe manipulation, and we want to ensure m_ChunkLength remains safe. + // Other code in _stringBuilder uses Unsafe manipulation, and we want to ensure m_ChunkLength remains safe. FormatError(); } @@ -2762,7 +2678,7 @@ public void AppendFormatted(T value, string? format) if ((uint)charsWritten > (uint)destination.Length) { // Protect against faulty ISpanFormattable implementations returning invalid charsWritten values. - // Other code in _stringBuilder uses unsafe manipulation, and we want to ensure m_ChunkLength remains safe. + // Other code in _stringBuilder uses Unsafe manipulation, and we want to ensure m_ChunkLength remains safe. FormatError(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs index ab03e12e87be0..27f29cb0dd949 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs @@ -27,7 +27,7 @@ namespace System.Threading /// /// [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")] - public readonly struct CancellationToken + public readonly struct CancellationToken : IEquatable { // The backing TokenSource. // if null, it implicitly represents the same thing as new CancellationToken(false). diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs index 20cb741435f0c..bf4427fa36c3e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs @@ -44,10 +44,7 @@ private void CreateEventCore(bool initialState, EventResetMode mode, string? nam private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle? result) { #if TARGET_WINDOWS - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); result = null; SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs index 6b6b86eb28b71..25a229c87ef66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs @@ -242,7 +242,7 @@ private bool WaitForSignal(int timeoutMs) } } - private struct Counts + private struct Counts : IEquatable { private const byte SignalCountShift = 0; private const byte WaiterCountShift = 32; @@ -350,10 +350,11 @@ public void DecrementCountOfWaitersSignaledToWake() public Counts InterlockedCompareExchange(Counts newCounts, Counts oldCounts) => new Counts(Interlocked.CompareExchange(ref _data, newCounts._data, oldCounts._data)); - public static bool operator ==(Counts lhs, Counts rhs) => lhs._data == rhs._data; - public static bool operator !=(Counts lhs, Counts rhs) => lhs._data != rhs._data; + public static bool operator ==(Counts lhs, Counts rhs) => lhs.Equals(rhs); + public static bool operator !=(Counts lhs, Counts rhs) => !lhs.Equals(rhs); - public override bool Equals([NotNullWhen(true)] object? obj) => obj is Counts counts && _data == counts._data; + public override bool Equals([NotNullWhen(true)] object? obj) => obj is Counts other && Equals(other); + public bool Equals(Counts other) => _data == other._data; public override int GetHashCode() => (int)_data + (int)(_data >> 32); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs index 61be44de4a1b8..2f6e63aacec79 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs @@ -29,15 +29,7 @@ private void CreateMutexCore(bool initiallyOwned, string? name, out bool created private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); OpenExistingResult status = WaitSubsystem.OpenNamedMutex(name, out SafeWaitHandle? safeWaitHandle); result = status == OpenExistingResult.Success ? new Mutex(safeWaitHandle!) : null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs index 48f23264a7f6c..f1a22346801d4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs @@ -41,15 +41,7 @@ private void CreateMutexCore(bool initiallyOwned, string? name, out bool created private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); result = null; // To allow users to view & edit the ACL's, call OpenMutex diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs index 43aa0fcf7102c..3242f165aff9a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs @@ -11,7 +11,7 @@ internal sealed partial class PortableThreadPool /// /// Tracks information on the number of threads we want/have in different states in our thread pool. /// - private struct ThreadCounts + private struct ThreadCounts : IEquatable { // SOS's ThreadPool command depends on this layout private const byte NumProcessingWorkShift = 0; @@ -126,7 +126,8 @@ public ThreadCounts InterlockedCompareExchange(ThreadCounts newCounts, ThreadCou public static bool operator ==(ThreadCounts lhs, ThreadCounts rhs) => lhs._data == rhs._data; public static bool operator !=(ThreadCounts lhs, ThreadCounts rhs) => lhs._data != rhs._data; - public override bool Equals([NotNullWhen(true)] object? obj) => obj is ThreadCounts other && _data == other._data; + public override bool Equals([NotNullWhen(true)] object? obj) => obj is ThreadCounts other && Equals(other); + public bool Equals(ThreadCounts other) => _data == other._data; public override int GetHashCode() => (int)_data + (int)(_data >> 32); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs index 8c588965add43..8a5f1d8bba581 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs @@ -58,7 +58,7 @@ private short GetAndResetHighWatermarkCountOfThreadsProcessingUserCallbacks() /// /// Tracks thread count information that is used when the EnableWorkerTracking config option is enabled. /// - private struct CountsOfThreadsProcessingUserCallbacks + private struct CountsOfThreadsProcessingUserCallbacks : IEquatable { private const byte CurrentShift = 0; private const byte HighWatermarkShift = 16; @@ -114,13 +114,16 @@ public CountsOfThreadsProcessingUserCallbacks InterlockedCompareExchange( public static bool operator ==( CountsOfThreadsProcessingUserCallbacks lhs, - CountsOfThreadsProcessingUserCallbacks rhs) => lhs._data == rhs._data; + CountsOfThreadsProcessingUserCallbacks rhs) => lhs.Equals(rhs); public static bool operator !=( CountsOfThreadsProcessingUserCallbacks lhs, - CountsOfThreadsProcessingUserCallbacks rhs) => lhs._data != rhs._data; + CountsOfThreadsProcessingUserCallbacks rhs) => !lhs.Equals(rhs); public override bool Equals([NotNullWhen(true)] object? obj) => - obj is CountsOfThreadsProcessingUserCallbacks other && _data == other._data; + obj is CountsOfThreadsProcessingUserCallbacks other && Equals(other); + + public bool Equals(CountsOfThreadsProcessingUserCallbacks other) => _data == other._data; + public override int GetHashCode() => (int)_data; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs index d92e9c9f88771..013023fe212a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs @@ -45,10 +45,7 @@ private void CreateSemaphoreCore(int initialCount, int maximumCount, string? nam private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? result) { #if TARGET_WINDOWS - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); // Pass false to OpenSemaphore to prevent inheritedHandles SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/CachedCompletedInt32Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/CachedCompletedInt32Task.cs new file mode 100644 index 0000000000000..080253a37dc5a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/CachedCompletedInt32Task.cs @@ -0,0 +1,36 @@ +// 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 System.IO; +using System.Runtime.CompilerServices; + +namespace System.Threading.Tasks +{ + /// + /// Encapsulates the logic of caching the last synchronously completed task of integer. + /// Used in classes like to reduce allocations. + /// + internal struct CachedCompletedInt32Task + { + private Task? _task; + + /// Gets a completed whose result is . + /// This method will try to return an already cached task if available. + /// The result value for which a is needed. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Task GetTask(int result) + { + if (_task is Task task) + { + Debug.Assert(task.IsCompletedSuccessfully, "Expected that a stored last task completed successfully"); + if (task.Result == result) + { + return task; + } + } + + return _task = Task.FromResult(result); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index 6e319542ce488..f5a4becbd73b4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -5627,6 +5627,20 @@ internal DelayPromiseWithCancellation(uint millisecondsDelay, CancellationToken _registration = token.UnsafeRegister(static (state, cancellationToken) => { var thisRef = (DelayPromiseWithCancellation)state!; + + // Normally RunContinuationsAsynchronously is set at construction time. We don't want to + // set it at construction because we want the timer firing (already on a thread pool thread with + // a stack in which it's fine to execute arbitrary code) to synchronously invoke any continuations + // from this task. However, a cancellation request will come synchronously from a call to + // CancellationTokenSource.Cancel, and we don't want to invoke arbitrary continuations from + // this delay task as part of that Cancel call. As such, we set RunContinuationsAsynchronously + // after the fact, only when the task is being completed due to cancellation. There is a race + // condition here, such that if the timer also fired concurrently, it might win, in which case + // it might also observe this RunContinuationsAsynchronously, but that's benign. An alternative + // is to make the whole cancellation registration queue, but that's visible in that the Task's + // IsCompleted wouldn't be set synchronously as part of IsCompleted. + thisRef.AtomicStateUpdate((int)TaskCreationOptions.RunContinuationsAsynchronously, 0); + if (thisRef.TrySetCanceled(cancellationToken)) { thisRef.Cleanup(); diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index e3f7c2a4b0e3e..781cd38aaadb3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -494,6 +494,12 @@ internal static void ThrowFormatException_BadFormatSpecifier() throw new FormatException(SR.Argument_BadFormatSpecifier); } + [DoesNotReturn] + internal static void ThrowFileLoadException_InvalidAssemblyName(string name) + { + throw new FileLoadException(SR.InvalidAssemblyName, name); + } + [DoesNotReturn] internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge() { @@ -524,12 +530,6 @@ internal static void ArgumentOutOfRangeException_Enum_Value() throw new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_Enum); } - internal static void ThrowForMissingPath_SafeFileHandle(string? path) - { - if (path is not null) return; - throw new IOException(SR.IO_SafeFileHandlePathNull); - } - private static Exception GetArraySegmentCtorValidationFailedException(Array? array, int offset, int count) { if (array == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs index ee3d11925d0c3..a979ce561452e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs @@ -892,15 +892,13 @@ public string ToString(string? format, IFormatProvider? provider) return DateTimeFormat.TryFormat(ToDateTime(), destination, out charsWritten, format, provider); default: - charsWritten = 0; - return false; + throw new FormatException(SR.Argument_BadFormatSpecifier); } } if (!DateTimeFormat.IsValidCustomTimeFormat(format, throwOnError: false)) { - charsWritten = 0; - return false; + throw new FormatException(SR.Format(SR.Format_DateTimeOnlyContainsNoneDateParts, format.ToString(), nameof(TimeOnly))); } return DateTimeFormat.TryFormat(ToDateTime(), destination, out charsWritten, format, provider); diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs index 6f53ab75ce351..7c754b4f28570 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs @@ -56,6 +56,12 @@ public bool Equals([NotNullWhen(true)] AdjustmentRule? other) => _daylightTransitionEnd.Equals(other._daylightTransitionEnd) && _daylightTransitionStart.Equals(other._daylightTransitionStart); + /// Indicates whether the current instance is equal to another instance. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is AdjustmentRule other && Equals(other); + public override int GetHashCode() => _dateStart.GetHashCode(); private AdjustmentRule( diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 53baf4eb65111..23c1044e1983c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -193,6 +193,7 @@ private sealed class AndroidTzData private string[] _ids; private int[] _byteOffsets; private int[] _lengths; + private bool[] _isBackwards; private string _tzFileDir; private string _tzFilePath; @@ -230,7 +231,7 @@ public AndroidTzData() foreach (var tzFileDir in tzFileDirList) { string tzFilePath = Path.Combine(tzFileDir, TimeZoneFileName); - if (LoadData(tzFilePath)) + if (LoadData(tzFileDir, tzFilePath)) { _tzFileDir = tzFileDir; _tzFilePath = tzFilePath; @@ -241,10 +242,62 @@ public AndroidTzData() throw new TimeZoneNotFoundException(SR.TimeZoneNotFound_ValidTimeZoneFileMissing); } + // On some versions of Android, the tzdata file may still contain backward timezone ids. + // We attempt to use tzlookup.xml, which is available on some versions of Android to help + // validate non-backward timezone ids + // tzlookup.xml is an autogenerated file that contains timezone ids in this form: + // + // + // + // + // Australia/Sydney + // ... + // ... + // Australia/Eucla + // + // + // ... + // ... + // ... + // + // + // + // + // Once the timezone cache is populated with the IDs, we reference tzlookup id tags + // to determine if an id is backwards and label it as such if they are. + private void FilterBackwardIDs(string tzFileDir, out HashSet tzLookupIDs) + { + tzLookupIDs = new HashSet(); + try + { + using (StreamReader sr = File.OpenText(Path.Combine(tzFileDir, "tzlookup.xml"))) + { + string? tzLookupLine; + while (sr.Peek() >= 0) + { + if (!(tzLookupLine = sr.ReadLine())!.AsSpan().TrimStart().StartsWith("') + 1; + int idLength = tzLookupLine.LastIndexOf(" or the end tag are not found + continue; + } + string id = tzLookupLine.Substring(idStart, idLength); + tzLookupIDs.Add(id); + } + } + } + catch {} + } + [MemberNotNullWhen(true, nameof(_ids))] [MemberNotNullWhen(true, nameof(_byteOffsets))] [MemberNotNullWhen(true, nameof(_lengths))] - private bool LoadData(string path) + [MemberNotNullWhen(true, nameof(_isBackwards))] + private bool LoadData(string tzFileDir, string path) { if (!File.Exists(path)) { @@ -254,7 +307,7 @@ private bool LoadData(string path) { using (FileStream fs = File.OpenRead(path)) { - LoadTzFile(fs); + LoadTzFile(tzFileDir, fs); } return true; } @@ -266,7 +319,8 @@ private bool LoadData(string path) [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void LoadTzFile(Stream fs) + [MemberNotNull(nameof(_isBackwards))] + private void LoadTzFile(string tzFileDir, Stream fs) { const int HeaderSize = 24; Span buffer = stackalloc byte[HeaderSize]; @@ -274,7 +328,7 @@ private void LoadTzFile(Stream fs) ReadTzDataIntoBuffer(fs, 0, buffer); LoadHeader(buffer, out int indexOffset, out int dataOffset); - ReadIndex(fs, indexOffset, dataOffset); + ReadIndex(tzFileDir, fs, indexOffset, dataOffset); } private void LoadHeader(Span buffer, out int indexOffset, out int dataOffset) @@ -303,16 +357,17 @@ private void LoadHeader(Span buffer, out int indexOffset, out int dataOffs [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void ReadIndex(Stream fs, int indexOffset, int dataOffset) + [MemberNotNull(nameof(_isBackwards))] + private void ReadIndex(string tzFileDir, Stream fs, int indexOffset, int dataOffset) { int indexSize = dataOffset - indexOffset; const int entrySize = 52; // Data entry size int entryCount = indexSize / entrySize; - _byteOffsets = new int[entryCount]; _ids = new string[entryCount]; _lengths = new int[entryCount]; - + _isBackwards = new bool[entryCount]; + FilterBackwardIDs(tzFileDir, out HashSet tzLookupIDs); for (int i = 0; i < entryCount; ++i) { LoadEntryAt(fs, indexOffset + (entrySize*i), out string id, out int byteOffset, out int length); @@ -320,6 +375,7 @@ private void ReadIndex(Stream fs, int indexOffset, int dataOffset) _byteOffsets[i] = byteOffset + dataOffset; _ids[i] = id; _lengths[i] = length; + _isBackwards[i] = !tzLookupIDs.Contains(id); if (length < 24) // Header Size { @@ -372,7 +428,25 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { - return _ids; + int numTimeZoneIDs = 0; + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + numTimeZoneIDs++; + } + } + string[] nonBackwardsTZIDs = new string[numTimeZoneIDs]; + var index = 0; + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + nonBackwardsTZIDs[index] = _ids[i]; + index++; + } + } + return nonBackwardsTZIDs; } public string GetTimeZoneDirectory() diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index bc7859c0d18d9..12a2dce1d7258 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -11,6 +11,8 @@ using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + #if TARGET_64BIT using nuint_t = System.UInt64; #else diff --git a/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx b/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx index b1fd067338933..f772c16d39646 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx +++ b/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx @@ -417,9 +417,6 @@ An internal error has occurred. No conversion is possible to '{0}' - error generating code for serialization. - - Collection type '{0}' doesn't have default constructor. - No get method for property '{1}' in type '{0}'. @@ -1137,9 +1134,6 @@ The implementation of the function requires System.Runtime.Serialization.SchemaImporter which is not supported on this platform. - - The canonicalization process is not supported on this platform. - Factory type '{0}' for ISerializable type '{1}' must also be ISerializable. @@ -1155,9 +1149,6 @@ The inclusive namespace prefix collection cannot contain null as one of the items. - - Failed to create Delegate for method '{0}' of type '{1}'. - Cannot set option twice. diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx index 3d23d9c39e926..debf029624848 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx @@ -123,21 +123,6 @@ Invalid argument: {0} can not be null and must have a length - - CoreObject Error binding: {0} - - - Error releasing object {0} - - - HostObject Error binding: {0} - - - JSObject Error binding: {0} - - - Multiple handles pointing at jsId: {0} - System.Private.Runtime.InteropServices.JavaScript is not supported on this platform. @@ -150,7 +135,4 @@ Unable to cast object of type {0} to type {1}. - - ValueType arguments are not supported. - \ No newline at end of file diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs index c9b443e9c82ce..d31f1543ce76b 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs @@ -48,7 +48,7 @@ internal void AddInFlight() InFlightCounter++; if (InFlightCounter == 1) { - Debug.Assert(InFlight == null); + Debug.Assert(InFlight == null, "InFlight == null"); InFlight = GCHandle.Alloc(this, GCHandleType.Normal); } } @@ -61,12 +61,12 @@ internal void ReleaseInFlight() { lock (this) { - Debug.Assert(InFlightCounter != 0); + Debug.Assert(InFlightCounter != 0, "InFlightCounter != 0"); InFlightCounter--; if (InFlightCounter == 0) { - Debug.Assert(InFlight.HasValue); + Debug.Assert(InFlight.HasValue, "InFlight.HasValue"); InFlight.Value.Free(); InFlight = null; } diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs index 60f694e2b7cf3..4b5d072e8ac43 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs @@ -49,14 +49,15 @@ private struct IntPtrAndHandle internal IntPtr ptr; [FieldOffset(0)] - internal RuntimeMethodHandle handle; + internal RuntimeMethodHandle methodHandle; [FieldOffset(0)] internal RuntimeTypeHandle typeHandle; } // see src/mono/wasm/driver.c MARSHAL_TYPE_xxx - public enum MarshalType : int { + public enum MarshalType : int + { NULL = 0, INT = 1, FP64 = 2, @@ -90,7 +91,8 @@ public enum MarshalType : int { } // see src/mono/wasm/driver.c MARSHAL_ERROR_xxx - public enum MarshalError : int { + public enum MarshalError : int + { BUFFER_TOO_SMALL = 512, NULL_CLASS_POINTER = 513, NULL_TYPE_POINTER = 514, @@ -98,13 +100,12 @@ public enum MarshalError : int { FIRST = BUFFER_TOO_SMALL } - public static string GetCallSignature(IntPtr methodHandle, object objForRuntimeType) + public static string GetCallSignature(IntPtr _methodHandle, object? objForRuntimeType) { - IntPtrAndHandle tmp = default(IntPtrAndHandle); - tmp.ptr = methodHandle; + var methodHandle = GetMethodHandleFromIntPtr(_methodHandle); - MethodBase? mb = objForRuntimeType == null ? MethodBase.GetMethodFromHandle(tmp.handle) : MethodBase.GetMethodFromHandle(tmp.handle, Type.GetTypeHandle(objForRuntimeType)); - if (mb == null) + MethodBase? mb = objForRuntimeType is null ? MethodBase.GetMethodFromHandle(methodHandle) : MethodBase.GetMethodFromHandle(methodHandle, Type.GetTypeHandle(objForRuntimeType)); + if (mb is null) return string.Empty; ParameterInfo[] parms = mb.GetParameters(); @@ -112,66 +113,163 @@ public static string GetCallSignature(IntPtr methodHandle, object objForRuntimeT if (parmsLength == 0) return string.Empty; - char[] res = new char[parmsLength]; + var result = new char[parmsLength]; + for (int i = 0; i < parmsLength; i++) + { + Type t = parms[i].ParameterType; + var mt = GetMarshalTypeFromType(t); + result[i] = GetCallSignatureCharacterForMarshalType(mt, null); + } + + return new string(result); + } + + private static RuntimeMethodHandle GetMethodHandleFromIntPtr(IntPtr ptr) + { + var temp = new IntPtrAndHandle { ptr = ptr }; + return temp.methodHandle; + } + + private static RuntimeTypeHandle GetTypeHandleFromIntPtr(IntPtr ptr) + { + var temp = new IntPtrAndHandle { ptr = ptr }; + return temp.typeHandle; + } + + internal static MarshalType GetMarshalTypeFromType(Type? type) + { + if (type is null) + return MarshalType.VOID; - for (int c = 0; c < parmsLength; c++) + var typeCode = Type.GetTypeCode(type); + if (type.IsEnum) { - Type t = parms[c].ParameterType; - switch (Type.GetTypeCode(t)) + switch (typeCode) + { + case TypeCode.Int32: + case TypeCode.UInt32: + return MarshalType.ENUM; + case TypeCode.Int64: + case TypeCode.UInt64: + return MarshalType.ENUM64; + default: + throw new JSException($"Unsupported enum underlying type {typeCode}"); + } + } + + switch (typeCode) + { + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + return MarshalType.INT; + case TypeCode.UInt32: + return MarshalType.UINT32; + case TypeCode.Boolean: + return MarshalType.BOOL; + case TypeCode.Int64: + return MarshalType.INT64; + case TypeCode.UInt64: + return MarshalType.UINT64; + case TypeCode.Single: + return MarshalType.FP32; + case TypeCode.Double: + return MarshalType.FP64; + case TypeCode.String: + return MarshalType.STRING; + case TypeCode.Char: + return MarshalType.CHAR; + } + + if (type.IsArray) + { + if (!type.IsSZArray) + throw new JSException("Only single-dimensional arrays with a zero lower bound can be marshaled to JS"); + + var elementType = type.GetElementType(); + switch (Type.GetTypeCode(elementType)) { case TypeCode.Byte: + return MarshalType.ARRAY_UBYTE; case TypeCode.SByte: + return MarshalType.ARRAY_BYTE; case TypeCode.Int16: + return MarshalType.ARRAY_SHORT; case TypeCode.UInt16: + return MarshalType.ARRAY_USHORT; case TypeCode.Int32: + return MarshalType.ARRAY_INT; case TypeCode.UInt32: - case TypeCode.Boolean: - // Enums types have the same code as their underlying numeric types - if (t.IsEnum) - res[c] = 'j'; - else - res[c] = 'i'; - break; - case TypeCode.Int64: - case TypeCode.UInt64: - // Enums types have the same code as their underlying numeric types - if (t.IsEnum) - res[c] = 'k'; - else - res[c] = 'l'; - break; + return MarshalType.ARRAY_UINT; case TypeCode.Single: - res[c] = 'f'; - break; + return MarshalType.ARRAY_FLOAT; case TypeCode.Double: - res[c] = 'd'; - break; - case TypeCode.String: - res[c] = 's'; - break; + return MarshalType.ARRAY_DOUBLE; default: - if (t == typeof(IntPtr)) - { - res[c] = 'i'; - } - else if (t == typeof(Uri)) - { - res[c] = 'u'; - } - else if (t == typeof(SafeHandle)) - { - res[c] = 'h'; - } - else - { - if (t.IsValueType) - throw new NotSupportedException(SR.ValueTypeNotSupported); - res[c] = 'o'; - } - break; + throw new JSException($"Unsupported array element type {elementType}"); } } - return new string(res); + else if (type == typeof(IntPtr)) + return MarshalType.POINTER; + else if (type == typeof(UIntPtr)) + return MarshalType.POINTER; + else if (type == typeof(SafeHandle)) + return MarshalType.SAFEHANDLE; + else if (typeof(Delegate).IsAssignableFrom(type)) + return MarshalType.DELEGATE; + else if ((type == typeof(Task)) || typeof(Task).IsAssignableFrom(type)) + return MarshalType.TASK; + else if (typeof(Uri) == type) + return MarshalType.URI; + else if (type.IsPointer) + return MarshalType.POINTER; + + if (type.IsValueType) + return MarshalType.VT; + else + return MarshalType.OBJECT; + } + + internal static char GetCallSignatureCharacterForMarshalType(MarshalType t, char? defaultValue) + { + switch (t) + { + case MarshalType.BOOL: + case MarshalType.INT: + case MarshalType.UINT32: + case MarshalType.POINTER: + return 'i'; + case MarshalType.UINT64: + case MarshalType.INT64: + return 'l'; + case MarshalType.FP32: + return 'f'; + case MarshalType.FP64: + return 'd'; + case MarshalType.STRING: + return 's'; + case MarshalType.URI: + return 'u'; + case MarshalType.SAFEHANDLE: + return 'h'; + case MarshalType.ENUM: + return 'j'; + case MarshalType.ENUM64: + return 'k'; + case MarshalType.TASK: + case MarshalType.DELEGATE: + case MarshalType.OBJECT: + return 'o'; + case MarshalType.VT: + return 'a'; + default: + if (defaultValue.HasValue) + return defaultValue.Value; + else + throw new JSException($"Unsupported marshal type {t}"); + } } /// diff --git a/src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs index 2656fe960b708..ca302b4be1c1c 100644 --- a/src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs +++ b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs @@ -546,13 +546,13 @@ public static void TestCompare() int i; i = Uri.Compare(uri1, uri2, UriComponents.AbsoluteUri, UriFormat.UriEscaped, StringComparison.CurrentCulture); - Assert.Equal(i, -1); + Assert.Equal(-1, i); i = Uri.Compare(uri1, uri2, UriComponents.Query, UriFormat.UriEscaped, StringComparison.CurrentCulture); Assert.Equal(0, i); i = Uri.Compare(uri1, uri2, UriComponents.Query | UriComponents.Fragment, UriFormat.UriEscaped, StringComparison.CurrentCulture); - Assert.Equal(i, -1); + Assert.Equal(-1, i); Assert.False(uri1.Equals(uri2)); diff --git a/src/libraries/System.Private.Xml.Linq/src/Resources/Strings.resx b/src/libraries/System.Private.Xml.Linq/src/Resources/Strings.resx index 6b427d8b7a9af..0f1c99d02d250 100644 --- a/src/libraries/System.Private.Xml.Linq/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Xml.Linq/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -75,9 +76,6 @@ '{0}' is an invalid name for a processing instruction. - - '{0}' is an invalid prefix. - The argument must be derived from {0}. diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs index 283b42a82e6cd..311a4855daa3e 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs @@ -478,8 +478,7 @@ public XNamespace GetDefaultNamespace() /// An for the namespace bound to the prefix public XNamespace? GetNamespaceOfPrefix(string prefix) { - if (prefix == null) throw new ArgumentNullException(nameof(prefix)); - if (prefix.Length == 0) throw new ArgumentException(SR.Format(SR.Argument_InvalidPrefix, prefix)); + ArgumentException.ThrowIfNullOrEmpty(prefix); if (prefix == "xmlns") return XNamespace.Xmlns; string? namespaceName = GetNamespaceOfPrefixInScope(prefix, null); if (namespaceName != null) return XNamespace.Get(namespaceName); diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs index 15d3987286556..1b673a0026bfd 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs @@ -71,8 +71,7 @@ public override string ToString() /// public static XName Get(string expandedName) { - if (expandedName == null) throw new ArgumentNullException(nameof(expandedName)); - if (expandedName.Length == 0) throw new ArgumentException(SR.Format(SR.Argument_InvalidExpandedName, expandedName)); + ArgumentException.ThrowIfNullOrEmpty(expandedName); if (expandedName[0] == '{') { int i = expandedName.LastIndexOf('}'); diff --git a/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMElement.cs b/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMElement.cs index 2a33a1a0b29b9..c09c64b9eeafb 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMElement.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMElement.cs @@ -784,7 +784,7 @@ public void ElementGetNamespaceOfPrefix() XElement e = new XElement(ns + "foo"); Assert.Throws(() => e.GetNamespaceOfPrefix(null)); - AssertExtensions.Throws(null, () => e.GetNamespaceOfPrefix(string.Empty)); + AssertExtensions.Throws("prefix", () => e.GetNamespaceOfPrefix(string.Empty)); XNamespace n = e.GetNamespaceOfPrefix("xmlns"); Assert.Equal("http://www.w3.org/2000/xmlns/", n.NamespaceName); diff --git a/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMXName.cs b/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMXName.cs index bee81c2d7aff1..a8ff672775032 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMXName.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/SDMSample/SDMXName.cs @@ -29,7 +29,7 @@ public void NameGetInvalid() Assert.Throws(() => XName.Get(null)); Assert.Throws(() => XName.Get(null, "foo")); Assert.Throws(() => XName.Get(string.Empty, "foo")); - AssertExtensions.Throws(null, () => XName.Get(string.Empty)); + AssertExtensions.Throws("expandedName", () => XName.Get(string.Empty)); AssertExtensions.Throws(null, () => XName.Get("{}")); AssertExtensions.Throws(null, () => XName.Get("{foo}")); } diff --git a/src/libraries/System.Private.Xml.Linq/tests/Streaming/StreamingOutput.cs b/src/libraries/System.Private.Xml.Linq/tests/Streaming/StreamingOutput.cs index 2086d14b9dba8..f3c4a8e094667 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/Streaming/StreamingOutput.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/Streaming/StreamingOutput.cs @@ -60,7 +60,7 @@ public void XNameAsNullConstructor() [Fact] public void XNameAsEmptyStringConstructor() { - AssertExtensions.Throws(null, () => new XStreamingElement(string.Empty)); + AssertExtensions.Throws("expandedName", () => new XStreamingElement(string.Empty)); Assert.Throws(() => new XStreamingElement(" ")); } diff --git a/src/libraries/System.Private.Xml.Linq/tests/axes/InvalidParamValidation.cs b/src/libraries/System.Private.Xml.Linq/tests/axes/InvalidParamValidation.cs index e9e11ef002901..953e692c6ca1c 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/axes/InvalidParamValidation.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/axes/InvalidParamValidation.cs @@ -50,9 +50,9 @@ public static void NullXNameTestAttributes() public static void InvalidXNameTest() { Assert.Throws(() => { TestData.GetDocumentWithContacts().Root.Attribute("*&^%_#@!"); }); - AssertExtensions.Throws(null, () => { TestData.GetDocumentWithContacts().Root.Attribute(""); }); + AssertExtensions.Throws("expandedName", () => { TestData.GetDocumentWithContacts().Root.Attribute(""); }); Assert.Throws(() => { TestData.GetDocumentWithContacts().Root.Attributes("*&^%_#@!"); }); - AssertExtensions.Throws(null, () => { TestData.GetDocumentWithContacts().Root.Attributes(""); }); + AssertExtensions.Throws("expandedName", () => { TestData.GetDocumentWithContacts().Root.Attributes(""); }); } } diff --git a/src/libraries/System.Private.Xml/src/Resources/Strings.resx b/src/libraries/System.Private.Xml/src/Resources/Strings.resx index 112359dfecba8..f9f838382dcbd 100644 --- a/src/libraries/System.Private.Xml/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Xml/src/Resources/Strings.resx @@ -390,9 +390,6 @@ The buffer is not large enough to fit a surrogate pair. Please provide a buffer of size at least 2 characters. - - The URL cannot be empty. - Unexpected node type {0}. {1} method can only be called on elements with simple or empty content. @@ -2829,9 +2826,6 @@ Only TypeKind.Root can be set for typeof(object) which is never value type. - - Internal error: deserialization failed to advance over underlying stream. - Invalid byte was found at index {0}. @@ -2844,9 +2838,6 @@ Type is incompatible. - - Cannot open '{0}'. The Uri parameter must be a file system relative or absolute path. - --- End of inner exception stack trace --- @@ -3126,9 +3117,6 @@ Stylesheet or function parameter '{0}' cannot have attribute 'tunnel'. - - The 'required' attribute must not be specified for parameter '{0}'. Function parameters are always mandatory. - Value '#default' is used within the 'exclude-result-prefixes' attribute and the parent element of this attribute has no default namespace. @@ -3306,9 +3294,6 @@ Cannot find the script or external object that implements prefix '{0}'. - - Namespace '{0}' has a duplicate implementation. - The 'msxsl:script' element cannot be empty. @@ -3345,9 +3330,6 @@ Array of type {0} is not supported. - - Type '{0}' cannot be serialized by XmlSerializer, serialization code for the type is missing. Consult the SDK documentation for adding it as a root serialization type. https://go.microsoft.com/fwlink/?LinkId=613136 - Uppercase-First sorting option is not supported. @@ -3444,15 +3426,9 @@ Usage: dotnet {0} [--assembly <assembly file path>] [--type <type name& {0}|{1} Show help. - - If you would like more help, please type "sgen {0}". - Method 'System.Xml.Serialization.XmlSerializer.GenerateSerializer' was not found. This is likely because you are using an older version of the framework. Please update to .NET Core v2.1 or later. - - Pre-generated serializer '{0}' has expired. You need to re-generate serializer for '{1}' - Compiling JScript/CSharp scripts is not supported diff --git a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs index 074f795ea54c0..33d1e3dff11c2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs @@ -59,7 +59,7 @@ private enum ScanState }; // Note: also used by XmlBinaryWriter - internal struct QName + internal struct QName : IEquatable { public string prefix; public string localname; @@ -95,45 +95,26 @@ public void CheckPrefixNS(string prefix, string namespaceUri) throw new XmlException(SR.XmlBinary_NoRemapPrefix, new string[] { prefix, this.namespaceUri, namespaceUri }); } - public override int GetHashCode() - { - return this.prefix.GetHashCode() ^ this.localname.GetHashCode(); - } + public int GetNSHashCode() => + HashCode.Combine(this.namespaceUri, this.localname); - public int GetNSHashCode() - { - return HashCode.Combine(this.namespaceUri, this.localname); - } + public override int GetHashCode() => + this.prefix.GetHashCode() ^ this.localname.GetHashCode(); + public override bool Equals([NotNullWhen(true)] object? other) => + other is QName qname && Equals(qname); - public override bool Equals([NotNullWhen(true)] object? other) - { - if (other is QName that) - { - return this == that; - } - return false; - } + public bool Equals(QName other) => + prefix == other.prefix && + localname == other.localname && + namespaceUri == other.namespaceUri; - public override string ToString() - { - if (prefix.Length == 0) - return this.localname; - else - return $"{this.prefix}:{this.localname}"; - } + public static bool operator ==(QName a, QName b) => a.Equals(b); - public static bool operator ==(QName a, QName b) - { - return ((a.prefix == b.prefix) - && (a.localname == b.localname) - && (a.namespaceUri == b.namespaceUri)); - } + public static bool operator !=(QName a, QName b) => !a.Equals(b); - public static bool operator !=(QName a, QName b) - { - return !(a == b); - } + public override string ToString() => + prefix.Length == 0 ? localname : $"{this.prefix}:{this.localname}"; }; private struct ElemInfo diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReader.cs index c6a6c1ce3e32f..b0e5d48b2d696 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReader.cs @@ -81,7 +81,9 @@ public abstract partial class XmlReader : IDisposable internal const int BiggerBufferSize = 8192; internal const int MaxStreamLengthForDefaultBufferSize = 64 * 1024; // 64kB - internal const int AsyncBufferSize = 64 * 1024; //64KB + // Chosen to be small enough that the character buffer in XmlTextReader when using Async = true + // is not allocated on the Large Object Heap (LOH) + internal const int AsyncBufferSize = 32 * 1024; // Settings public virtual XmlReaderSettings? Settings => null; @@ -1633,12 +1635,7 @@ internal static ConformanceLevel GetV1ConformanceLevel(XmlReader reader) // Creates an XmlReader for parsing XML from the given Uri. public static XmlReader Create(string inputUri) { - ArgumentNullException.ThrowIfNull(inputUri); - - if (inputUri.Length == 0) - { - throw new ArgumentException(SR.XmlConvert_BadUri, nameof(inputUri)); - } + ArgumentException.ThrowIfNullOrEmpty(inputUri); // Avoid using XmlReader.Create(string, XmlReaderSettings), as it references a lot of types // that then can't be trimmed away. diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs index 1a7723bc697ab..68adf4d128807 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs @@ -318,12 +318,7 @@ public XmlReaderSettings Clone() internal XmlReader CreateReader(string inputUri, XmlParserContext? inputContext) { - ArgumentNullException.ThrowIfNull(inputUri); - - if (inputUri.Length == 0) - { - throw new ArgumentException(SR.XmlConvert_BadUri, nameof(inputUri)); - } + ArgumentException.ThrowIfNullOrEmpty(inputUri); // resolve and open the url XmlResolver tmpResolver = GetXmlResolver() ?? new XmlUrlResolver(); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs index 6c7614308a93d..2222a29d20685 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs @@ -567,15 +567,7 @@ internal XmlTextReaderImpl(string xmlFragment, XmlParserContext? context) public XmlTextReaderImpl(string url, XmlNameTable nt) : this(nt) { - if (url == null) - { - throw new ArgumentNullException(nameof(url)); - } - - if (url.Length == 0) - { - throw new ArgumentException(SR.Xml_EmptyUrl, nameof(url)); - } + ArgumentException.ThrowIfNullOrEmpty(url); _namespaceManager = new XmlNamespaceManager(nt); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs index 7f2e13f22e52e..ed42e646f8df2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs @@ -755,7 +755,7 @@ public static string ToString(DateTime value) return ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz"); } - public static string ToString(DateTime value, string format) + public static string ToString(DateTime value, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format) { return value.ToString(format, DateTimeFormatInfo.InvariantInfo); } @@ -793,7 +793,7 @@ public static string ToString(DateTimeOffset value) return xsdDateTime.ToString(); } - public static string ToString(DateTimeOffset value, string format) + public static string ToString(DateTimeOffset value, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format) { return value.ToString(format, DateTimeFormatInfo.InvariantInfo); } @@ -1250,12 +1250,12 @@ public static DateTime ToDateTime(string s) return ToDateTime(s, AllDateTimeFormats); } - public static DateTime ToDateTime(string s, string format) + public static DateTime ToDateTime(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format) { return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite); } - public static DateTime ToDateTime(string s, string[] formats) + public static DateTime ToDateTime(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats) { return DateTime.ParseExact(s, formats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite); } @@ -1299,7 +1299,7 @@ public static DateTimeOffset ToDateTimeOffset(string s) return dateTimeOffset; } - public static DateTimeOffset ToDateTimeOffset(string s, string format) + public static DateTimeOffset ToDateTimeOffset(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string format) { if (s == null) { @@ -1308,7 +1308,7 @@ public static DateTimeOffset ToDateTimeOffset(string s, string format) return DateTimeOffset.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite); } - public static DateTimeOffset ToDateTimeOffset(string s, string[] formats) + public static DateTimeOffset ToDateTimeOffset(string s, [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string[] formats) { if (s == null) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs index 8e3e1a4b841a7..33b4fe98b3f92 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs @@ -7,49 +7,34 @@ namespace System.Xml.Xsl { - internal struct Int32Pair + internal readonly struct Int32Pair : IEquatable { - private readonly int _left; - private readonly int _right; - public Int32Pair(int left, int right) { - _left = left; - _right = right; + Left = left; + Right = right; } - public int Left { get { return _left; } } - public int Right { get { return _right; } } + public int Left { get; } + public int Right { get; } - public override bool Equals([NotNullWhen(true)] object? other) - { - if (other is Int32Pair) - { - Int32Pair o = (Int32Pair)other; - return _left == o._left && _right == o._right; - } + public override bool Equals([NotNullWhen(true)] object? other) => + other is Int32Pair o && Equals(o); - return false; - } + public bool Equals(Int32Pair other) => Left == other.Left && Right == other.Right; - public override int GetHashCode() - { - return _left.GetHashCode() ^ _right.GetHashCode(); - } + public override int GetHashCode() => Left.GetHashCode() ^ Right.GetHashCode(); } - internal struct StringPair + internal readonly struct StringPair { - private readonly string _left; - private readonly string _right; - public StringPair(string left, string right) { - _left = left; - _right = right; + Left = left; + Right = right; } - public string Left { get { return _left; } } - public string Right { get { return _right; } } + public string Left { get; } + public string Right { get; } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs index 1046765a2d3b2..a95ce13c1737c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs @@ -11,7 +11,7 @@ namespace System.Xml.Xsl /// Cardinality of part of XmlQueryType /// struct is being used because enum doesn't allow members /// - internal struct XmlQueryCardinality + internal readonly struct XmlQueryCardinality : IEquatable { private readonly int _value; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs index 6df66d73c106e..4b4a5c508615f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs @@ -1055,8 +1055,6 @@ private QilNode CompileAvt(string source) return result; } - private static readonly char[] s_curlyBraces = { '{', '}' }; - [return: NotNullIfNotNull("avt")] private QilNode? CompileStringAvt(string? avt) { @@ -1064,7 +1062,7 @@ private QilNode CompileAvt(string source) { return null; } - if (avt.IndexOfAny(s_curlyBraces) == -1) + if (avt.AsSpan().IndexOfAny('{', '}') < 0) { return _f.String(avt); } @@ -1074,7 +1072,7 @@ private QilNode CompileAvt(string source) private QilNode CompileTextAvt(string avt) { Debug.Assert(avt != null); - if (avt.IndexOfAny(s_curlyBraces) == -1) + if (avt.AsSpan().IndexOfAny('{', '}') < 0) { return _f.TextCtor(_f.String(avt)); } diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs index cb50258f7fa27..592f6254d8c51 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs +++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs @@ -58,12 +58,12 @@ public static void Xml_ByteArrayNull() [Fact] public static void Xml_CharAsRoot() { - Assert.StrictEqual(SerializeAndDeserialize(char.MinValue, + Assert.StrictEqual(char.MinValue, SerializeAndDeserialize(char.MinValue, @" -0"), char.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(char.MaxValue, +0")); + Assert.StrictEqual(char.MaxValue, SerializeAndDeserialize(char.MaxValue, @" -65535"), char.MaxValue); +65535")); Assert.StrictEqual('a', SerializeAndDeserialize('a', @" 97")); @@ -81,12 +81,12 @@ public static void Xml_ByteAsRoot() Assert.StrictEqual(10, SerializeAndDeserialize(10, @" 10")); - Assert.StrictEqual(SerializeAndDeserialize(byte.MinValue, + Assert.StrictEqual(byte.MinValue, SerializeAndDeserialize(byte.MinValue, @" -0"), byte.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(byte.MaxValue, +0")); + Assert.StrictEqual(byte.MaxValue, SerializeAndDeserialize(byte.MaxValue, @" -255"), byte.MaxValue); +255")); } [Fact] @@ -128,46 +128,46 @@ public static void Xml_DecimalAsRoot() [Fact] public static void Xml_DoubleAsRoot() { - Assert.StrictEqual(SerializeAndDeserialize(-1.2, + Assert.StrictEqual(-1.2, SerializeAndDeserialize(-1.2, @" --1.2"), -1.2); +-1.2")); Assert.StrictEqual(0, SerializeAndDeserialize(0, @" 0")); Assert.StrictEqual(2.3, SerializeAndDeserialize(2.3, @" 2.3")); - Assert.StrictEqual(SerializeAndDeserialize(double.MinValue, + Assert.StrictEqual(double.MinValue, SerializeAndDeserialize(double.MinValue, @" --1.7976931348623157E+308"), double.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(double.MaxValue, +-1.7976931348623157E+308")); + Assert.StrictEqual(double.MaxValue, SerializeAndDeserialize(double.MaxValue, @" -1.7976931348623157E+308"), double.MaxValue); +1.7976931348623157E+308")); } [Fact] public static void Xml_FloatAsRoot() { - Assert.StrictEqual(SerializeAndDeserialize((float)-1.2, + Assert.StrictEqual((float)-1.2, SerializeAndDeserialize((float)-1.2, @" --1.2"), (float)-1.2); - Assert.StrictEqual(SerializeAndDeserialize((float)0, +-1.2")); + Assert.StrictEqual((float)0, SerializeAndDeserialize((float)0, @" -0"), (float)0); - Assert.StrictEqual(SerializeAndDeserialize((float)2.3, +0")); + Assert.StrictEqual((float)2.3, SerializeAndDeserialize((float)2.3, @" -2.3"), (float)2.3); +2.3")); } [Fact] public static void Xml_FloatAsRoot_NotNetFramework() { - Assert.StrictEqual(SerializeAndDeserialize(float.MinValue, + Assert.StrictEqual(float.MinValue, SerializeAndDeserialize(float.MinValue, @" --3.4028235E+38"), float.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(float.MaxValue, +-3.4028235E+38")); + Assert.StrictEqual(float.MaxValue, SerializeAndDeserialize(float.MaxValue, @" -3.4028235E+38"), float.MaxValue); +3.4028235E+38")); } [Fact] @@ -229,8 +229,8 @@ public static void Xml_XmlQualifiedNameAsRoot() Assert.StrictEqual(SerializeAndDeserialize(new XmlQualifiedName("abc", "def"), @" q1:abc"), new XmlQualifiedName("abc", "def")); - Assert.StrictEqual(SerializeAndDeserialize(XmlQualifiedName.Empty, -@""), XmlQualifiedName.Empty); + Assert.StrictEqual(XmlQualifiedName.Empty, SerializeAndDeserialize(XmlQualifiedName.Empty, +@"")); } [Fact] diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs index 9f561b2554e00..6c320a7295bcd 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs @@ -1234,7 +1234,7 @@ public void LoadGeneric12(InputType inputType, ReaderType readerType, TransformT } catch (System.InvalidOperationException e2) { - CheckExpectedError(e2, "system.xml", "Xslt_NoStylesheetLoaded", new string[] { "IDontExist.xsl" }); + CheckExpectedError(e2, "system.xml", "Xslt_NoStylesheetLoaded", new string[] { "" }); return; } } diff --git a/src/libraries/System.Reflection.Context/src/Resources/Strings.resx b/src/libraries/System.Reflection.Context/src/Resources/Strings.resx index faa2e9cbb08c0..3b0d6ec30a2a6 100644 --- a/src/libraries/System.Reflection.Context/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Context/src/Resources/Strings.resx @@ -66,9 +66,6 @@ The property type needs to be mapped to the current ReflectionContext. - - The set accessor of the property was not found. - Duplicate AttributeUsageAttribute records found on attribute type {0}. diff --git a/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderByRefs.cs b/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderByRefs.cs new file mode 100644 index 0000000000000..01baa3bc010d9 --- /dev/null +++ b/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderByRefs.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using Xunit; + +namespace System.Reflection.Emit.Tests +{ + public class MethodBuilderByRefs + { + [Fact] + public void ByRef_Ldtoken() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("TestMethod", MethodAttributes.Public, typeof(Type), Type.EmptyTypes); + ILGenerator ilg = method.GetILGenerator(); + ilg.Emit(OpCodes.Ldtoken, typeof(int).MakeByRefType()); + ilg.Emit(OpCodes.Ret); + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs index 34433ae11f391..e1d927cfa25b0 100644 --- a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs +++ b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs @@ -160,11 +160,11 @@ public void DefineEnum_VoidUnderlyingType_ThrowsArgumentException() } [Fact] - public void DefineEnum_ByRefUnderlyingType_ThrowsCOMExceptionOnCreation() + public void DefineEnum_ByRefUnderlyingType_ThrowsTypeLoadExceptionOnCreation() { ModuleBuilder module = Helpers.DynamicModule(); EnumBuilder enumBuilder = module.DefineEnum("Name", TypeAttributes.Public, typeof(int).MakeByRefType()); - Assert.Throws(() => enumBuilder.CreateTypeInfo()); + Assert.Throws(() => enumBuilder.CreateTypeInfo()); } [Theory] diff --git a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineInitializedData.cs b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineInitializedData.cs index 77ecb3b5ad60a..178667241fdd6 100644 --- a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineInitializedData.cs +++ b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineInitializedData.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Runtime.InteropServices; namespace System.Reflection.Emit.Tests { @@ -59,5 +60,59 @@ public void DefineInitializedData_CreateGlobalFunctionsCalled_ThrowsInvalidOpera module.CreateGlobalFunctions(); Assert.Throws(() => module.DefineInitializedData("MyField2", new byte[] { 1, 0, 1 }, FieldAttributes.Public)); } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] + public void DefineInitializedData_EnsureAlignmentIsMinimumNeededForUseOfCreateSpan() + { + ModuleBuilder module = Helpers.DynamicModule(); + + // Create static field data in a variety of orders that requires the runtime to actively apply alignment + // RuntimeHelpers.CreateSpan requires data to be naturally aligned within the "PE" file. At this time CreateSpan only + // requires alignments up to 8 bytes. + FieldBuilder field1Byte = module.DefineInitializedData("Field1Byte", new byte[] { 1 }, FieldAttributes.Public); + byte[] field4Byte_1_data = new byte[] { 1, 2, 3, 4 }; + byte[] field8Byte_1_data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; + byte[] field4Byte_2_data = new byte[] { 5, 6, 7, 8 }; + byte[] field8Byte_2_data = new byte[] { 9, 10, 11, 12, 13, 14, 15, 16 }; + FieldBuilder field4Byte_1 = module.DefineInitializedData("Field4Bytes_1", field4Byte_1_data, FieldAttributes.Public); + FieldBuilder field8Byte_1 = module.DefineInitializedData("Field8Bytes_1", field8Byte_1_data, FieldAttributes.Public); + FieldBuilder field4Byte_2 = module.DefineInitializedData("Field4Bytes_2", field4Byte_2_data, FieldAttributes.Public); + FieldBuilder field8Byte_2 = module.DefineInitializedData("Field8Bytes_2", field8Byte_2_data, FieldAttributes.Public); + module.CreateGlobalFunctions(); + + var checkTypeBuilder = module.DefineType("CheckType", TypeAttributes.Public); + CreateLoadAddressMethod("LoadAddress1", field1Byte); + CreateLoadAddressMethod("LoadAddress4_1", field4Byte_1); + CreateLoadAddressMethod("LoadAddress4_2", field4Byte_2); + CreateLoadAddressMethod("LoadAddress8_1", field8Byte_1); + CreateLoadAddressMethod("LoadAddress8_2", field8Byte_2); + + var checkType = checkTypeBuilder.CreateType(); + + CheckMethod("LoadAddress4_1", 4, field4Byte_1_data); + CheckMethod("LoadAddress4_2", 4, field4Byte_2_data); + CheckMethod("LoadAddress8_1", 8, field8Byte_1_data); + CheckMethod("LoadAddress8_2", 8, field8Byte_2_data); + + void CreateLoadAddressMethod(string name, FieldBuilder fieldBuilder) + { + var loadAddressMethod = checkTypeBuilder.DefineMethod(name, MethodAttributes.Public | MethodAttributes.Static, typeof(IntPtr), null); + var methodIL = loadAddressMethod.GetILGenerator(); + methodIL.Emit(OpCodes.Ldsflda, fieldBuilder); + methodIL.Emit(OpCodes.Ret); + } + + void CheckMethod(string name, int minAlignmentRequired, byte[] dataToVerify) + { + var methodToCall = checkType.GetMethod(name); + nint address = (nint)methodToCall.Invoke(null, null); + + for (int i = 0; i < dataToVerify.Length; i++) + { + Assert.Equal(dataToVerify[i], Marshal.ReadByte(address + (nint)i)); + } + Assert.Equal(name + "_0" + "_" + address.ToString(), name + "_" + (address % minAlignmentRequired).ToString() + "_" + address.ToString()); + } + } } } diff --git a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj index e5d46e991da82..d47bdd3466c79 100644 --- a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj +++ b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj @@ -33,6 +33,7 @@ + diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderAddInterfaceImplementaion.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderAddInterfaceImplementaion.cs index 8d9adab4662e0..da3e695dcd389 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderAddInterfaceImplementaion.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderAddInterfaceImplementaion.cs @@ -61,13 +61,6 @@ public void AddInterfaceImplementation_NullInterfaceType_ThrowsArgumentNullExcep AssertExtensions.Throws("interfaceType", () => type.AddInterfaceImplementation(null)); } - [Fact] - public void AddInterfaceImplementation_ByRefInterfaceType_ThrowsArgumentExceptioN() - { - TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); - AssertExtensions.Throws(null, () => type.AddInterfaceImplementation(typeof(int).MakeByRefType())); - } - [Fact] public void AddInterfaceImplementation_TypeAlreadyCreated_ThrowsInvalidOperationException() { diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineEvent.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineEvent.cs index 2c7452339c9e8..59ebb7fc77bb4 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineEvent.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineEvent.cs @@ -106,11 +106,11 @@ public void DefineEvent_Invalid(string name, Type eventType, Type exceptionType) } [Fact] - public void DefineEvent_ByRefEventType_ThrowsArgumentException() + public void DefineEvent_ByRefEventType() { TypeBuilder type = Helpers.DynamicType(TypeAttributes.Class | TypeAttributes.Public); - - AssertExtensions.Throws(null, () => type.DefineEvent("Name", EventAttributes.None, typeof(int).MakeByRefType())); + type.DefineEvent("Name", EventAttributes.None, typeof(int).MakeByRefType()); + type.CreateTypeInfo().AsType(); } [Fact] diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineField.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineField.cs index e765a08dcc403..a09e69f6738ad 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineField.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineField.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Xunit; @@ -112,15 +113,6 @@ public void DefineField_VoidFieldType_ThrowsArgumentException() AssertExtensions.Throws(null, () => type.DefineField("Name", typeof(void), FieldAttributes.Public)); } - [Fact] - public void DefineField_ByRefFieldType_ThrowsCOMExceptionOnCreation() - { - TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); - type.DefineField("Name", typeof(int).MakeByRefType(), FieldAttributes.Public); - - Assert.Throws(() => type.CreateTypeInfo()); - } - [Theory] [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] [InlineData((FieldAttributes)(-1), (FieldAttributes)(-38145))] @@ -152,6 +144,69 @@ public void DefineField_DynamicFieldTypeNotCreated_ThrowsTypeLoadException() Assert.Equal(createdFieldType, field.FieldType); } + [Fact] + public void DefineByRefField_Class_ThrowsTypeLoadExceptionOnCreation() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + type.DefineField("Name", typeof(int).MakeByRefType(), FieldAttributes.Public); + + Assert.Throws(() => type.CreateTypeInfo()); + } + + [Fact] + public void DefineByRefField_ValueType_NonByRefLike_ThrowsTypeLoadExceptionOnCreation() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public, baseType: typeof(ValueType)); + type.DefineField("Name", typeof(int).MakeByRefType(), FieldAttributes.Public); + + Assert.Throws(() => type.CreateTypeInfo()); + } + + [Fact] + public void DefineByRefField_ValueType_ByRefLike() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public, baseType: typeof(ValueType)); + + // Define type to be ByRefLike + CustomAttributeBuilder ca = new(typeof(IsByRefLikeAttribute).GetConstructors()[0], new object[] { }); + type.SetCustomAttribute(ca); + + type.DefineField("Name", typeof(int).MakeByRefType(), FieldAttributes.Public); + + Type createdType = type.CreateTypeInfo().AsType(); + FieldInfo[] fields = createdType.GetFields(); + Assert.Equal(1, fields.Length); + Assert.True(fields[0].FieldType.IsByRef); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/45152")] + public void Instantiate_ValueType_With_ByRefField() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public, baseType: typeof(ValueType)); + + // Define type to be ByRefLike + CustomAttributeBuilder ca = new(typeof(IsByRefLikeAttribute).GetConstructors()[0], new object[] { }); + type.SetCustomAttribute(ca); + + var field = type.DefineField("Name", typeof(int).MakeByRefType(), FieldAttributes.Public); + + var ctor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(string) }); + { + ILGenerator il = ctor.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarga_S, 1); + il.Emit(OpCodes.Stfld, field); + il.Emit(OpCodes.Ret); + } + + Type createdType = type.CreateTypeInfo().AsType(); + + var ctorToCall = createdType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, new[] { typeof(string) }); + var str = "12345"; + ctorToCall.Invoke(new[] { str }); + } + [Fact] public void GetField_TypeNotCreated_ThrowsNotSupportedException() { diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineNestedType.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineNestedType.cs index cf24e8d87adad..d71506544525d 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineNestedType.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderDefineNestedType.cs @@ -210,15 +210,9 @@ public void DefineNestedType_NullInterface_ThrowsArgumentNullException() AssertExtensions.Throws("interfaces", () => type.DefineNestedType("Name", TypeAttributes.NestedPublic, typeof(object), new Type[] { null })); } - [Fact] - public void DefineNestedType_ByRefInterfaceType_ThrowsArgumentException() - { - TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); - AssertExtensions.Throws(null, () => type.DefineNestedType("Name", TypeAttributes.NestedPublic, typeof(object), new Type[] { typeof(int).MakeByRefType() })); - } - public static IEnumerable InvalidInterfaceType_TestData() { + yield return new object[] { typeof(int).MakeByRefType() }; yield return new object[] { typeof(EmptyNonGenericClass) }; yield return new object[] { typeof(EmptyNonGenericStruct) }; yield return new object[] { typeof(EmptyGenericClass) }; diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderSetParent.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderSetParent.cs index 8a4e5ace9ec8d..5c985d52a4676 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderSetParent.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderSetParent.cs @@ -56,14 +56,14 @@ public void SetParent_InterfaceType_ThrowsArgumentException(TypeAttributes attri } [Fact] - public void SetParent_ByRefType_ThrowsArgumentExceptionOnCreation() + public void SetParent_ByRefType_ThrowsNotSupportedExceptionOnCreation() { TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); type.SetParent(typeof(int).MakeByRefType()); Assert.Equal(typeof(int).MakeByRefType(), type.BaseType); - AssertExtensions.Throws(null, () => type.CreateTypeInfo()); + Assert.Throws(() => type.CreateTypeInfo()); } [Fact] diff --git a/src/libraries/System.Reflection.Emit/tests/Utilities.cs b/src/libraries/System.Reflection.Emit/tests/Utilities.cs index 8e1c965e19a27..1e951be849a86 100644 --- a/src/libraries/System.Reflection.Emit/tests/Utilities.cs +++ b/src/libraries/System.Reflection.Emit/tests/Utilities.cs @@ -54,9 +54,16 @@ public static ModuleBuilder DynamicModule(string assemblyName = "TestAssembly", return DynamicAssembly(assemblyName).DefineDynamicModule(moduleName); } - public static TypeBuilder DynamicType(TypeAttributes attributes, string assemblyName = "TestAssembly", string moduleName = "TestModule", string typeName = "TestType") + public static TypeBuilder DynamicType(TypeAttributes attributes, string assemblyName = "TestAssembly", string moduleName = "TestModule", string typeName = "TestType", Type? baseType = null) { - return DynamicModule(assemblyName, moduleName).DefineType(typeName, attributes); + if (baseType is null) + { + return DynamicModule(assemblyName, moduleName).DefineType(typeName, attributes); + } + else + { + return DynamicModule(assemblyName, moduleName).DefineType(typeName, attributes, baseType); + } } public static EnumBuilder DynamicEnum(TypeAttributes visibility, Type underlyingType, string enumName = "TestEnum", string assemblyName = "TestAssembly", string moduleName = "TestModule") diff --git a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs index 21ee42cf39176..6934766e36392 100644 --- a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs +++ b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs @@ -249,7 +249,7 @@ public void GetRuntimeField() }); - Assert.Throws(null, () => + AssertExtensions.Throws(null, () => { typeof(RuntimeReflectionExtensionsTests).GetRuntimeField(null); }); diff --git a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx index f4a6f03089790..e85eb5e2a3aa9 100644 --- a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx @@ -405,7 +405,4 @@ Unexpected value '{0}' of unknown type. - - This program location is thought to be unreachable. - diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ExceptionUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ExceptionUtilities.cs index 3d6b4605cf492..c0ebc31d376e8 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ExceptionUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ExceptionUtilities.cs @@ -14,8 +14,5 @@ internal static Exception UnexpectedValue(object value) return new InvalidOperationException(SR.Format(SR.UnexpectedValueUnknownType, value)); } - - internal static Exception Unreachable => - new InvalidOperationException(SR.UnreachableLocation); } } diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs index 302a6167c5563..abd9cf514babf 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs @@ -190,7 +190,7 @@ public string GetDocumentName(DocumentNameBlobHandle handle) int separator = blobReader.ReadByte(); if (separator > 0x7f) { - throw new BadImageFormatException(SR.Format(SR.InvalidDocumentName, separator)); + throw new BadImageFormatException(SR.InvalidDocumentName); } var pooledBuilder = PooledStringBuilder.GetInstance(); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs index a4e71b93171a6..6cdac1a324b58 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs @@ -1,6 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.IO.MemoryMappedFiles; +using System.Reflection.PortableExecutable; +using Microsoft.Win32.SafeHandles; + namespace System.Reflection.Metadata { public sealed partial class MetadataReader @@ -8,7 +13,8 @@ public sealed partial class MetadataReader internal AssemblyName GetAssemblyName(StringHandle nameHandle, Version version, StringHandle cultureHandle, BlobHandle publicKeyOrTokenHandle, AssemblyHashAlgorithm assemblyHashAlgorithm, AssemblyFlags flags) { string name = GetString(nameHandle); - string? cultureName = (!cultureHandle.IsNil) ? GetString(cultureHandle) : null; + // compat: normalize 'null' culture name to "" to match AssemblyName.GetAssemblyName() + string cultureName = (!cultureHandle.IsNil) ? GetString(cultureHandle) : ""; var hashAlgorithm = (Configuration.Assemblies.AssemblyHashAlgorithm)assemblyHashAlgorithm; byte[]? publicKeyOrToken = !publicKeyOrTokenHandle.IsNil ? GetBlobBytes(publicKeyOrTokenHandle) : null; @@ -36,6 +42,51 @@ internal AssemblyName GetAssemblyName(StringHandle nameHandle, Version version, return assemblyName; } + internal static unsafe AssemblyName GetAssemblyName(string assemblyFile) + { + if (assemblyFile == null) + throw new ArgumentNullException(nameof(assemblyFile)); + + FileStream? fileStream = null; + MemoryMappedFile? mappedFile = null; + MemoryMappedViewAccessor? accessor = null; + PEReader? peReader = null; + + try + { + try + { + // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict + fileStream = new FileStream(assemblyFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false); + if (fileStream.Length == 0) + { + throw new BadImageFormatException(SR.PEImageDoesNotHaveMetadata, assemblyFile); + } + + mappedFile = MemoryMappedFile.CreateFromFile( + fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); + accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); + + SafeMemoryMappedViewHandle? safeBuffer = accessor.SafeMemoryMappedViewHandle; + peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength); + MetadataReader mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None); + AssemblyName assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName(); + return assemblyName; + } + finally + { + peReader?.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); + } + } + catch (InvalidOperationException ex) + { + throw new BadImageFormatException(ex.Message); + } + } + private AssemblyNameFlags GetAssemblyNameFlags(AssemblyFlags flags) { AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs index 33bd80dec21f7..1762b12d928ba 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs @@ -121,7 +121,7 @@ public ManagedTextSection( public const int MappedFieldDataAlignment = 8; - public int CalculateOffsetToMappedFieldDataStream() + internal int CalculateOffsetToMappedFieldDataStreamUnaligned() { int result = ComputeOffsetToImportTable(); @@ -135,6 +135,16 @@ public int CalculateOffsetToMappedFieldDataStream() return result; } + public int CalculateOffsetToMappedFieldDataStream() + { + int result = CalculateOffsetToMappedFieldDataStreamUnaligned(); + if (MappedFieldDataSize != 0) + { + result = BitArithmetic.Align(result, MappedFieldDataAlignment); + } + return result; + } + internal int ComputeOffsetToDebugDirectory() { Debug.Assert(MetadataSize % 4 == 0); @@ -185,7 +195,7 @@ public int GetEntryPointAddress(int rva) { // TODO: constants return RequiresStartupStub ? - rva + CalculateOffsetToMappedFieldDataStream() - (Is32Bit ? 6 : 10) : + rva + CalculateOffsetToMappedFieldDataStreamUnaligned() - (Is32Bit ? 6 : 10) : 0; } @@ -293,6 +303,8 @@ public void Serialize( // mapped field data: if (mappedFieldDataBuilderOpt != null) { + if (mappedFieldDataBuilderOpt.Count != 0) + builder.Align(MappedFieldDataAlignment); builder.LinkSuffix(mappedFieldDataBuilderOpt); } diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index bba7976b646df..f02b3e292b413 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs @@ -127,7 +127,7 @@ public unsafe void InvalidFindMscorlibAssemblyRefNoProjection() //find index for mscorlib int mscorlibIndex = IndexOf(peImage, Encoding.ASCII.GetBytes("mscorlib"), headers.MetadataStartOffset); - Assert.NotEqual(mscorlibIndex, -1); + Assert.NotEqual(-1, mscorlibIndex); //mutate mscorlib peImage[mscorlibIndex + headers.MetadataStartOffset] = 0xFF; @@ -146,10 +146,10 @@ public unsafe void InvalidStreamHeaderLengths() // mutate CLR to reach MetadataKind.WindowsMetadata // find CLR int clrIndex = IndexOf(peImage, Encoding.ASCII.GetBytes("CLR"), headers.MetadataStartOffset); - Assert.NotEqual(clrIndex, -1); + Assert.NotEqual(-1, clrIndex); //find 5, This is the streamcount and is the last thing that should be read befor the test. int fiveIndex = IndexOf(peImage, new byte[] {5}, headers.MetadataStartOffset + clrIndex); - Assert.NotEqual(fiveIndex, -1); + Assert.NotEqual(-1, fiveIndex); peImage[clrIndex + headers.MetadataStartOffset] = 0xFF; @@ -173,7 +173,7 @@ public unsafe void InvalidSpaceForStreams() //find 5, This is the streamcount we'll change to one to leave out loops. int fiveIndex = IndexOf(peImage, new byte[] { 5 }, headers.MetadataStartOffset); - Assert.NotEqual(fiveIndex, -1); + Assert.NotEqual(-1, fiveIndex); Array.Copy(BitConverter.GetBytes((ushort)1), 0, peImage, fiveIndex + headers.MetadataStartOffset, BitConverter.GetBytes((ushort)1).Length); string[] streamNames= new string[] @@ -206,7 +206,7 @@ public unsafe void InvalidExternalTableMask() //0x900001447 is the external table mask from PortablePdbs.DocumentsPdb int externalTableMaskIndex = IndexOf(peImage, new byte[] { 0x47, 0x14, 0, 0, 9, 0, 0, 0 }, 0); - Assert.NotEqual(externalTableMaskIndex, -1); + Assert.NotEqual(-1, externalTableMaskIndex); Array.Copy(new byte[] { 0x48, 0x14, 0, 0, 9, 0, 0, 0 }, 0, peImage, externalTableMaskIndex, 8); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject(), peImage.Length)); @@ -219,13 +219,13 @@ public unsafe void IsMinimalDelta() GCHandle pinned = GetPinnedPEImage(peImage); //Find COR20Constants.StringStreamName to be changed to COR20Constants.MinimalDeltaMetadataTableStreamName int stringIndex = IndexOf(peImage, Encoding.ASCII.GetBytes(COR20Constants.StringStreamName), 0); - Assert.NotEqual(stringIndex, -1); + Assert.NotEqual(-1, stringIndex); //find remainingBytes to be increased because we are changing to uncompressed int remainingBytesIndex = IndexOf(peImage, BitConverter.GetBytes(180), 0); - Assert.NotEqual(remainingBytesIndex, -1); + Assert.NotEqual(-1, remainingBytesIndex); //find compressed to change to uncompressed int compressedIndex = IndexOf(peImage, Encoding.ASCII.GetBytes(COR20Constants.CompressedMetadataTableStreamName), 0); - Assert.NotEqual(compressedIndex, -1); + Assert.NotEqual(-1, compressedIndex); Array.Copy(Encoding.ASCII.GetBytes(COR20Constants.MinimalDeltaMetadataTableStreamName), 0, peImage, stringIndex, Encoding.ASCII.GetBytes(COR20Constants.MinimalDeltaMetadataTableStreamName).Length); peImage[stringIndex + COR20Constants.MinimalDeltaMetadataTableStreamName.Length] = (byte)0; @@ -248,10 +248,10 @@ public unsafe void InvalidMetaDataTableHeaders() //0x0570 is the remaining bytes from NetModule.AppCS int remainingBytesIndex = IndexOf(peImage, new byte[] { 0x70, 0x05, 0, 0 }, headers.MetadataStartOffset); - Assert.NotEqual(remainingBytesIndex, -1); + Assert.NotEqual(-1, remainingBytesIndex); //0xcc90da21757 is the presentTables from NetModule.AppCS, must be after remainingBytesIndex int presentTablesIndex = IndexOf(peImage, new byte[] { 0x57, 0x17, 0xa2, 0x0d, 0xc9, 0x0c, 0, 0 }, headers.MetadataStartOffset + remainingBytesIndex); - Assert.NotEqual(presentTablesIndex, -1); + Assert.NotEqual(-1, presentTablesIndex); //Set this.ModuleTable.NumberOfRows to 0 Array.Copy(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset + 16, 8); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyDefinitionTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyDefinitionTests.cs index 9b940dcfa4be8..b54b3f855af0b 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyDefinitionTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyDefinitionTests.cs @@ -55,7 +55,7 @@ public void ValidateAssemblyNameWithPublicKey() Assert.Equal(assembly.Version, assemblyName.Version); Assert.Equal(assembly.Name, assemblyName.Name); Assert.Equal(assembly.ContentType, assemblyName.ContentType); - Assert.Null(assemblyName.CultureName); + Assert.Equal("", assemblyName.CultureName); Assert.Equal(Configuration.Assemblies.AssemblyHashAlgorithm.SHA1, assemblyName.HashAlgorithm); Assert.Equal(assembly.Flags, assemblyName.Flags); Assert.NotNull(assemblyName.GetPublicKeyToken()); @@ -94,7 +94,7 @@ public void ValidateAssemblyNameForAssemblyDefinition() Assert.Equal(item.Version, assemblyName.Version); Assert.Equal(item.Name, assemblyName.Name); Assert.Equal(item.ContentType, assemblyName.ContentType); - Assert.Null(assemblyName.CultureName); + Assert.Equal("", assemblyName.CultureName); Assert.Equal(Configuration.Assemblies.AssemblyHashAlgorithm.SHA1, assemblyName.HashAlgorithm); Assert.Null(assemblyName.GetPublicKey()); Assert.Null(assemblyName.GetPublicKeyToken()); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyReferenceTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyReferenceTests.cs index 8da72d74e59ad..801d546722a39 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyReferenceTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/AssemblyReferenceTests.cs @@ -21,7 +21,7 @@ public void ValidateAssemblyNameForSingleAssemblyReference() Assert.Equal("System.Runtime", assemblyName.Name); Assert.Equal(new Version(4, 0, 0, 0), assemblyName.Version); Assert.Equal(new byte[] { 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A }, assemblyName.GetPublicKeyToken()); - Assert.Null(assemblyName.CultureName); + Assert.Equal("",assemblyName.CultureName); Assert.Equal(Configuration.Assemblies.AssemblyHashAlgorithm.None, assemblyName.HashAlgorithm); Assert.Null(assemblyName.GetPublicKey()); Assert.Equal(AssemblyNameFlags.None, assemblyName.Flags); @@ -70,7 +70,7 @@ public void ValidateAssemblyNameForMultipleAssemblyReferences() Assert.Equal(expRefs[i], assemblyName.Name); Assert.Equal(expVers[i], assemblyName.Version); Assert.Equal(expKeys[i], assemblyName.GetPublicKeyToken()); - Assert.Null(assemblyName.CultureName); + Assert.Equal("",assemblyName.CultureName); Assert.Equal(Configuration.Assemblies.AssemblyHashAlgorithm.None, assemblyName.HashAlgorithm); Assert.Null(assemblyName.GetPublicKey()); Assert.Equal(AssemblyNameFlags.None, assemblyName.Flags); diff --git a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs index 763e26dbc1811..c3dab37bbd359 100644 --- a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs @@ -64,7 +64,8 @@ private static void WritePEImage( Blob mvidFixup = default(Blob), byte[] privateKeyOpt = null, bool publicSigned = false, - Machine machine = 0) + Machine machine = 0, + BlobBuilder? mappedFieldData = null) { var peHeaderBuilder = new PEHeaderBuilder(imageCharacteristics: entryPointHandle.IsNil ? Characteristics.Dll : Characteristics.ExecutableImage, machine: machine); @@ -75,7 +76,8 @@ private static void WritePEImage( ilBuilder, entryPoint: entryPointHandle, flags: CorFlags.ILOnly | (privateKeyOpt != null || publicSigned ? CorFlags.StrongNameSigned : 0), - deterministicIdProvider: content => s_contentId); + deterministicIdProvider: content => s_contentId, + mappedFieldData: mappedFieldData); var peBlob = new BlobBuilder(); @@ -487,6 +489,98 @@ private static MethodDefinitionHandle ComplexEmit(MetadataBuilder metadata, Blob return default(MethodDefinitionHandle); } + [Theory] // Validate FieldRVA alignment on common machine types + [MemberData(nameof(AllMachineTypes))] + public void FieldRVAAlignmentVerify(Machine machine) + { + using (var peStream = new MemoryStream()) + { + var ilBuilder = new BlobBuilder(); + var mappedRVADataBuilder = new BlobBuilder(); + var metadataBuilder = new MetadataBuilder(); + double validationNumber = 0.100001; + var fieldDef = FieldRVAValidationEmit(metadataBuilder, mappedRVADataBuilder, validationNumber); + + WritePEImage(peStream, metadataBuilder, ilBuilder, default(MethodDefinitionHandle), + mappedFieldData: mappedRVADataBuilder, + machine: machine); + + // Validate FieldRVA is aligned as ManagedPEBuilder.MappedFieldDataAlignemnt + peStream.Position = 0; + using (var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen)) + { + var mdReader = peReader.GetMetadataReader(); + + // Validate that there is only 1 field rva entry + Assert.Equal(1, mdReader.FieldRvaTable.NumberOfRows); + + // Validate that the RVA is aligned properly (which should be at least an 8 byte alignment + Assert.Equal(0, mdReader.FieldRvaTable.GetRva(1) % ManagedPEBuilder.MappedFieldDataAlignment); + + // Validate that the correct data is at the RVA + var fieldRVAData = peReader.GetSectionData(mdReader.FieldRvaTable.GetRva(1)); + Assert.Equal(validationNumber, fieldRVAData.GetReader().ReadDouble()); + } + + VerifyPE(peStream, machine); + } + } + + private static FieldDefinitionHandle FieldRVAValidationEmit(MetadataBuilder metadata, BlobBuilder mappedRVAData, double doubleToWriteAsData) + { + metadata.AddModule( + 0, + metadata.GetOrAddString("ConsoleApplication.exe"), + metadata.GetOrAddGuid(s_guid), + default(GuidHandle), + default(GuidHandle)); + + metadata.AddAssembly( + metadata.GetOrAddString("ConsoleApplication"), + version: new Version(1, 0, 0, 0), + culture: default(StringHandle), + publicKey: metadata.GetOrAddBlob(ImmutableArray.Create(Misc.KeyPair_PublicKey)), + flags: AssemblyFlags.PublicKey, + hashAlgorithm: AssemblyHashAlgorithm.Sha1); + + var mscorlibAssemblyRef = metadata.AddAssemblyReference( + name: metadata.GetOrAddString("mscorlib"), + version: new Version(4, 0, 0, 0), + culture: default(StringHandle), + publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)), + flags: default(AssemblyFlags), + hashValue: default(BlobHandle)); + + var systemObjectTypeRef = metadata.AddTypeReference( + mscorlibAssemblyRef, + metadata.GetOrAddString("System"), + metadata.GetOrAddString("Object")); + + mappedRVAData.WriteDouble(doubleToWriteAsData); + + var rvaFieldSignature = new BlobBuilder(); + + new BlobEncoder(rvaFieldSignature). + FieldSignature().Double(); + + var fieldRVADef = metadata.AddFieldDefinition( + FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasFieldRVA, + metadata.GetOrAddString("RvaField"), + metadata.GetOrAddBlob(rvaFieldSignature)); + + metadata.AddFieldRelativeVirtualAddress(fieldRVADef, 0); + + metadata.AddTypeDefinition( + TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, + metadata.GetOrAddString("ConsoleApplication"), + metadata.GetOrAddString("Program"), + systemObjectTypeRef, + fieldList: fieldRVADef, + methodList: MetadataTokens.MethodDefinitionHandle(1)); + + return fieldRVADef; + } + private class TestResourceSectionBuilder : ResourceSectionBuilder { public TestResourceSectionBuilder() diff --git a/src/libraries/System.Reflection.Metadata/tests/Utilities/CompressedIntegerTests.cs b/src/libraries/System.Reflection.Metadata/tests/Utilities/CompressedIntegerTests.cs index f6d7b5bb9044e..fbd523ca9b124 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Utilities/CompressedIntegerTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Utilities/CompressedIntegerTests.cs @@ -323,7 +323,7 @@ private unsafe int ReadCompressedInteger(byte[] bytes, TryReadFunc tryRead, Read { Assert.Equal(0, reader.Offset); Assert.Throws(() => reader.ReadCompressedInteger()); - Assert.Equal(value, BlobReader.InvalidCompressedInteger); + Assert.Equal(BlobReader.InvalidCompressedInteger, value); Assert.Equal(0, reader.Offset); } diff --git a/src/libraries/System.Reflection/tests/AssemblyNameTests.cs b/src/libraries/System.Reflection/tests/AssemblyNameTests.cs index 05f3bf31a0c68..60ce4be8e8d7c 100644 --- a/src/libraries/System.Reflection/tests/AssemblyNameTests.cs +++ b/src/libraries/System.Reflection/tests/AssemblyNameTests.cs @@ -68,6 +68,15 @@ public void Ctor_String(string name, string expectedName) Assert.Equal(ProcessorArchitecture.None, assemblyName.ProcessorArchitecture); } + [Theory] + [InlineData("MyAssemblyName, Version=1.0.0.0, PublicKeyToken=b77a5c561934e089", "MyAssemblyName, Version=1.0.0.0, PublicKeyToken=b77a5c561934e089")] + [InlineData("MyAssemblyName, Version=1.0.0.0, PublicKey=00000000000000000400000000000000", "MyAssemblyName, Version=1.0.0.0, PublicKeyToken=b77a5c561934e089")] + public void Ctor_String_Public_Key(string name, string expectedName) + { + AssemblyName assemblyName = new AssemblyName(name); + Assert.Equal(expectedName, assemblyName.FullName); + } + [Theory] [InlineData(null, typeof(ArgumentNullException))] [InlineData("", typeof(ArgumentException))] @@ -76,17 +85,45 @@ public void Ctor_String(string name, string expectedName) [InlineData("/a", typeof(FileLoadException))] [InlineData(" ", typeof(FileLoadException))] [InlineData(" \t \r \n ", typeof(FileLoadException))] + [InlineData("aa, culture=en-en, culture=en-en", typeof(FileLoadException))] + [InlineData("MyAssemblyName, PublicKey=00000000000000000400000000000000, PublicKeyToken=b77a5c561934e089", typeof(FileLoadException))] public void Ctor_String_Invalid(string assemblyName, Type exceptionType) { Assert.Throws(exceptionType, () => new AssemblyName(assemblyName)); } + [Theory] + [InlineData("aaaa, language=en-en", "aaaa")] + [InlineData("aaaa, foo=bar, foo=baz", "aaaa")] + [InlineData("aaaa, foo = bar, foo = bar", "aaaa")] + [InlineData("aaaa, custom=10", "aaaa")] + [InlineData("aaaa, custom=10, custom=20", "aaaa")] + [InlineData("aaaa, custom=lalala", "aaaa")] + public void Ctor_String_Valid_Legacy(string name, string expectedName) + { + AssemblyName assemblyName = new AssemblyName(name); + Assert.Equal(expectedName, assemblyName.Name); + } + + [Theory] + [InlineData("name\\u50; ", typeof(FileLoadException))] + [InlineData("aa/name ", typeof(FileLoadException))] + [InlineData("aa\\/tname", typeof(FileLoadException))] + [InlineData("aaaa, publickey=neutral", typeof(FileLoadException))] + [InlineData("aaaa, publickeytoken=neutral", typeof(FileLoadException))] + [InlineData("aaaa\0", typeof(FileLoadException))] + [InlineData("aaaa\0potato", typeof(FileLoadException))] + [InlineData("aaaa, publickeytoken=null\0,culture=en-en", typeof(FileLoadException))] + public void Ctor_String_Invalid_Legacy(string assemblyName, Type exceptionType) + { + Assert.Throws(exceptionType, () => new AssemblyName(assemblyName)); + } + [Theory] [InlineData("na,me", typeof(FileLoadException))] [InlineData("na=me", typeof(FileLoadException))] [InlineData("na\'me", typeof(FileLoadException))] [InlineData("na\"me", typeof(FileLoadException))] - [ActiveIssue ("https://github.com/dotnet/runtime/issues/45032", TestRuntimes.Mono)] public void Ctor_String_Invalid_Issue(string assemblyName, Type exceptionType) { Assert.Throws(exceptionType, () => new AssemblyName(assemblyName)); @@ -272,20 +309,13 @@ public static void GetAssemblyName() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34492", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] + [SkipOnPlatform(TestPlatforms.Browser, "File locking is not respected")] public static void GetAssemblyName_LockedFile() { using (var tempFile = new TempFile(Path.GetTempFileName(), 100)) using (var fileStream = new FileStream(tempFile.Path, FileMode.Append, FileAccess.Write, FileShare.None)) { - if (PlatformDetection.IsWindows) // File locking is Windows specific. - { - Assert.Throws(() => AssemblyName.GetAssemblyName(tempFile.Path)); - } - else - { - Assert.Throws(() => AssemblyName.GetAssemblyName(tempFile.Path)); - } + Assert.Throws(() => AssemblyName.GetAssemblyName(tempFile.Path)); } } diff --git a/src/libraries/System.Reflection/tests/AssemblyTests.cs b/src/libraries/System.Reflection/tests/AssemblyTests.cs index db230110beed7..1a85f648f8364 100644 --- a/src/libraries/System.Reflection/tests/AssemblyTests.cs +++ b/src/libraries/System.Reflection/tests/AssemblyTests.cs @@ -161,7 +161,7 @@ public void GetFile() if (asm.Location.Length > 0) { Assert.Throws(() => asm.GetFile(null)); - AssertExtensions.Throws(null, () => asm.GetFile("")); + Assert.Throws(() => asm.GetFile("")); Assert.Null(asm.GetFile("NonExistentfile.dll")); Assert.NotNull(asm.GetFile("System.Reflection.Tests.dll")); diff --git a/src/libraries/System.Reflection/tests/GetTypeTests.cs b/src/libraries/System.Reflection/tests/GetTypeTests.cs index 73ff198d9eab9..5cc854e1f3d1d 100644 --- a/src/libraries/System.Reflection/tests/GetTypeTests.cs +++ b/src/libraries/System.Reflection/tests/GetTypeTests.cs @@ -39,27 +39,27 @@ public void GetType_EmptyString() AssertExtensions.Throws("typeName@0", () => Type.GetType(aqn, throwOnError: true, ignoreCase: true)); // Assembly.GetType - AssertExtensions.Throws(null, () => a.GetType(typeName)); + Assert.Throws(() => a.GetType(typeName)); Assert.Null(a.GetType(aqn)); - AssertExtensions.Throws(null, () => a.GetType(typeName, throwOnError: false, ignoreCase: false)); - AssertExtensions.Throws(null, () => a.GetType(typeName, throwOnError: false, ignoreCase: true)); + Assert.Throws(() => a.GetType(typeName, throwOnError: false, ignoreCase: false)); + Assert.Throws(() => a.GetType(typeName, throwOnError: false, ignoreCase: true)); Assert.Null(a.GetType(aqn, throwOnError: false, ignoreCase: false)); Assert.Null(a.GetType(aqn, throwOnError: false, ignoreCase: true)); - AssertExtensions.Throws(null, () => a.GetType(typeName, throwOnError: true, ignoreCase: false)); - AssertExtensions.Throws(null, () => a.GetType(typeName, throwOnError: true, ignoreCase: true)); + Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: false)); + Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: true)); AssertExtensions.Throws("typeName@0", () => a.GetType(aqn, throwOnError: true, ignoreCase: false)); AssertExtensions.Throws("typeName@0", () => a.GetType(aqn, throwOnError: true, ignoreCase: true)); // Module.GetType - AssertExtensions.Throws(null, () => m.GetType(typeName, throwOnError: false, ignoreCase: false)); - AssertExtensions.Throws(null, () => m.GetType(typeName, throwOnError: false, ignoreCase: true)); + Assert.Throws(() => m.GetType(typeName, throwOnError: false, ignoreCase: false)); + Assert.Throws(() => m.GetType(typeName, throwOnError: false, ignoreCase: true)); Assert.Null(m.GetType(aqn, throwOnError: false, ignoreCase: false)); Assert.Null(m.GetType(aqn, throwOnError: false, ignoreCase: true)); - AssertExtensions.Throws(null, () => m.GetType(typeName, throwOnError: true, ignoreCase: false)); - AssertExtensions.Throws(null, () => m.GetType(typeName, throwOnError: true, ignoreCase: true)); + Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: false)); + Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: true)); AssertExtensions.Throws("typeName@0", () => m.GetType(aqn, throwOnError: true, ignoreCase: false)); AssertExtensions.Throws("typeName@0", () => m.GetType(aqn, throwOnError: true, ignoreCase: true)); } diff --git a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs index b5acc81f999c0..f6285546a8713 100644 --- a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs +++ b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs @@ -104,7 +104,7 @@ public void RawDefaultValue_Enum() ParameterInfo p = GetParameterInfo(typeof(ParameterInfoMetadata), "Foo1", 0); object raw = p.RawDefaultValue; Assert.Equal(typeof(int), raw.GetType()); - Assert.Equal((int)raw, (int)BindingFlags.DeclaredOnly); + Assert.Equal((int)BindingFlags.DeclaredOnly, (int)raw); } [Fact] @@ -114,7 +114,7 @@ public void RawDefaultValueFromAttribute() ParameterInfo p = GetParameterInfo(typeof(ParameterInfoMetadata), "Foo2", 0); object raw = p.RawDefaultValue; Assert.Equal(typeof(int), raw.GetType()); - Assert.Equal((int)raw, (int)BindingFlags.IgnoreCase); + Assert.Equal((int)BindingFlags.IgnoreCase, (int)raw); } [Fact] @@ -123,7 +123,7 @@ public void RawDefaultValue_MetadataTrumpsAttribute() ParameterInfo p = GetParameterInfo(typeof(ParameterInfoMetadata), "Foo3", 0); object raw = p.RawDefaultValue; Assert.Equal(typeof(int), raw.GetType()); - Assert.Equal((int)raw, (int)BindingFlags.FlattenHierarchy); + Assert.Equal((int)BindingFlags.FlattenHierarchy, (int)raw); } [Theory] diff --git a/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs b/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs index 378a416210d62..47e6299b373e2 100644 --- a/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs +++ b/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs @@ -69,36 +69,36 @@ public static void ExceptionforDuplicateKey() { writer.AddResource("duplicate", "value"); - Assert.Throws(null, () => writer.AddResource("duplicate", "value")); - Assert.Throws(null, () => writer.AddResource("duplicate", new object())); - Assert.Throws(null, () => writer.AddResource("duplicate", new byte[0])); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", "value")); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", new object())); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", new byte[0])); using (var stream = new MemoryStream()) { - Assert.Throws(null, () => writer.AddResource("duplicate", stream)); - Assert.Throws(null, () => writer.AddResource("duplicate", stream, true)); - Assert.Throws(null, () => writer.AddActivatorResource("duplicate", stream, "System.DayOfWeek", false)); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", stream)); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", stream, true)); + AssertExtensions.Throws(null, () => writer.AddActivatorResource("duplicate", stream, "System.DayOfWeek", false)); } - Assert.Throws(null, () => writer.AddBinaryFormattedResource("duplicate", new byte[1], "System.DayOfWeek")); - Assert.Throws(null, () => writer.AddTypeConverterResource("duplicate", new byte[1], "System.DayOfWeek")); - Assert.Throws(null, () => writer.AddResource("duplicate", "Monday", "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddBinaryFormattedResource("duplicate", new byte[1], "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddTypeConverterResource("duplicate", new byte[1], "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddResource("duplicate", "Monday", "System.DayOfWeek")); - Assert.Throws(null, () => writer.AddResource("Duplicate", "value")); - Assert.Throws(null, () => writer.AddResource("dUplicate", new object())); - Assert.Throws(null, () => writer.AddResource("duPlicate", new byte[0])); + AssertExtensions.Throws(null, () => writer.AddResource("Duplicate", "value")); + AssertExtensions.Throws(null, () => writer.AddResource("dUplicate", new object())); + AssertExtensions.Throws(null, () => writer.AddResource("duPlicate", new byte[0])); using (var stream = new MemoryStream()) { - Assert.Throws(null, () => writer.AddResource("dupLicate", stream)); - Assert.Throws(null, () => writer.AddResource("duplIcate", stream, true)); - Assert.Throws(null, () => writer.AddActivatorResource("dupliCate", stream, "System.DayOfWeek", false)); + AssertExtensions.Throws(null, () => writer.AddResource("dupLicate", stream)); + AssertExtensions.Throws(null, () => writer.AddResource("duplIcate", stream, true)); + AssertExtensions.Throws(null, () => writer.AddActivatorResource("dupliCate", stream, "System.DayOfWeek", false)); } - Assert.Throws(null, () => writer.AddBinaryFormattedResource("duplicAte", new byte[1], "System.DayOfWeek")); - Assert.Throws(null, () => writer.AddTypeConverterResource("duplicaTe", new byte[1], "System.DayOfWeek")); - Assert.Throws(null, () => writer.AddResource("duplicatE", "Monday", "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddBinaryFormattedResource("duplicAte", new byte[1], "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddTypeConverterResource("duplicaTe", new byte[1], "System.DayOfWeek")); + AssertExtensions.Throws(null, () => writer.AddResource("duplicatE", "Monday", "System.DayOfWeek")); } } diff --git a/src/libraries/System.Resources.Extensions/tests/runtimeconfig.template.json b/src/libraries/System.Resources.Extensions/tests/runtimeconfig.template.json deleted file mode 100644 index e3ad204dd9e51..0000000000000 --- a/src/libraries/System.Resources.Extensions/tests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Drawing.EnableUnixSupport": true - } -} \ No newline at end of file diff --git a/src/libraries/System.Runtime.Caching/src/Resources/Strings.resx b/src/libraries/System.Runtime.Caching/src/Resources/Strings.resx index 92219ad308310..2dee4b5671ea1 100644 --- a/src/libraries/System.Runtime.Caching/src/Resources/Strings.resx +++ b/src/libraries/System.Runtime.Caching/src/Resources/Strings.resx @@ -116,9 +116,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Unable to retrieve configuration section '{0}'. - Invalid configuration: {0}="{1}". The {0} value must be a time interval that can be parsed by System.TimeSpan.Parse. diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs index e4eab06b7adb3..f9cc0fd36dadf 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs @@ -13,7 +13,7 @@ namespace System.Runtime.Caching { - internal struct ExpiresEntryRef + internal readonly struct ExpiresEntryRef : IEquatable { internal static readonly ExpiresEntryRef INVALID = new ExpiresEntryRef(0, 0); @@ -31,55 +31,18 @@ internal ExpiresEntryRef(int pageIndex, int entryIndex) _ref = ((((uint)pageIndex) << PAGE_SHIFT) | (((uint)(entryIndex)) & ENTRY_MASK)); } - public override bool Equals(object value) - { - if (value is ExpiresEntryRef) - { - return _ref == ((ExpiresEntryRef)value)._ref; - } + public override bool Equals(object value) => value is ExpiresEntryRef other && Equals(other); - return false; - } + public bool Equals(ExpiresEntryRef other) => _ref == other._ref; - public static bool operator !=(ExpiresEntryRef r1, ExpiresEntryRef r2) - { - return r1._ref != r2._ref; - } - public static bool operator ==(ExpiresEntryRef r1, ExpiresEntryRef r2) - { - return r1._ref == r2._ref; - } + public static bool operator ==(ExpiresEntryRef r1, ExpiresEntryRef r2) => r1.Equals(r2); + public static bool operator !=(ExpiresEntryRef r1, ExpiresEntryRef r2) => !r1.Equals(r2); - public override int GetHashCode() - { - return (int)_ref; - } + public override int GetHashCode() => (int)_ref; - internal int PageIndex - { - get - { - int result = (int)(_ref >> PAGE_SHIFT); - return result; - } - } - - internal int Index - { - get - { - int result = (int)(_ref & ENTRY_MASK); - return result; - } - } - - internal bool IsInvalid - { - get - { - return _ref == 0; - } - } + internal int PageIndex => (int)(_ref >> PAGE_SHIFT); + internal int Index => (int)(_ref & ENTRY_MASK); + internal bool IsInvalid => _ref == 0; } [StructLayout(LayoutKind.Explicit)] diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs index 73ed9f30d3d5c..7b7ea64279211 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs @@ -13,7 +13,7 @@ namespace System.Runtime.Caching { - internal struct UsageEntryRef + internal readonly struct UsageEntryRef : IEquatable { internal static readonly UsageEntryRef INVALID = new UsageEntryRef(0, 0); @@ -31,38 +31,18 @@ internal UsageEntryRef(int pageIndex, int entryIndex) _ref = ((((uint)pageIndex) << PAGE_SHIFT) | (((uint)(entryIndex)) & ENTRY_MASK)); } - public override bool Equals(object value) - { - if (value is UsageEntryRef) - { - return _ref == ((UsageEntryRef)value)._ref; - } + public override bool Equals(object value) => + value is UsageEntryRef other && Equals(other); - return false; - } - public static bool operator ==(UsageEntryRef r1, UsageEntryRef r2) - { - return r1._ref == r2._ref; - } + public bool Equals(UsageEntryRef other) => _ref == other._ref; - public static bool operator !=(UsageEntryRef r1, UsageEntryRef r2) - { - return r1._ref != r2._ref; - } + public static bool operator ==(UsageEntryRef r1, UsageEntryRef r2) => r1.Equals(r2); - public override int GetHashCode() - { - return (int)_ref; - } + public static bool operator !=(UsageEntryRef r1, UsageEntryRef r2) => !r1.Equals(r2); - internal int PageIndex - { - get - { - int result = (int)(_ref >> PAGE_SHIFT); - return result; - } - } + public override int GetHashCode() => (int)_ref; + + internal int PageIndex => (int)(_ref >> PAGE_SHIFT); internal int Ref1Index { @@ -84,29 +64,11 @@ internal int Ref2Index } } - internal bool IsRef1 - { - get - { - return ((int)(sbyte)(_ref & ENTRY_MASK)) > 0; - } - } + internal bool IsRef1 => ((int)(sbyte)(_ref & ENTRY_MASK)) > 0; - internal bool IsRef2 - { - get - { - return ((int)(sbyte)(_ref & ENTRY_MASK)) < 0; - } - } + internal bool IsRef2 => ((int)(sbyte)(_ref & ENTRY_MASK)) < 0; - internal bool IsInvalid - { - get - { - return _ref == 0; - } - } + internal bool IsInvalid => _ref == 0; } internal struct UsageEntryLink diff --git a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs index 415cafb9f02c2..8c6fc1a78d47b 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs @@ -236,7 +236,7 @@ public void Version_Valid() [Fact] public void WorkingSet_Valid() { - if (PlatformDetection.IsBrowser) + if (PlatformDetection.IsBrowser || (PlatformDetection.IsiOS && !PlatformDetection.IsMacCatalyst) || PlatformDetection.IstvOS) Assert.Equal(0, Environment.WorkingSet); else Assert.True(Environment.WorkingSet > 0, "Expected positive WorkingSet value"); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs index 2ef46ada0d0b6..45f3b048c92a3 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs @@ -157,7 +157,7 @@ public void GetRandomFileName() for (int i = 0; i < 100; i++) { string s = Path.GetRandomFileName(); - Assert.Equal(s.Length, 8 + 1 + 3); + Assert.Equal(8 + 1 + 3, s.Length); Assert.Equal('.', s[8]); Assert.Equal(-1, s.IndexOfAny(invalidChars)); Assert.True(fileNames.Add(s)); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs index 3f9cb8775d704..2012c1f09cd91 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs @@ -158,7 +158,7 @@ public static void GePathRoot_Unix(string path) [Fact] public void GetFullPath_ThrowsOnEmbeddedNulls() { - Assert.Throws(null, () => Path.GetFullPath("/gi\0t", "/foo/bar")); + AssertExtensions.Throws(null, () => Path.GetFullPath("/gi\0t", "/foo/bar")); } public static TheoryData TestData_TrimEndingDirectorySeparator => new TheoryData diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.cs index 949e44c6a1723..9f53541319f9a 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.cs @@ -616,7 +616,7 @@ public void GetFullPath_CommonUnRooted_Windows(string path, string basePath, str [Fact] public void GetFullPath_ThrowsOnEmbeddedNulls() { - Assert.Throws(null, () => Path.GetFullPath("/gi\0t", @"C:\foo\bar")); + AssertExtensions.Throws(null, () => Path.GetFullPath("/gi\0t", @"C:\foo\bar")); } public static TheoryData TestData_TrimEndingDirectorySeparator => new TheoryData diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs index 6f1b289fd00ee..50fe5210c91ad 100644 --- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs +++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs @@ -44,6 +44,10 @@ public void VerifyArchitecture() Assert.Equal(Architecture.LoongArch64, processArch); break; + case Architecture.Armv6: + Assert.Equal(Architecture.Armv6, processArch); + break; + default: Assert.False(true, "Unexpected Architecture."); break; diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj index 85f7a7c0c00bc..b3baca91121a9 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj @@ -16,8 +16,8 @@ Microsoft - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + https://github.com/dotnet/runtime/tree/main/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator + https://github.com/dotnet/runtime/ false DllImportGenerator Summary of changes made in this release of the package. @@ -26,10 +26,6 @@ true - - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json ;$(RestoreAdditionalProjectSources) - - diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs index ec42fcd838f84..569db790ffe70 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs @@ -96,7 +96,7 @@ private IEnumerable GeneratePinningPath(TypePositionInfo info, // of an array as long as it is non-null, matching the behavior of the built-in interop system // for single-dimensional zero-based arrays. - // ref = == null ? ref *(); + // ref = ref == null ? ref *(*)0 : ref MemoryMarshal.GetArrayDataReference(); PrefixUnaryExpressionSyntax nullRef = PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression, CastExpression( diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index 901b76346b82c..d56bf7a1737d4 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -98,7 +98,7 @@ public sealed partial class AllowReversePInvokeCallsAttribute : System.Attribute { public AllowReversePInvokeCallsAttribute() { } } - public readonly partial struct ArrayWithOffset + public readonly partial struct ArrayWithOffset : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -157,13 +157,14 @@ public enum ClassInterfaceType AutoDual = 2, } [System.CLSCompliantAttribute(false)] - public readonly struct CLong : IEquatable + public readonly partial struct CLong : System.IEquatable { - public CLong(int value) { } - public CLong(nint value) { } + private readonly int _dummyPrimitive; + public CLong(int value) { throw null; } + public CLong(nint value) { throw null; } public nint Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(CLong other) { throw null; } + public bool Equals(System.Runtime.InteropServices.CLong other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } @@ -294,13 +295,14 @@ public sealed partial class ComUnregisterFunctionAttribute : System.Attribute public ComUnregisterFunctionAttribute() { } } [System.CLSCompliantAttribute(false)] - public readonly struct CULong : IEquatable + public readonly partial struct CULong : System.IEquatable { - public CULong(uint value) { } - public CULong(nuint value) { } + private readonly int _dummyPrimitive; + public CULong(uint value) { throw null; } + public CULong(nuint value) { throw null; } public nuint Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(CULong other) { throw null; } + public bool Equals(System.Runtime.InteropServices.CULong other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } @@ -782,15 +784,99 @@ public static void Free(void* ptr) { } [System.CLSCompliantAttribute(false)] public static void* Realloc(void* ptr, nuint byteCount) { throw null; } } - public readonly struct NFloat : IEquatable + public readonly partial struct NFloat : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable { - public NFloat(float value) { } - public NFloat(double value) { } + private readonly int _dummyPrimitive; + public NFloat(double value) { throw null; } + public NFloat(float value) { throw null; } + public static System.Runtime.InteropServices.NFloat Epsilon { get { throw null; } } + public static System.Runtime.InteropServices.NFloat MaxValue { get { throw null; } } + public static System.Runtime.InteropServices.NFloat MinValue { get { throw null; } } + public static System.Runtime.InteropServices.NFloat NaN { get { throw null; } } + public static System.Runtime.InteropServices.NFloat NegativeInfinity { get { throw null; } } + public static System.Runtime.InteropServices.NFloat PositiveInfinity { get { throw null; } } + public static int Size { get { throw null; } } public double Value { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(NFloat other) { throw null; } + public int CompareTo(object? obj) { throw null; } + public int CompareTo(System.Runtime.InteropServices.NFloat other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Runtime.InteropServices.NFloat other) { throw null; } public override int GetHashCode() { throw null; } + public static bool IsFinite(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNaN(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNegative(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNegativeInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNormal(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsPositiveInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsSubnormal(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator +(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator --(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator /(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator ==(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static explicit operator System.Runtime.InteropServices.NFloat (decimal value) { throw null; } + public static explicit operator System.Runtime.InteropServices.NFloat (double value) { throw null; } + public static explicit operator byte (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator char (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator decimal (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator short (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator int (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator long (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator nint (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator sbyte (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator float (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator ushort (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator uint (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator ulong (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator nuint (System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool operator >(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator >=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (byte value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (char value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (short value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (int value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (long value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (nint value) { throw null; } + public static implicit operator double (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (sbyte value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (ulong value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (nuint value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator ++(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool operator !=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator <(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator <=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator %(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator *(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator -(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator -(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator +(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowExponent | System.Globalization.NumberStyles.AllowLeadingSign | System.Globalization.NumberStyles.AllowLeadingWhite | System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.AllowTrailingWhite, System.IFormatProvider? provider = null) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } + public string ToString(System.IFormatProvider? provider) { throw null; } + public string ToString(string? format) { throw null; } + public string ToString(string? format, System.IFormatProvider? provider) { throw null; } + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse(System.ReadOnlySpan s, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Runtime.InteropServices.NFloat result) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, Inherited=false)] public sealed partial class OptionalAttribute : System.Attribute diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs index bf5ec1713cdbc..8a79b7a66db45 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs @@ -138,6 +138,7 @@ public void Equals_Object_ReturnsExpected(GCHandle handle, object other, bool ex Assert.Equal(expected, handle.Equals(other)); if (other is GCHandle otherHandle) { + Assert.Equal(expected, handle.Equals(otherHandle)); Assert.Equal(expected, handle == otherHandle); Assert.Equal(!expected, handle != otherHandle); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs index c2311afae708d..6f97497fe03c7 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs @@ -15,36 +15,844 @@ public class NFloatTests [Fact] public void Ctor_Empty() { - NFloat value = new NFloat(); - Assert.Equal(0, value.Value); + NFloat result = new NFloat(); + Assert.Equal(0, result.Value); } [Fact] public void Ctor_Float() { - NFloat value = new NFloat(42.0f); - Assert.Equal(42.0, value.Value); + NFloat result = new NFloat(42.0f); + Assert.Equal(42.0, result.Value); } [Fact] public void Ctor_Double() { - NFloat value = new NFloat(42.0); - Assert.Equal(42.0, value.Value); + NFloat result = new NFloat(42.0); + Assert.Equal(42.0, result.Value); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))] public void Ctor_Double_OutOfRange() { - NFloat value = new NFloat(double.MaxValue); - Assert.Equal((double)(float)double.MaxValue, value.Value); + NFloat result = new NFloat(double.MaxValue); + Assert.Equal(float.PositiveInfinity, result.Value); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))] public void Ctor_Double_LargeValue() { - NFloat value = new NFloat(double.MaxValue); - Assert.Equal(double.MaxValue, value.Value); + NFloat result = new NFloat(double.MaxValue); + Assert.Equal(double.MaxValue, result.Value); + } + + [Fact] + public void Epsilon() + { + NFloat result = NFloat.Epsilon; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.Epsilon, result.Value); + } + else + { + Assert.Equal(float.Epsilon, result.Value); + } + } + + [Fact] + public void MaxValue() + { + NFloat result = NFloat.MaxValue; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.MaxValue, result.Value); + } + else + { + Assert.Equal(float.MaxValue, result.Value); + } + } + + [Fact] + public void MinValue() + { + NFloat result = NFloat.MinValue; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.MinValue, result.Value); + } + else + { + Assert.Equal(float.MinValue, result.Value); + } + } + + [Fact] + public void NaN() + { + NFloat result = NFloat.NaN; + Assert.True(double.IsNaN(result.Value)); + } + + [Fact] + public void NegativeInfinity() + { + NFloat result = NFloat.NegativeInfinity; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.NegativeInfinity, result.Value); + } + else + { + Assert.Equal(float.NegativeInfinity, result.Value); + } + } + + [Fact] + public void PositiveInfinity() + { + NFloat result = NFloat.PositiveInfinity; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.PositiveInfinity, result.Value); + } + else + { + Assert.Equal(float.PositiveInfinity, result.Value); + } + } + + [Fact] + public unsafe void Size() + { + int size = PlatformDetection.Is32BitProcess ? 4 : 8; +#pragma warning disable xUnit2000 // The value under test here is the sizeof expression + Assert.Equal(size, sizeof(NFloat)); +#pragma warning restore xUnit2000 + Assert.Equal(size, Marshal.SizeOf()); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_UnaryPlus(float value) + { + NFloat result = +(new NFloat(value)); + Assert.Equal(+value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_UnaryNegation(float value) + { + NFloat result = -(new NFloat(value)); + Assert.Equal(-value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_Decrement(float value) + { + NFloat result = new NFloat(value); + --result; + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)value - 1, result.Value); + } + else + { + Assert.Equal(value - 1, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_Increment(float value) + { + NFloat result = new NFloat(value); + ++result; + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)value + 1, result.Value); + } + else + { + Assert.Equal(value + 1, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Addition(float left, float right) + { + NFloat result = new NFloat(left) + new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left + right, result.Value); + } + else + { + Assert.Equal(left + right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Subtraction(float left, float right) + { + NFloat result = new NFloat(left) - new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left - right, result.Value); + } + else + { + Assert.Equal(left - right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Multiply(float left, float right) + { + NFloat result = new NFloat(left) * new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left * right, result.Value); + } + else + { + Assert.Equal(left * right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Division(float left, float right) + { + NFloat result = new NFloat(left) / new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left / right, result.Value); + } + else + { + Assert.Equal(left / right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Modulus(float left, float right) + { + NFloat result = new NFloat(left) % new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left % right, result.Value); + } + else + { + Assert.Equal(left % right, result.Value); + } + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_Equality(float left, float right) + { + bool result = new NFloat(left) == new NFloat(right); + Assert.Equal(left == right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_Inequality(float left, float right) + { + bool result = new NFloat(left) != new NFloat(right); + Assert.Equal(left != right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_GreaterThan(float left, float right) + { + bool result = new NFloat(left) > new NFloat(right); + Assert.Equal(left > right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_GreaterThanOrEqual(float left, float right) + { + bool result = new NFloat(left) >= new NFloat(right); + Assert.Equal(left >= right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_LessThan(float left, float right) + { + bool result = new NFloat(left) < new NFloat(right); + Assert.Equal(left < right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_LessThanOrEqual(float left, float right) + { + bool result = new NFloat(left) <= new NFloat(right); + Assert.Equal(left <= right, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void DoubleToNFloat(float value) + { + NFloat result = (NFloat)(double)value; + + if (Environment.Is64BitProcess) + { + Assert.Equal(value, result.Value); + } + else + { + Assert.Equal((float)value, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToByte(float value) + { + byte result = (byte)new NFloat(value); + Assert.Equal((byte)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToChar(float value) + { + char result = (char)new NFloat(value); + Assert.Equal((char)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToDecimal(float value) + { + decimal result = (decimal)new NFloat(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal((decimal)(double)value, result); + } + else + { + Assert.Equal((decimal)value, result); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt16(float value) + { + short result = (short)new NFloat(value); + Assert.Equal((short)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt32(float value) + { + int result = (int)new NFloat(value); + Assert.Equal((int)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt64(float value) + { + long result = (long)new NFloat(value); + Assert.Equal((long)value, result); + } + + [Theory] + [InlineData(-4567.0f, Skip = "https://github.com/dotnet/runtime/issues/64386")] + [InlineData(-4567.89101f, Skip = "https://github.com/dotnet/runtime/issues/64386")] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToIntPtr(float value) + { + nint result = (nint)new NFloat(value); + Assert.Equal((nint)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToSByte(float value) + { + sbyte result = (sbyte)new NFloat(value); + Assert.Equal((sbyte)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToSingle(float value) + { + float result = (float)new NFloat(value); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt16(float value) + { + ushort result = (ushort)new NFloat(value); + Assert.Equal((ushort)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt32(float value) + { + uint result = (uint)new NFloat(value); + Assert.Equal((uint)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt64(float value) + { + ulong result = (ulong)new NFloat(value); + Assert.Equal((ulong)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUIntPtr(float value) + { + nuint result = (nuint)new NFloat(value); + Assert.Equal((nuint)value, result); + } + + [Theory] + [InlineData((byte)0)] + [InlineData((byte)5)] + [InlineData((byte)42)] + [InlineData((byte)127)] + [InlineData((byte)255)] + public void ByteToNFloat(byte value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData('A')] + [InlineData('B')] + [InlineData('C')] + [InlineData('D')] + [InlineData('E')] + public void CharToNFloat(char value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((short)-255)] + [InlineData((short)-127)] + [InlineData((short)0)] + [InlineData((short)127)] + [InlineData((short)255)] + public void Int16ToNFloat(short value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-255)] + [InlineData(-127)] + [InlineData(0)] + [InlineData(127)] + [InlineData(255)] + public void Int32ToNFloat(int value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((long)-255)] + [InlineData((long)-127)] + [InlineData((long)0)] + [InlineData((long)127)] + [InlineData((long)255)] + public void Int64ToNFloat(long value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((int)-255)] + [InlineData((int)-127)] + [InlineData((int)0)] + [InlineData((int)127)] + [InlineData((int)255)] + public void IntPtrToNFloat(int value) + { + NFloat result = (nint)value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((sbyte)-127)] + [InlineData((sbyte)-63)] + [InlineData((sbyte)0)] + [InlineData((sbyte)63)] + [InlineData((sbyte)127)] + public void SByteToNFloat(sbyte value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void SingleToNFloat(float value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((ushort)0)] + [InlineData((ushort)5)] + [InlineData((ushort)42)] + [InlineData((ushort)127)] + [InlineData((ushort)255)] + public void UInt16ToNFloat(ushort value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((uint)0)] + [InlineData((uint)5)] + [InlineData((uint)42)] + [InlineData((uint)127)] + [InlineData((uint)255)] + public void UInt32ToNFloat(uint value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((ulong)0)] + [InlineData((ulong)5)] + [InlineData((ulong)42)] + [InlineData((ulong)127)] + [InlineData((ulong)255)] + public void UInt64ToNFloat(ulong value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((uint)0)] + [InlineData((uint)5)] + [InlineData((uint)42)] + [InlineData((uint)127)] + [InlineData((uint)255)] + public void UIntPtrToNFloat(uint value) + { + NFloat result = (nuint)value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToDouble(float value) + { + double result = new NFloat(value); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsFinite(float value) + { + bool result = NFloat.IsFinite(value); + Assert.Equal(float.IsFinite(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsInfinity(float value) + { + bool result = NFloat.IsInfinity(value); + Assert.Equal(float.IsInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNaN(float value) + { + bool result = NFloat.IsNaN(value); + Assert.Equal(float.IsNaN(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNegative(float value) + { + bool result = NFloat.IsNegative(value); + Assert.Equal(float.IsNegative(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNegativeInfinity(float value) + { + bool result = NFloat.IsNegativeInfinity(value); + Assert.Equal(float.IsNegativeInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNormal(float value) + { + bool result = NFloat.IsNormal(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.IsNormal(value), result); + } + else + { + Assert.Equal(float.IsNormal(value), result); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsPositiveInfinity(float value) + { + bool result = NFloat.IsPositiveInfinity(value); + Assert.Equal(float.IsPositiveInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsSubnormal(float value) + { + bool result = NFloat.IsSubnormal(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.IsSubnormal(value), result); + } + else + { + Assert.Equal(float.IsSubnormal(value), result); + } } public static IEnumerable EqualsData() @@ -83,7 +891,6 @@ public void NaNEqualsTest() [InlineData(0.0f)] [InlineData(4567.0f)] [InlineData(4567.89101f)] - [InlineData(float.NaN)] public static void ToStringTest64(float value) { @@ -106,15 +913,5 @@ public static void ToStringTest32(float value) Assert.Equal(value.ToString(), nfloat.ToString()); } - - [Fact] - public unsafe void Size() - { - int size = PlatformDetection.Is32BitProcess ? 4 : 8; -#pragma warning disable xUnit2000 // The value under test here is the sizeof expression - Assert.Equal(size, sizeof(NFloat)); -#pragma warning restore xUnit2000 - Assert.Equal(size, Marshal.SizeOf()); - } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs index 10104a0a0bb77..6c45152e8fe2c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs @@ -71,11 +71,6 @@ public void SetMessageSendCallback_AlreadySet() var (msgSend, func) = msgSendOverrides[0]; ObjectiveCMarshal.SetMessageSendCallback(msgSend, func); Assert.Throws(() => ObjectiveCMarshal.SetMessageSendCallback(msgSend, func)); - - // TODO: Remove once https://github.com/dotnet/arcade/issues/5865 is resolved - // RemoteExecutor currently only checks the expected exit code if the invoked function returns an int. - // Check the exit code to ensure the test will fail if there was a crash that could not be caught by the executor. - return RemoteExecutor.SuccessExitCode; }).Dispose(); } @@ -102,11 +97,6 @@ public void SetMessageSendCallback(MessageSendFunction[] funcsToOverride) } SetMessageSendCallbackImpl(msgSendArray); - - // TODO: Remove once https://github.com/dotnet/arcade/issues/5865 is resolved - // RemoteExecutor currently only checks the expected exit code if the invoked function returns an int. - // Check the exit code to ensure the test will fail if there was a crash that could not be caught by the executor. - return RemoteExecutor.SuccessExitCode; }, string.Join(';', funcsToOverride)).Dispose(); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs index 5a67e3367eaff..d60e2b6a43b37 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs @@ -59,11 +59,6 @@ public void ValidateSetMessageSendPendingException(MessageSendFunction func) Assert.True(Enum.IsDefined(msgSend)); ValidateSetMessageSendPendingExceptionImpl(msgSend); - - // TODO: Remove once https://github.com/dotnet/arcade/issues/5865 is resolved - // RemoteExecutor currently only checks the expected exit code if the invoked function returns an int. - // Check the exit code to ensure the test will fail if there was a crash that could not be caught by the executor. - return RemoteExecutor.SuccessExitCode; }, func.ToString()).Dispose(); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs index d60da1fc34ba8..303c2250b538f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs @@ -76,8 +76,8 @@ public void ReadWrite_NotEnoughSpaceInBuffer_ThrowsArgumentException(ulong byteO var buffer = new SubBuffer(true); buffer.Initialize(4); - Assert.Throws(null, () => buffer.Read(byteOffset)); - Assert.Throws(null, () => buffer.Write(byteOffset, 2)); + AssertExtensions.Throws(null, () => buffer.Read(byteOffset)); + AssertExtensions.Throws(null, () => buffer.Write(byteOffset, 2)); } [Fact] diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index e6a39a0552129..67ab0317761f9 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -3751,6 +3751,7 @@ public void Vector128Int64SumTest() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63746", TestPlatforms.tvOS)] public void Vector128NIntSumTest() { Vector128 vector = Vector128.Create((nint)0x01); @@ -3766,6 +3767,7 @@ public void Vector128NIntSumTest() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63746", TestPlatforms.tvOS)] public void Vector128NUIntSumTest() { Vector128 vector = Vector128.Create((nuint)0x01); diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis.cs index 186144e290e35..a5ec0d11b1f5c 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis.cs @@ -7,19 +7,21 @@ namespace System.Reflection.Metadata.ApplyUpdate.Test { public class AddLambdaCapturingThis { - public AddLambdaCapturingThis () { - field = "abcd"; - } + public AddLambdaCapturingThis() + { + field = "abcd"; + } - public string GetField => field; + public string GetField => field; - private string field; + private string field; - public string TestMethod () { - // capture 'this' but no locals - Func fn = s => field; - return "123"; - } + public string TestMethod() + { + // capture 'this' but no locals + Func fn = s => field; + return "123"; + } } } diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis_v1.cs index 22dd869021dc3..44ff73ab1d591 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis_v1.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis/AddLambdaCapturingThis_v1.cs @@ -7,23 +7,21 @@ namespace System.Reflection.Metadata.ApplyUpdate.Test { public class AddLambdaCapturingThis { - public AddLambdaCapturingThis () { - field = "abcd"; - } + public AddLambdaCapturingThis() + { + field = "abcd"; + } - public string GetField => field; + public string GetField => field; - private string field; - - public string TestMethod () { - // capture 'this' but no locals - Func fn = s => NewMethod (s + field, 42); - return fn ("123"); - } - - private string NewMethod (string s, int i) { - return i.ToString() + s; - } + private string field; + public string TestMethod() + { + // capture 'this' but no locals + Func fn = s => field; + Func fn2 = s => "42" + s + field; + return fn2 ("123"); + } } } diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass.cs new file mode 100644 index 0000000000000..d5bd6ce27fd0e --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass.cs @@ -0,0 +1,20 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddNestedClass + { + public AddNestedClass() + { + } + + public string TestMethod() + { + return "123"; + } + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass_v1.cs new file mode 100644 index 0000000000000..04fc6992631d9 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/AddNestedClass_v1.cs @@ -0,0 +1,29 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddNestedClass + { + public AddNestedClass() + { + } + + public string TestMethod() + { + var n = new Nested(); + n.f = "123"; + return n.M(); + } + + private class Nested { + public Nested() { } + internal string f; + public string M () { + return f + "456"; + } + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass.csproj new file mode 100644 index 0000000000000..26f3348462094 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/deltascript.json new file mode 100644 index 0000000000000..e70a3b3bbafbc --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "AddNestedClass.cs", "update": "AddNestedClass_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField.cs new file mode 100644 index 0000000000000..6ac1360c3581b --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField.cs @@ -0,0 +1,22 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddStaticField + { + public AddStaticField () { + } + + public string GetField => s_field; + + private static string s_field; + + public void TestMethod () { + s_field = "abcd"; + } + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField_v1.cs new file mode 100644 index 0000000000000..f9282469a4fce --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/AddStaticField_v1.cs @@ -0,0 +1,25 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddStaticField + { + public AddStaticField () { + } + + public string GetField => s_field2; + + private static string s_field; + + private static string s_field2; + + public void TestMethod () { + s_field = "spqr"; + s_field2 = "4567"; + } + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField.csproj new file mode 100644 index 0000000000000..0a3f60146cac3 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/deltascript.json new file mode 100644 index 0000000000000..3c0d7a0fc6866 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "AddStaticField.cs", "update": "AddStaticField_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda.cs new file mode 100644 index 0000000000000..9e759e6075b5b --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda.cs @@ -0,0 +1,18 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddStaticLambda + { + public string TestMethod() + { + return "abcd"; + } + + public string Double(Func f) => f("") + f("1"); + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda_v1.cs new file mode 100644 index 0000000000000..6f9e94b08a7f4 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/AddStaticLambda_v1.cs @@ -0,0 +1,18 @@ +// 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.Reflection.Metadata.ApplyUpdate.Test +{ + public class AddStaticLambda + { + public string TestMethod() + { + return Double(static (s) => s + "abcd"); + } + + public string Double(Func f) => f("") + f("1"); + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda.csproj new file mode 100644 index 0000000000000..3b402585aa298 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/deltascript.json new file mode 100644 index 0000000000000..1d60513f4a43f --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "AddStaticLambda.cs", "update": "AddStaticLambda_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index dd5c49c396335..9e28894b6bbf3 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -71,6 +71,7 @@ void LambdaBodyChange() [ActiveIssue("https://github.com/dotnet/runtime/issues/54617", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] void LambdaCapturesThis() { + // Tests that changes to the body of a lambda that captures 'this' is supported. ApplyUpdateUtil.TestCase(static () => { var assm = typeof (ApplyUpdate.Test.LambdaCapturesThis).Assembly; @@ -263,25 +264,92 @@ public void AsyncMethodChanges() }); } - [ActiveIssue ("https://github.com/dotnet/runtime/issues/50249", TestRuntimes.Mono)] - [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] - public static void TestAddLambdaCapturingThis() - { - ApplyUpdateUtil.TestCase(static () => - { - var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis).Assembly; + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] + public static void TestAddLambdaCapturingThis() + { + // Test that adding a lambda that captures 'this' (to a method that already has a lambda that captures 'this') is supported + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis).Assembly; + + var x = new System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis(); + + Assert.Equal("123", x.TestMethod()); + + ApplyUpdateUtil.ApplyUpdate(assm); + + string result = x.TestMethod(); + Assert.Equal("42123abcd", result); + }); + } + + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] + public static void TestAddStaticField() + { + // Test that adding a new static field to an existing class is supported + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField).Assembly; + + var x = new System.Reflection.Metadata.ApplyUpdate.Test.AddStaticField(); + + x.TestMethod(); + + Assert.Equal ("abcd", x.GetField); + + ApplyUpdateUtil.ApplyUpdate(assm); + + x.TestMethod(); + + string result = x.GetField; + Assert.Equal("4567", result); + }); + } + + [ActiveIssue("https://github.com/dotnet/runtime/issues/63643", TestRuntimes.Mono)] + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] + public static void TestAddNestedClass() + { + // Test that adding a new nested class to an existing class is supported + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass).Assembly; + + var x = new System.Reflection.Metadata.ApplyUpdate.Test.AddNestedClass(); + + var r = x.TestMethod(); + + Assert.Equal ("123", r); + + ApplyUpdateUtil.ApplyUpdate(assm); + + r = x.TestMethod(); - var x = new System.Reflection.Metadata.ApplyUpdate.Test.AddLambdaCapturingThis(); + Assert.Equal("123456", r); + }); + } + + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] + public static void TestAddStaticLambda() + { + // Test that adding a new static lambda to an existing method body is supported + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda).Assembly; - Assert.Equal("123", x.TestMethod()); + var x = new System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda(); - ApplyUpdateUtil.ApplyUpdate(assm); + var r = x.TestMethod(); - string result = x.TestMethod(); - Assert.Equal("42123abcd", result); - }); - } + Assert.Equal ("abcd", r); + ApplyUpdateUtil.ApplyUpdate(assm); + + r = x.TestMethod(); + + Assert.Equal("abcd1abcd", r); + }); + } class NonRuntimeAssembly : Assembly { diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs index beaa4a0e7338b..405afc9f50edb 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs @@ -47,7 +47,7 @@ internal static bool CheckSupportedMonoConfiguration() { // check that interpreter is enabled, and the build has hot reload capabilities enabled. var isInterp = RuntimeFeature.IsDynamicCodeSupported && !RuntimeFeature.IsDynamicCodeCompiled; - return isInterp && HasApplyUpdateCapabilities(); + return isInterp && !PlatformDetection.IsMonoAOT && HasApplyUpdateCapabilities(); } internal static bool HasApplyUpdateCapabilities() diff --git a/src/libraries/System.Runtime.Loader/tests/DefaultContext/DefaultLoadContextTest.cs b/src/libraries/System.Runtime.Loader/tests/DefaultContext/DefaultLoadContextTest.cs index 8f7ecc5dc71bd..420f24fa625f7 100644 --- a/src/libraries/System.Runtime.Loader/tests/DefaultContext/DefaultLoadContextTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/DefaultContext/DefaultLoadContextTest.cs @@ -151,7 +151,7 @@ public void LoadInDefaultContext() Assert.Equal(assemblyExpected, assemblyExpectedFromLoad); // And make sure the simple name matches - Assert.Equal(assemblyExpected.GetName().Name, TestAssemblyName); + Assert.Equal(TestAssemblyName, assemblyExpected.GetName().Name); // Unwire the Resolving event. AssemblyLoadContext.Default.Resolving -= ResolveAssemblyAgain; diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index d678320e01740..e21bc7e673f5f 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -53,6 +53,9 @@ + + + diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index 2d7395e2e83dd..984bde00e7cb2 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -310,14 +310,14 @@ internal static bool TryValidateParseStyleInteger(NumberStyles style, [NotNullWh // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - e = new ArgumentException(SR.Format(SR.Argument_InvalidNumberStyles, nameof(style))); + e = new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); return false; } if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number if ((style & ~NumberStyles.HexNumber) != 0) { - e = new ArgumentException(SR.Argument_InvalidHexStyle); + e = new ArgumentException(SR.Argument_InvalidHexStyle, nameof(style)); return false; } } diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs index 115a61366d093..7f0f427e4e5e2 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -18,7 +18,7 @@ public class parseTest // Invariant culture is commonly used for (de-)serialization and similar to en-US // Ukrainian (Ukraine) added to catch regressions (https://github.com/dotnet/runtime/issues/14545) - // Current cultue to get additional value out of glob/loc test runs + // Current culture to get additional value out of glob/loc test runs public static IEnumerable Cultures { get @@ -66,11 +66,11 @@ public static void RunParseToStringTests(CultureInfo culture) //invalid number style // ******InvalidNumberStyles NumberStyles invalid = (NumberStyles)0x7c00; - AssertExtensions.Throws(null, () => + AssertExtensions.Throws("style", () => { BigInteger.Parse("1", invalid).ToString("d"); }); - AssertExtensions.Throws(null, () => + AssertExtensions.Throws("style", () => { BigInteger junk; BigInteger.TryParse("1", invalid, null, out junk); @@ -116,6 +116,16 @@ public void Parse_Hex32Bits() Assert.True(BigInteger.TryParse("080000001", NumberStyles.HexNumber, null, out result)); Assert.Equal(0x80000001u, result); + + Assert.Throws(() => + { + BigInteger.Parse("zzz", NumberStyles.HexNumber); + }); + + AssertExtensions.Throws("style", () => + { + BigInteger.Parse("1", NumberStyles.AllowHexSpecifier | NumberStyles.AllowCurrencySymbol); + }); } private static void RunFormatProviderParseStrings() diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx b/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx index db744f8c42ee8..df3d7f4311915 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx @@ -237,9 +237,6 @@ No MemberInfo for Object {0}. - - Type {0} and the types derived from it (such as {1}) are not permitted to be deserialized at this security level. - Selector contained a cycle. diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs index ad4d0aef0dd1e..f239ccb1a53ab 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs @@ -1189,7 +1189,7 @@ public static IEnumerable SerializableObjects() yield return new object[] { ContentAlignment.BottomCenter, new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAAB9TeXN0ZW0uRHJhd2luZy5Db250ZW50QWxpZ25tZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAIAAAs=", TargetFrameworkMoniker.netcoreapp21), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAAB9TeXN0ZW0uRHJhd2luZy5Db250ZW50QWxpZ25tZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAIAAAs=", TargetFrameworkMoniker.netfx461) } }; yield return new object[] { LinearGradientMode.BackwardDiagonal, new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACtTeXN0ZW0uRHJhd2luZy5EcmF3aW5nMkQuTGluZWFyR3JhZGllbnRNb2RlAQAAAAd2YWx1ZV9fAAgCAAAAAwAAAAs=", TargetFrameworkMoniker.netcoreapp21), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACtTeXN0ZW0uRHJhd2luZy5EcmF3aW5nMkQuTGluZWFyR3JhZGllbnRNb2RlAQAAAAd2YWx1ZV9fAAgCAAAAAwAAAAs=", TargetFrameworkMoniker.netfx461) } }; yield return new object[] { FontStyle.Bold, new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABhTeXN0ZW0uRHJhd2luZy5Gb250U3R5bGUBAAAAB3ZhbHVlX18ACAIAAAABAAAACw==", TargetFrameworkMoniker.netcoreapp21), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABhTeXN0ZW0uRHJhd2luZy5Gb250U3R5bGUBAAAAB3ZhbHVlX18ACAIAAAABAAAACw==", TargetFrameworkMoniker.netfx461) } }; - // libgdiplus is not supported on some Windows variants. + // Drawing is not supported on all platforms if (PlatformDetection.IsDrawingSupported) { yield return new object[] { new Font("coreFxAwesomeFont", 8.5f, FontStyle.Strikeout, GraphicsUnit.Pixel), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABNTeXN0ZW0uRHJhd2luZy5Gb250BAAAAAROYW1lBFNpemUFU3R5bGUEVW5pdAEABAQLGFN5c3RlbS5EcmF3aW5nLkZvbnRTdHlsZQIAAAAbU3lzdGVtLkRyYXdpbmcuR3JhcGhpY3NVbml0AgAAAAIAAAAGAwAAABFjb3JlRnhBd2Vzb21lRm9udAAACEEF/P///xhTeXN0ZW0uRHJhd2luZy5Gb250U3R5bGUBAAAAB3ZhbHVlX18ACAIAAAAIAAAABfv///8bU3lzdGVtLkRyYXdpbmcuR3JhcGhpY3NVbml0AQAAAAd2YWx1ZV9fAAgCAAAAAgAAAAs=", TargetFrameworkMoniker.netcoreapp30), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABNTeXN0ZW0uRHJhd2luZy5Gb250BAAAAAROYW1lBFNpemUFU3R5bGUEVW5pdAEABAQLGFN5c3RlbS5EcmF3aW5nLkZvbnRTdHlsZQIAAAAbU3lzdGVtLkRyYXdpbmcuR3JhcGhpY3NVbml0AgAAAAIAAAAGAwAAABFjb3JlRnhBd2Vzb21lRm9udAAACEEF/P///xhTeXN0ZW0uRHJhd2luZy5Gb250U3R5bGUBAAAAB3ZhbHVlX18ACAIAAAAIAAAABfv///8bU3lzdGVtLkRyYXdpbmcuR3JhcGhpY3NVbml0AQAAAAd2YWx1ZV9fAAgCAAAAAgAAAAs=", TargetFrameworkMoniker.netfx461) } }; @@ -1346,8 +1346,8 @@ public static IEnumerable SerializableObjects() // System.Drawing.Common // Since this code paths use GDI+ we need to validate it is available - // libgdiplus versions before 6.0 do not roundtrip bitmaps reliably - if (PlatformDetection.IsDrawingSupported && Helpers.GetIsWindowsOrAtLeastLibgdiplus6()) + // Drawing is not supported on all platforms + if (PlatformDetection.IsDrawingSupported) { const string InlineJpegImage = "iVBORw0KGgoAAAANSUhEUgAAAG4AAABkCAIAAADoopLKAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAIABJREFUeJzcuQdUU+u67825Z++z99qrr2VvCCi9954EQkioCQRCEgiE3nvvvfeOgEhXQBCkiKJiAcSCUqSDNJGO9G7ug9nbs+65e5xx7rjfGHecb47/eMczZxKc+c3/U97IYpLxRD24go0UwE0Ldrn1vHhk/dbUVvWnXcuCO9d7p28NzmW0vLn+6E3ti/6WrtHXo4t3X3d/YjA+bO5UtDzaZDA2GV8Wt9d3GIe7DAZoj8HYP2LsHzAYX0BHoL2d3aODw6+n/6v+mx9f/reDxbWsK+jusHX+Y83QQu2IAmLcDfPcmujWbv/6tpqpjfrpjett/TVvx1/PbkxsMNYYjN6VrUUG49XUXErZrWUGY/XoaP3L4Q6DMbd+uPUVJWA8+jupI8bB/h85Hu4fHOztfzk8+v8nSufCp3Eto6F3u+lp1Wr+aVK2QWivWNfSRp+qx1VjK5VD84kN7XkPXz8Zmx9aOwJ2M1/1aGgqurBsaufw08EhXPzMYPR8mJvdONj5SvPw77Y72t/b+eO/vbOzs7W1tbu7e3h4+P+Mwf9Hxz9B2Tx79HiJUTO6UdrzqWpoJa9zNPVxT3nfJ6vMirLe2ar3n8Ju3g8vrS9qfdX8fuLN3EbfLqN7nfH4w1Jm/aPxPcbwxu7E7uHw6vrLkemptd0NBgO8uXXEpHm0f7h3+JUsaP/L0ebuzsbO9s7B/n97kP8U5RSDMcFgdG0w3m0xPjAYL5YZNX2fWiY3bVJvNk1svlhh5Lb2pDW1Vb4ZePRh7tXS1vNlRsvU1sOpzZyHr14t7j6dWBjcOnr/ea9rcm5q6wDsuXLIWNre2TjcO2AcHTKO9r76FLTNOFw/2IXrzNP/7sc/QVnXO/hsZvHF/Pqrxe2OT9vFT/uym149GF51zax+OnvYu82oejtV3TPxcnW3a+Pg5erOw0VGac/87YHlhMYXtf1zt7s/DO4zhvYY7WPT4xu7kOxz+4cz6+sre1t7xxyPmO1om3G0dri7vLv5+WCHeeW/+/HPEnzg/euFhf6NnfEDRv/6l+rO4dLW3q75L6FFDx6ObT4Y+ZzZ/Lrm/dT7A0bbymbJm97bH/aj7/fmdE7E3XtbN7Ja0//p/T6jbX6v9uXbt58WPx0y5g6PPm5tLuxtbjMOdhlHO8ccv6wd7S1sr898Xvq4try8t7UFHem/+fFPUI7ubfZvrHZ+nO1d3Rjc+HK7oz+h7P6N5rdZDW9bhteLnw0GFtaXvxnuO2TcHZ3yLa3MfjXnXPwosXUou328bZ3xcHb/7Raj/PV4XsP91qGxid39+aMvs3s7SwfbG4y9Tcb+1teBaflwZ2ptaXh+BjSxuvBpe+3/NYr/2+OfoJxd25heWZ/+vN0zvQCVLvZG5fXGpy9n1kqf9rWOrebee+kUfz3zbtu7ZcbbpS8NPTNFr0cbx5bCbjVW94zf7Ox5t7w1ecgY2zuqefYcUnt0cWV2a3fnGN/fx8yZ/Z25L4ftI+NvJudejS89H5hb/drxp9bXt5mNHkam7eORCT4FL0GXZ97rwcHB5ubm0dGxf6Hp/9Mvw3z1v/7lYXKAj8B68PWAAC7+/eXD4zs5nuOOvhx+OYImuXecUkffho39/f29vb8X+eObhN4Jb/465H05/ugXlq6hseG5xY+be0NLG68+zEVeryh/0jW+y4i7eb+pb/ZW+2B0aVPN6/FpGMsPGW1Tm+VdH+59WImqbK7vn6rs7O2cXelb3e5eWK1ufT6xvv16ZOLN6OTI3Er/9Dz4cecrNRC0+NHPO28ml+o7+t9NbXdNbM9sbu7+AyUUVJjq1w6OZre3v1E7/Hr856b4P0LJhPjtg3D8O0cmysMvDMC7DxPGwS7oeF7+97/PfADM+Pgx7O79fUZm3g+DwfKsZwC+/7vJuZHV3azb93MbnpY9fdc+ue6dUd7Y+7G5fy4H2kvXRO/nY45AtnFkGSpjWv2zR+OLtzv7Hg5OPh780NTVl11e/Xb84+N3A+0D491T87DObB2uMBgf948WGIw3U5/g73d//NzYOfBuev3t1Mb4ysrml7+jZHyd2dcPv8z8w4ZMF3z7qt++w/8lSvg7/wu+Px6wS9s7gKa4vbm1tbO9tbe7cwS1/t/fDJb89pjh3sCYcOWPD5vlxdBEa+/wo56R2UNGXGld18JucWtPdlOnRWh69auxlqFFyPGbbQPPJtbBpIWP3j39uPv2MyP/4evXc9t3u4budQ3VtnWVP3jqG53S8rK3tXsI3D2zy3g5+Wl0Y29yn9E5NvN64lNDZ8/b6aW30yv3Xg8Mr+xNbTH6Z2eXtnf/iBLy/SM0pH+wg/uGFb4/BJ8/f/7fOTKP/yJHZnb/8fH8xwP+ta2drbX11eWVlc+ra1ub24f7gJL5FOGz6+vra2tr8Bcg3t7eBtB7R4dQB+DewZtf9g9YChse3Wxpe9Q3CdvB2NLGSQYjs+llakOnrnPojYdv695Opt15WvKk9+WnPaiV7dNbLSOrHTPb1xrauxf34VOPesYaX/TUPXsVGnftfntfy+uhwaWd6QPGk/HZN4sbPRv7IyuH7+c3m171A0coIHeev3k//3l658uH1dXP+4d/RLm6dzC8sMC8b+Ydf/v+cBz94fivoPwPLzEtCT5iPp5/8n4o8WsbKwuLc7OfPs3PLX1e3dzf3fv6QeYtAUd4ovAXmE939x+75IOjw93tna3VNRY9O0/X2MzSx8cuc0kuejq145lTU9r5wdg/ETpP5Yvh0ILaxMqHkOxPxj8/HF6qbB+52zUZV9r47uP2s/6Z9v7p5z1jbb2j2Tfu3m8bKGtsv/9uvH1q5ebLvqax2WeLG2DAgYW95tfD/QtbfXNrTa+7x9a3mAX0W62EO9rbZ8ysfH49Ogo3CbnzLXH+WPW/9YpvNP8TG/6xFH57JMw//h+8yXz1cGN7Y3l1/uPs5IeJianJuaXFjb2dvT+8h+nKbybd/Lqvg2J6vIVb/bzycY6FYOOBt/VySciNLG5wTim5P7ZhFnOjum/RJ/Mm9OvbL0chCMy9DakNaX68Phm43T4ckVf9anz14duxR6+HWl70PXszkJpdfau2PT63urzlzcPhuRvt3bcHJ+unF99N7XYMLde19UFeQ+d52PN+cnsHOK79A+XhzhdoO9DB59Y3uycnYZP+rYlDMDc3B1+A8bVUwcEE+q17/Cco/0j8myXhD25sbEB6fntC8Cqz8B3AA15YmpmYHBkaHhkbnZn7tL67vfe11MB74CPz8/NwMzBUwN+B0xXGwSpjH3Ycqxvr4OWFD9MsKZX3KO5hWja+ZO/YlPoXsIl0yaquGfgcnF8DPQcaTlBedUzZPQiYp/VvphteTUTl1bwYWap/3lt9/0VFfeud+889/FKSsqoCE25UPOmGDeXt9x9uj85Uf5h9Pb79vH+prq1/7POXkdXt2vbO11MTYxufoSwu7+xtbO5tfd452v17rYQJ6Y+1fHZ29vXr1319fSsrK7tfD2aGfsP0f4SSaUlIUsDxzZjwNrgOz29/bXN1fnFq/MNg/8DQyPD0p9m1HdiwMVZXV8GPCwsLY2Njo6OjQBNuZnFxcfZgc3ZvY35rbXF1ZfHT3ML4FEtxfde1yrbYvPq4/NrU0vra5z2vPixMbB7ZR2YllDS+GFu5cfdJQ1sP+Ll/evHRi+6bz1+UP+2ML7/TNb9Z2vIy587TtFuPwq/VxGSWZVe2xJQ01XRNvV3aH1w97iArW8u961sPRz/cevFq/IgxsL2X3/L4wfAYxFBPe2cWV9bXvu7ON6A2jSxtPB2eHZie7PnQP/55eGT9fX5Drp4z3cTX53pja/fw+8W15QPG1/GDqcOvH2XsHjH2v3z9Ye94voMpFcrFHmNv4wge0tbn7eMXv8C79zfXFqYnhj6OD+6uLTK+wNPb3VtfWp2b2liaPdxaXZp5uzDe/rH3wcTLhuGO5pE3rydHPn6cha3u6iawm5wa7X4/MjA4s7w0d7Q7zdjrWv/ct7I8ND0z9K6798nj3pZGlsK613nV7bcedBc1tDe/HoH+AM0BFJR5Pe/ug86Juazb9/LvPhpeP7z3brTofntBa2d9z2hqdXPv4s79rqGSxqdJ+RXx2WWugfERmWX+meUwML38tNW3uAb0P63N96xtv1laq+8d7Fpeb/0wk9lw/97AKMQfthjD8ytQ2iHRjxPocH92a7+1fxLOx+c/ltSXOwTbkxwNjdxhdVcxtAWU86uL0DFhfv4Dyi9fUe7BQPjtN2Xw9P4+AyB+Xlz7vLi6u7kBfZhxtL2+OjszObg0PXq0uQynIAg2F2d2V+cYu2vz4y9nB1on3zQMP7898OTuQGf7SP/YxIfl+Y9Tq58+zo2OD73p7ut6NzI5ObGxBlvEyeM572B2cWW87/3bB/efVZWxxOTW+ieWFNS2BaUWgiVTy2oaOt/devg8Lje78lFLx+hYclVN1M2a+sGZwhcD8U0dfkW1sI/0yylpeNXf2PY6q6DI0cklKCDQ0NLZOTjBITz9+oM3bVPrfcub6wzG0u7m+42D0X3G04m5l3Of63uG02qbmwc+dH5afT+3OrYAnoE0O9g7OK5Ky/uMppfdr3qG27u6K+rvxuakxxfkVj1+9vDdeOOr8e7hgdmlheMf6L4wW/7RsQN3do+OtuBJgOn+PgccszxGt7a4vPxpfvHjx7Wluf3t5YOdpbXlybmP/TPD3etzHxhbS0cbC59nx+Y/9K/MjGwvTX8c7Jh4+2DoWdX7+6U9DyrfP2/pf9czNDgx0v9udmxwdnCwv+Plq6cdXT3v3898Aj/2f14bXlqZmPw41t3b/6S1q6mWpebJ+6SiuzVPu10j0hpf9iYVV3RNzz0fGg2I8Stvqrj/9kVydVXYzerCN4O5b8ciHnbFNrS3LezHlNc9fDfwbnD4TtWtIA/7krQ4Y3NbJ/8IC7+Y1JonzUNzb+Y3j39wYzAGto51/Fvc9vGaWf/o4cjHkT3G4Ow87FnBg1tfjhY3j4OZ1bXCmro7d1syrxVfK7z14Pmr1jf9N+48TC68m1sFCT40NTe7sbN9CJyOwe0zDrcZe2uH+ytfDtaPXQZXvhwxUcJIsDH/afXj9PLMh7W5DzurM3vrU5vLI6tz76f73yxPDGzNfVj/ODo/2jsz0LUw1rc2MzLT1zbe2dj/oOxd/fXueyW9Txrev+7o6+nte/1k6v2b2b6e/mcdHS1PO1+8ez00CZvgjuHxzp6Bl22vOptbXty503GngqVt8NONu0+bXg46hydUPm4PSs9q6e6pe9Fu5miUXZJZ2FCRcLM4uLg04d7jtGfdnhX3IquaH47N+aZdu9V07/GTRyW56f72xmXJoT6+gSHRyTZ+MZGFdcVP++52j47vHA4sLb+e32kZ+lTVOTC6x+ha3EuvfXx/4ONHBmMDdmZfd5arR4wx2LmvbXT29oXFx5WVVzo7exvSbONTix6/GGpo7YlKLzV3D+seGhmbnl7ZWD38cvzj59HBytH+IuNg8WDr09HOImMXOurW8U9RsAPdg6Q/2JifAPetz41uLo7urIKGN5fery28+zzRu/VxcG9+FNaV8e7lsXcb0/37C2Mfu9tH2xq6G268rcnuabzR/+RO38vWnjcd3S+aP3S3T797/f7Js1cP2jrbu1/2fHjePzU8vdDdPfSk8VFdftHNxKSiuAiWu+19uTX3q1o7vePTMipuW/j6BaSl2IUE4inakanRoSmxgSlJXkkpXunZkOYmoXEOEVEppWUkC4u4lKTEhOhAD3srfY1QZ/OEmNik1Cz7gKjAnIrk2qeZjc/uD3yoftnV1Ddzq70/7U7ro5HF5v7ZxMoHd99N9KyCew42jw7XvjCmt4/eTs13jUzW3m/28HKNiwtLTEwMCIhwdQ+7UXpvfv14fJte2+wZHhsan1xYXTw6Ho039nZnd7c/MI5mtlc/7H6ePtiY+7K1xNhZZ2xvMrZA25uzQ9tzI3tLI/vLw3vL77cX3q3NvlyZblscfLk09Ar0qQ8APZ3pfgZX1j90f+xqH35U11Wd8+pWcndt9vvHN3vbG7pe3O/rqB979XC840nfg8ddDzvetg+0vxpvbh+a+fR5sGf0ef2jhryiqqSUkoQoljvP38Jup6q1I/1WdWr5TdfoSLtQf0M3B6wOwScs1MLJ2cHL2yUgwMU/MDEn18zROSQuNDUnxcHZqrKqJDsjMTEqJNTHNdLPI8THKyo61t43LCy/KqOxI+tex93e8dKnLys6huq7pxMqWmLLm+Nu3odpH8ZVaE0jI72Pnj9tefXu2dBMS8/Yg5dvK2trQkN9szJD792rvnOnzt8/2tUjvKaxdXFna4dxACj7R8Y/Qf88tvLa9vb41uYg4wvk78DGwtDO8uT+59nDtcWj9ZWj9c+HMPJMvNv+1He4PHi0MrC3+G5tun1+tOXjYOPEq/vjnfeG2+rft9b0PKyCdexF03TXw4mO1r7Gyo6S5LbCqK6q5J77N7oe3+xovd3fUTfwvKHvQf3bhns9LZ19L0afPh+qbHzd3TX06vGrZ7ebH5dUPiosvl+cz5JQWBFXcDM4Pdc3KdUqwM/YwxVvRdcwo2IIJFe/UB2ysZm1naubh5eXx42CXE9Xp8AAu9BgFwc7WmP9zdSEqNiIkMiQQE9nZxtjI29vXxvPoPiyhrKO4Vtvxp7PrkOvv9U2/OrTYfqdNvPgDMvQLAhaBpfjyltKCrODw8PC0nNhKqh6/q72aWdtQ/21rMTy8rjUlKCw0ODo6NT0zKKiitutr559WBrpGfrQNzT6cWH26Nimq5ubw5sbfYwvY58/9q7P9m/Nj+wtTx6szB6uLB6uLIOWRjo3p98eLr0/Wu7bmXu1NPZoqq92tKty6k0LoBx6frf30W1ACYkMpzNvH40/fdR1p/TJ9djH14JelEd3NWS9vF/4pLmkv72m53H1q7rKzpo6QPm+c+zx44HiiuePGp89uH3/flHNw4LyhwWFdbkZLH5J2bqWDjgK3cY7wC0wWJ9moozDqeG1DA0NHb4edDrd3t4+PDw8ODjYysoqwDMgMjjY0pScEOsHykqLtTA2drF1MTU19fD0Do2C51Lz8FV/eXNHWPatsGtVhXc7iupfxObd8YrJz654RLEP9k8sCkkr94pLz6tpLLzTVN306FZ13b2mllftLyODQ+9Ulob4eyfGRD57+LCy9JaZoZmvm9/A2+E3Pa97B7snpgc/r01+OZqD+Z1xNHa01/95vH1hsPXT+4erY22HCz2MtSHG6sDBfPd8b9Xu1APGUgdj7sXBdMfOh7a5d/f6H5b3P7w1+qwGNNRaNdFx9/PAs43h9uW+1uGnee8a057djH1cGPPkRkpnSd6b0uKusrI3HeX9b+tePq28XZJRkpNWf7OipeZefdndpqKChhv5d6/nwnqv+EZzSSGLY0i0sr6RpIoG0dTC2tXdyNKCZm7q6uWmr69vaWlpbW1No9FsbGyCgoL8/f0tLCw8HD2iQkIcbekpiUFx0T7pyVH2lpZh/mEUqhFMRV7+wQmZ+aV1D5IKqtwiM3wSC8obO0vrOyIzbjpB0b1eS7L0gR1RWGqpd0xKXE5RUk5RccWd6LhkFxe38NAwGoVccC090MfDxpwOTo8OjYwKjvL3CPB09IlJjG66X7u4PHH8u8fOxMJs5/z0s9X5jvnBRx/77oNWxp4dLLxjrL6HdWPqxfSbsvXRhqNPTw8/tu1Pte9OtC/03B9qreh7UD785PbAo4q3jUUgCN633Hx9twA4dtYkPimLeVKU8Kw4vb0k93lh/vP86x2txX1v7r5pu1Nfcb2iILeuDKaZiuspubfSU0CVmWnVOZm1eTkgFn0rRwm0Op+0opoeydjaimJCo5kZu7o7aWpqgjGNjY0NDAxMTExcXFwcHR2pVCqdQvd1d7egG0RHeAb62cdGBtiam8eGxZIphnZOri6evoERcQDIPybV3jciIOFacc3jG1Ut/tHZxnZ+oYnXtal2XmFpvpGZCVk30vPL8oorHz3ryMrNO/a7v6+DvbWfp7O3m5ODtYWpoaE5zdTewt7G1NZIzwSqc0ZW/Os3jzc3PsDszziaYOwNMvbeT/c0Tr6rn+ltWh1/erDQdbQEHNvnBh6MddxYHrizO/Vwd/LJzodnW2PPwJUDj24OPq4EM4LAnr33y2DtaS59UZPbXhX3tDzmUXH0o6KEJyWZrUXXWvJzm7Kym2qyX7RWvnxS11xTWlde2lhRVZFflhaZnB8dUZQQW5GReic3Gzjezs5gQeH1BOURogoIApkKfsTraKNVEFicsoaGBkAEmmBPJk3gCBd1NXQhozVxSHcXU1BkqA+cBvsEU41Nndw83bz9/UMiopMy/MNiPIMi0/KK06+VZebddPeNJBnZ+IcmaujQnDxCrB19I6JTcvKKK27Xdff0NzXfS09PLS27ER0VGh8V4mJvbW9lHujt7efhY0o1pVNMvZ39TEz08Xi0gb5qUqzncG8TgzHJOBj4PPNo8l0d6FP/vc3pti/Lb4+WulbHW+EKoFzqr9meeLA59nBt6OFKf8uHjpquhoKuhkJwJaCEFbCOt9WCwJudVYlPS6Kb86Mac2Pv5ac238htKshvyM+/WZB8/07J44bK+lvFDbduPb7bUF9enZeUfS0itCQpHiBCdkOy11zLYpFBYwSlZSURigSSnjHdUJeohcOhNNVQgA+qJOQ4rACUTCYTCAQsFkslUulUKkpB3NmBFuTvALXSzsLC28WbZGhi6+Tm6Obl7R8Uk5AcGhYBKioujY1NTU/P8/EJodEso6KSyGS6mxtwsbakWyfFphTm3Wisb6isKCspLbhVUUQ3J9fdLvdxd6bq64L3C3Lyc9Nzg7yDHSycoyK8zUwIBA2ZAC/j7heVjC+jjMOBz9PN0721M311iyPNO5/aGGtvj5ZfLY89GO+qmnxVsjpUByjXhu8v9DROv6rtuV/0uCy56Xps++2cN/U3OqqvtVVlQ2rDQA5839ZkPi2Jr8sMuZUUfCstuiYv825xcVP5zdtFec3VFU1VFZU3rt8pKXtU19hUWVOQmpMVGgQooVZClawvyINkZ1FQURWTl5NSkNPU1qAZk63Mqc72dD8veyAIJdLJyQk6j7m5ORMlZL013RoyWlVZ1tfLOjkhsLz4mqu9vaeTp7qOAdXU2sTCxtnFLSoqKizIP9jP61pGSmxETE56doh/sJWpZXpSmq2FDcQWJuaOdNucxPTC7NybRUW52WnX8lKuXU9GY2VjI4KS46LCg/zdHR1D/YOvpV1LjEqyM3Osrcyvrcy9f/dGb+edtZnnjO1uxu5bxsaL2f460OJI0/bsU8bqq4PFDohHX98ElCuDtZvjzcv9jR/f1I4+r+iszWnMjwKUzyuzIKMfFCXW5UTA6eOy1NbytDcV6Q/zo2/F++eFe+fFhJZkplUVFdbdqrhXVf2orr7hVmVxVk7Ztet3yysrrhelRMQk+XpBjldlpUOtBKbZYcEsqpqaSliMqgbWgKxraUlzsjPxcbMK9XWCvIaGAyXM1tYWsOrq6mp+PSi6FHMaDYuW8/O2gXKZnR5nZmRkY2qjrKFLMKDpkQ3hAUSHh4SAqezMI/3dYoJDspOSA9w9TEgGKdExzlbWsSGhDuYWoY5eOdGJuUkpFUUFackx4ZE+6dkxNAs9CxNKZEhAZkpisK+vmRHd2MDYwdLRx8U/IdKzujxj4HXj/PjT2YHGD+9uzb6v+DxW92mw5mP/bVg/T97bnW/d/NgyO1A92HljpO36XE/l6lD9fE/dZOftoSflL+5k1+dGPCpN6byTBygb82NuJfvXZIbeL0w4ppkbXZcSXBjumRnskR4ReC058fq1nBvXC2pLbjfeqrt9ozw/Gap7dtWNkoK0jFBP73gv95zwkLKUROCYGRIY4+7CoqlL0CHpQmo7Otm4OVvZW1DpZC2qLkZZWVldXR3SHDoPiUTC4XAqKiqQ4AhpBEBFyos52Ru5Opn4eTnilJX1tfVVtPTwJCMdfTI0/bjIUJjbHekG3rbGEX6+qdFRLlaWeIxKuK+PrYlxTFCgo7mZC8XUy9TKz84+NyUpJMDdzMIgKjEwMMo9LjKYRtaDBA/19w/w8lNHq6soYsCVQZ4WhTmRb55WzY+0rk48/jx+b2uq6XDhGNx0XyVoYaRubap5daJpqrfifXv++8fZ0MQX39+ZfVsz8aJq+OlNcGXT9eiGvGjwIACtTA0siHQtT/RlGrMuwe9WhEdekEtGkHtaeFB6fGxaSmpKanp+Ul5ZTnFRRkF2XPqNtGu3C0vzU9ICXd3BlXlR4YASmk9qgG+4kz0LRkWNQia5OJl6eZg42+pYGKmZG2hYGRCodCM5pLIShqBPttXE09W1KXoUI209AkpdQ0ZRFq+JDvKyTY72A/pEsp4myQCJo2jpGFmamPo7WcX7OyWHeyZG+8dG+1tY03X0tIxNKLZWpp6OdjiEQnxIUKi7W6h7SKRPcKCbk4uVkas1zcfR1pFubaBGqihMjQ9zd7Emezkap8f5l+TGZycFh/vZ1xaFNFfEdDZnjXXeXOytXeqpnekoHXmY+/ZB5sCz69NvK1ZHGtfHm+f6at4/yWuvS/jQcv3jsxsLLws/vswdbE1/WZ/0uCLpQUnqzayIe+UZZWmhOaGu1anhDdmxd5LD7mXGpkc7+jnS7Iwo7jYukYFxaQk5udkFxcWloSGRcbFJSYlpiQmpyUnpKckZEeExMKkkuprfCPeszYiqy4wuifbN8LFjkZNHaWlpWFiQnR0o9lYEK5qmNVXHjmZAMCBIyMnJIbDqWkYIJQJKRYtAImnra2PwBEVlhC5elYnSy93OyJRGoptitE10Saa25pbBbnaJgS4pEV6AMi4mwNnN3siEbG1j5uxg7eFgi5AQ83N2tKcZ2dGs3a3tvR1s/FysogLcEkID/ZzcjHUM40LdgjytPB1o/m5GeGdzAAAgAElEQVTmCeEe11JCc1PDMhMCa4simm7GPL+bMfC0ePZN9fzbakA59ji/+2H26Ivihf5a4Lgy3DD55iZcAZQLHbcWO8vmO29Mv8gZeJzWfieu4UZERVpIaohDWUZIboxHqp9NZXJQQ3Z0bUrog2txhWk+4V6WTqaGbpYOwR5hUUGxsVGJKUmpEUFB8ZGRCVD+Q0JgbwKnXi4uUOKSPa1yQ1yLY3zzw9wT3S2CLUks3Hyi8ooKOkScsYmWGV3DgqZlY6zvYErTJGpIysvKo1TRWKKYlLKMIhqvT9QhE7A6uiiMEqD0cjKNCHB2dbIElBRzCxUtYx19urWpObgyxsc+NtA5Mtg9NNjdzdPJ1ILm4mrv5+0W4OGqJC3pZW9rrq9nqkezM6Z72VvGBLnlpUbmp8YHuXkY4cmO5gbutjQfJzNfZ3NQoLt1VIBLcqRvVV5ETUFk883Elw3Zw0+KJjvKJp8Xjbfm9bRkTb0u3xi7B80a0nn4ecHb5mMPAsrZ54UTrVmjT1IB5Yu6hDu5wQXRnomBVqUZgdfjPbNC7G+nBtVnRVQnBTRlRlTmhsQHwKaN6mRi4WHj5u3o5ePmFeDjG+BoE+buFOrm6O9g7WdvBacupkYmBI0AC3Kko2mipy0oxsUCxMLKISggKqGMQejooQ2pODpN28aU4mRhrmekg1JVRuM0IccFRRWkFVC6ZD24CCjROBVIcBs60dXWyMyEpGtA1CZTFFUNoAiYUAxdLYwCHemBrubQvtxdLSHByYZ6gDI0yDc2NAiPQYf7eDmb0p3NrV0szcGSSZEehdlRuSlRPo72JHVta5qek4Whuy0dVguqjom+Jqz2puTrCQE3kgJuZobeK4p9VZfe35I78vjayMOsN3eTJ9qLN4ebtkeb57oqBx/ldjel99zLGH+QP9CQ2lMX09ccCyhfNSTX5YfmR7oXpXo/qEy5WxRdnuJTfy3sblbIzRj3O8l+FTl+sd6mDhRdKxLFwcjKwdTWydLG1cHWVl/TxYgIcqQQXGl6vpZG7iYkK101J7KWF10/xM4kwsk80tkixs2a5aqAtJCkPAKD0NRVIRuq0+l6thZ0R2trAxOCigYaraYGxuQVkpBFInUpOlr6qhr6JA2Cpp4OzoyqZUkjkPU11fEakPUKGBJO08CIRHY2o/raGvk6mrg7mjo50HX1tdW1VCHBA/08Y0ICCaoqTJS+js7uNhZeDvSYEMesJH/wnZe9tam+gYuliZM5zc6EYknVMyURjHQ0yFpYfXWVGE/nOB+n9BC38hT/h8XRr+tS3jenDtxPbbsZOfggZ/ld9Vpf3ccXZUMt1/qbs2AdbMjqrol/czv8XUNkz/3EthrYmfimB9jdzPF/Vp/VUpl0OzugMS+sNiPgZqxrbYpvabJLuLOBBQFD19Sy1KPaUk3sYY9nZWGmjbEmqlvq4Ey1VCAAms6GuhYErAuN5Glm6GdNB7nTKXYGBBZROTVJlKoiTgWLV9Yl4SiGBGMaxYxmiidj5dEyMggFUSk5bgERlKoKWFJFS0HLgAx9hkaFBoU3N9SmkLS0dLVVCTrQdjQJhnSqkbuVcZCTaZCbha+7tYebFXBUUlGEtuPuYh/o6aYiJwMJbkrUdbYwAwPam+kEehrHhtpFBtgHuNn6OjmAN+ElK0NASbYzoTmYmlgbUU1Jeu4mdB8L80hXm/xIz6b88Jd3kvrupQzcT35eHNpblzLzrGih8yasow+uDTZlHqsh6/3d5N67sYCyszaiocA3J9wm3IGaEWlxtySspiCwONGpOsPrToZ3dbL7w+uht1KdIx2JFpooI6yqqaaOqY6epQHJ3phsroe3JOlARpOwyhR1jBlRm66jCbETjeRmSvWyNAZBYEvWYRGSUxeUUxaWlxVXFJNBiSOUZFAohBJSBUtQFJMTFBQXFhSTFJWSJVL0ze2NcToIJQ1NbSLeiEIAV5pSNA3JeIL+cdYjsGRmggPKYGezYHdLf09bLw8bNU0MCq1gaERycbTxd3dRlpEClGZ6RFOSLo2oZmWs4etGDvYx9nU19ne1jvL39nV0dLOysjM2tjY0PPaFhQWcgiwJBg5kapCtVW6YV3NB9Ju7qYMt6SOPUjvLIt/dThi5lz31uAAEQe+d5DcVsW+rEntrE983xAPKpxWBlRnOqQGmYfaUKB/9smyPknTXnAjzcqCZ5lGf5dNZkdBc4J/qbeSgi6Fh0IYYnIGKKgmrYqiJIREIBjo6BHV1VRRKXUUFTkFaWKyjMcWBRobVyYTqTDeElYVDGHlZQPIiD9dFHlY2ngvsXJfZr3CwXb6qoiUjJMXNL8YvIiWFUFGxdrL2CHAkGmFF5OSVsWgiAWtIVAVBguP1CJDg0igdNFaXQtR3pJP97Gj+zqberpZQK5kojWgG4MpQXy9NZVSEr7eruZkhQdNQB2tD1/BzNwA5Wem42RiH+3j4ODh52tq7WFjZGBmbG1AsKYZOZhZwxRinZ0OkBtpY50f4PCxK6LmXNfYkZ+JZ1tvKuJ7qxIG7aWPNORMtecONmW9uxTwrCHqcF9hZHg618m19ROtN/4p0p6xQqwRP8xg/g/IcT0CZFWZaGu9wO9W9Mcevqya143Z0QbiNB1ndRFWZhFLGyytoyEpqIiRV0DhVjLoSCiMvh0QrY4m6BmQDI10dkr+jnbulmTWFZKKjTdVUI6tjWa6Ii3OIibGJiLAKCV0UEDjPx3eOl/csD8/fTpz66cy5E5cus/LwwSZdEaumoW9ApJlgiVhVXVW8IZ5mSzO2MyYYEXB6ODV9NSQSicNiSLp4uqGBnSnVw840xN0u1t9FH6lhoU2la+hFuXoF2TkY4bChTnZZ4dCZKfBpV0uDKD+HhBA3aFNwxdPWECMvStbGQMWEkdPf2dnFwsaKQjfVM4Q9lbO1BQyhbuaE1ACTtsrIyefZU8/SG7Idm/NcHxd5Py8P6KgIbr8V9KzM/0mJ7/PqKJjSodtUZ3lVpHo2F0bdSvEJsyW60dXjPOmFce6VaT6NuYHPy2Ne3IptKwlrLY0uinL3MSEb4dQJSjgNZawSCiEnL4n6h5QVpTEoOTUVhBZOmaCBgUIJJdLZSN+WhDfD4yiqSBZOSUmgyS4qCigv8PMDxNNcXCevXuUQELrMy3+Bk/ssx1XQ+atcl7h54YoESkocKamAQ2gYaGmStVGayjIqcvJYRS1tgiGkpJ2Nl6ujl7Otq7Ux7HbsaHpGanhLXRIVqxZgZ+dpboJHSNuSCa50kpst1c5U19FCP9DDMtjL2tnKwJyqYUZRJ6gq6OKQBpqqdH0dKyrVimpMJ1IpmkSskhJNX9fBjOxnT86PdnhVm/jhafZgc9yDbNeWHLdHuR6t+V5PC3yeF/q1FweAmgp9WyvCmosDy5OdSxNcqtJ9b0Q7RzqQXOmaoc6U1EDLvHD7m4lu964FNl/zu5PiWpXinuROt9JSVZeSQYnKICTl5GSlpWXEpEQFpcWEZMSF5SRF5aXEFKTFFWUkQPZUoh1F18aAYEHUNNZSJWNR/+7KS4KC4EcmxxNXrrDzC4IfAeW5K5wgCIAj8L0ixMUucJVPUlBWRUEBixRVkBCQFhaRF0epYDW18FQq1czUxJJuZEUjWRrqWhkRKWpq5no6Bji0j62ZmwVFCylGJ6KNdVBaGBl1ZUmiBsLaRNfNjuZkRYHpCmRvakAjqhMwSLwKiqKlZapPAUsa4UmqSgiqLt7SUMfJWDvJh/7gRujb2oTOW6FN8baNcTYNsdYgiO8nOTxMdX6c7lqaZF0Ub1EQY349yup6pG1umE26v3mCO82Bpu5upu1jRQi2J6b4GBdG2hWEWKS465fHO8W70Ky1sVqy8hgpRYyCEloZhVZByEoAQXGErJSSgiwIKSetIC0BF8lqKtCFQBBAF9JFI1jAiSDI62+pfYabG3TqMjtTYElgyikMT0dWTAFxkZv9POdlDkFuMUVpSZScgLQor4SQkKw4VBJZhLKMrLykpKSMhKiyoiwRnGVAwCpImehpA50At+M9jJ6mrIMF3sFCS1aMR16CD4OQIOExFjSirRnZmk6yNNbzdbZ0MKPADKSjqoxHo/VwmmBJQGlqBG+gQqcioiVsiYgsP7O6NM86cFOQye1g+p0w87oIy7uRVkxBnBVCSfDCx3sSMoOMs4LMEjyocW7UVB8zWyMNG0N1K320DQnlb6md6GkY40T0oaHyQy1inQyd9LUpGCwehVVDYQAlSklemJdXXFBQTkICISODlJVVkJKSFhWFb6wsLY6WkcDISWEVZHCKsrCy/M7BAR4EJ4IfgSMABbJQNCGdIanPsF85ycoGgoCZ4+eucJxmu3yJm4tfUkJYVoZbVIRTWAhiZQ1dRRV1CVlFHgFhDg4Ozqsc4kJ8kAjSgvw0Pbw5lejvZutgYYDHyThZ67s7ULQ1lAlaKrBr0tdVoxpowyQAs6oGDgnNB+qss4WxMRGvjkCgpeW1UFigaUYzsDIxoOBV1WQFyEqiQab4NDdasgMp14l4w51c5mtcGWReFWxx059e7GVY4GaQ7Ksb5aIW5aKR7ENO9KREOOhGOZEAJZQUO2NtUz00XQcBdTPKjQrXvU0wIZY4L0OcpSZGXwmNlUHKiUoJ8PNycrGd+Om3s7+fvnzuEuflK9zsnLCyX7jMevaiGA+3BB+vtKCAnIiwgpgoiOWXy5d/ZWMDoEyaYEwmSjY+gW8JDhAhhuwGb55mY//94qUz7BxXBIW4RERZeXgvcfNAzCuuICyrLInAyCgqSYF/4RAVlhITFuET0tPW1dMmWJgY6eE15KQEDYg4kq4qDqusrYUj4NVBJH0YZslUih5cgcbi72oT4unsYmlKUldXRyjr4/CWZBNVJXkSHgso9VXkzDWQgSZ6oSZEN22Ur4F8oCEyjK4SZYEDhZtigoxQfmSFeE/tRG9CgpdOtAsh1FYr2For3J4Y5QijAsXenARF2URXydFIHepmjIdRmIO+B0XBiYgyU1MmIpXQEvIS/CJcnFfY2C+c+PHEqZ9Pnfv93KXTl1jPsMJ6/sT5s7+d5efkFuTmFeETEBMQEhcUhpUFCP5TgQ1BkN0XuYCUsICUjAQCJYvGAFmmSY/rpqAwkzVw//Ecx+krApzCMrB3EpOWB5pwKMjLivDKqqK0JYXlVRA4NEJFXFhEVVlJXFgIaoa4pIisvJScgrQqDk2m6lMMSZraahZUAmwTYcNjSSUBSh2MmqG2vjXVVBkhqaeFphKwFBwKKloQnRxkRHTAIj2Nke5Gis5kWUeStIO+lJOBjJuhggcNEeOmkRNmmBlMDbRSdaMi/M3Vgqy0PY1UaSRNE4oWRUdFV1WKoikPXSjEiRzuRPEzUXYnY6DtgCtVpREK4jLSUhIysuKifGIivKLCPCKCXEJ8V/i52Xg4WbmuXuIU4RcWFRARFxIDiQmKwikLs0RCcQR84E0w6U+XLv148eJpNg5ABsMQExwABXZcImLsfMLnr/Bc4uLnEpYAsXILXOTkuyIgepZL9ByX8FkO/pOXrp44e/HsxctXrnIJCgqK8SnJiuIunOAR5pFByeHkJBAYFPYK61WOq+zwgIREBHn4uIVFhRAoRXlFOQEhfhxCAqsooSIrjpIURUlIqMgoQILrYbXBy6ZUgqEOjoCUNkIjvMnEEBrFQ1sjNcw8xpca4KjtYanqboHxd9CK8iYnBdMjnXE3Ys3yIuleJkhrvLgPXdXfXMMGL4tRktJSVVBXlkZKcWNkuGnaxzR9rXX86WhXEpqORWnKyCFFpAElDENq6ipYpDpaXlVREiUlJCvCI85/RYiXXYCHjV9aTEpGXBoEgaSIBNBkAUOBrX67cOmXcxdgBXa/X2T99fxFEMQAlOlNcB/0dEAJ74dWDkWTORtdFRLhFZcEz17kFLrMI8rKLXKOg//3C1dPXuKCmFdMnktYBlZBKaSwjJKAJAJO4W3nwb+8Eld5xK9wi3FwicIKp9z8UryCMhxsQlfYhTivCHGDC3iFBAQEhIQEhIUFhSUEJWWE1TXk7a0IUYHGGVGm12KM8uOozwrM5ttiFtrjH2ablQSp30s1e1ni1XbdLchVMcIbfT3FqCCVFumjEuKO9HOUNdQ+H+om62sj50iVM9NSoKkijLFK5poq1mBSFIqsqkrG4bSUUQgJ8BqfpJigvIw4WoxVDy1sY4B2MdFwMMTaUTAQ+FgTMbKKCiISiqKSOAWUBhKtJCnLwkxY4AiCgDn6ADtACWQBK1PQyuE64AN7QukExACa6VmIj7s8twgHv8QVAUk2XjEgBWLnE+cRlWNe5BSSBkHA5HiGjfciG/95Vt6zF7nPXOACQXDuEg9cOX+W69IFHg42fh5uYWEhcZgH5ORkFBXlObiOzYvDoews9EK96NE+lDAXzQBbpaxIal2hZ3Wee6Q73s0EEeKID3XUdSArWhIVoUcHOZDCXKjQXvxtiRFuRk5GqiEuCr42Ck6GilYEZQstrI2OhjOZ4GGsoyImpiQsLM/PL8XPK8nPK8LPLcjHycfNgRS5pIXgN9KSMyEoGuAkCUpCRBWYhKRkBUUF2Tn5WDnEufllBEQkeARYANmPp89+f/I07G2AF7gPeMHKRAaMvhVNOIXrzHbEfABML/989jwIzHiJSxjwgSAAXheuCgJfIAsCgnARnAvXz7LzAUpwIjunyOUrQqwcgpfYBWBluyoMV7g5xfl4JIUEpMXF5GSkFRQVFZWUkCoqyjx8UiIiMnIy8urKSJI6wlBdRl+JR1P6PEaFi0JWIOnJIxQ4FWS5tDUUcCoygryXOH8+efWnE5KsV6Uuc/L+flaBk58gi1TmF9VBn1STO4EQOCnBfkL00mkJtnNyXBeQApcU+fnF2Ni4Tp/munBOmPMKoOTlYmdnPacowoaT5yeqSulhpTWRwhgZHhBckeIT4r5w+fKJM1fPXuS9xM51npUFWADKH06dARzgL+DFJAjIgCZABL5MlPAqxEzQcAoo4THAA4DPwpP4+QzbiYucgIkJCxL8l7PsP52+zITIdOLpyzwgCOANkNcADsRMcO7je5MVgFlfFCkmoigqLCcsJCUkKAYJzs/Py8fHIyCoLMCvyMUhwnP5qjQvFwEhYaImb6ouY0qScrXCOVvgDPGSVG0ZO5o6TI4kNVkNSWmsqDhREaktIyfPya0uIUVVUYXV3kTaVE+CqCKsKsmPEORSFLiKErmClmBXFhGR4+ERYWMTYL8MKIX5uAR4r/JwsimI8cBeVltFTgd2dGhZdZSUhpI0nCLEpISvcPNcZBPi4BK5ygP2ZGHOj0zTgd2Ym0VgB76DvAbKIGYNhRXibykPp4ASHgDzSfx4ihXYAU0gBYJy+f2Ji3/+6TRcgZiJlSmIfz3H8cMv50E//Xbx15OXT527euEyH7gSmPJwSXBdFb3CLnCZlev8OdbTp0+fOPHbb7/9cv682BV2KS4OUWFOIS0k0sfSJC3AOSvYua3Us/tOWOfNgIpo0ywPfK63wY0A4zwfapgLOdhRP97XNMKNak9RcjXB+lrjzXVkAz2IHnZ4a0MNQ21VfZwySQ1F1UYYExU1ZGU15eRUpaRkhQQEr7BzsV+C7BYV4pUTFUBKiarIS6kqysCqLCuhJCMOKxRKSG3Ia6iSWHkkSkKGBZoGNBMYa6CBQAArAGXOQOA7MB0gA8pgUoDORAyn8CqTO6wQA33gBQJw4DtI9lOs3AAXUDL1bz+fAX07Bf3pr7//+bsTf/n+1Pc/n/vlBCuTJqQ5tB0ONkH2y3zsbDzsbJzs7OxsbKygEyd5eXnkZCXRsKUzJmgFOZhFOpt607XL/NXuROpXBOkkW8gG6fKHG0gkmaLSrTCOxtIONKkAR1UfW2UTAq8ZUcCaLIpHndPE8Ksi+BESfLJCfHLC/MoywhpoEV0NUR0kUk9ZWRuBUIDJh/Ui67lTV9kvCgtwC/HwMCXABUMM9ARWtvPnWc+ehccOtyvGxQccdVXV8WgsC/RlZkeGlVkHIZHBbrACx+9+Pwm+g1eZlJltB94DnwL6IOZW/Zj7JS7wGqQ5rBAD1r/9fuF/fH/iX/72+59+PPWXX87CKeivv54DjnAdzMjU76fZT569Am0HGhGUTmYH57oqzAujnICoiIiIuLiohITYuQt8YmIwMqkoy8kQ0HJW+hi6hhRW9BxR9jRJ4QJR5rym6EltsfMURW4TtJCxkrAtWc7GQNbLEutKV6aq8dPxonCqq3QFg+BHyfDLi/HLCgtBp1ZDSZPwCsZkBAWLJSopYaWlpQX4+NkvX718gZPjEiQ4+0W2y+dZL529eOH0+fOnzp09cebkLyd++/FX6Dmc5y5BuYSeA1syZSk5FmaSgsB9YEPIXMjWP//8K8t337P865+P9ad/g1IIVRJehbfBq4CYOTkx6yzg/rdffgOCkNFgPaD2w8lLEP/rDydZ/vQjXAGCzNxn4oZXv/vtPHRtcCJABJRMmqfPc8JF6OAXznGxwlafjefqFR5ubm4olFAuz5y/IiQkJSkuIcbPiZHltyYpO1IQVAyXCVmVoovSUVPQUUMYETXNKHpkbU0cQtGerG5FxDgbaVvrqeIVhAxUpMzwShBoq0mpoaWV5WCulEbLy2pi5A10ESaGCDMCAVAihITEebjEeblFBXigVnJdYT1/6sLZE+fO/H4WAtZzl9kvcrBdgG50WZJXEDiynTwLqwDb1eNa+T9+//5PJ3/8y5lfvoc90qVTP7GeZur7U7/8eOa3Xy+cOsF69jT7hTMcF0EQMDs+4PvbiVPMSgrBMfp//YHlu9/++tv57347+6fvf/0ff/n+z9/98N2Pv5y8ePmXM+d/O3fxNCs7rH/5+bfvfj1x4gLrr1ABLnD87fTFn89cPHPx8kU2dlbY2l+6ICR8WViEQ1SUU0yMT1xMEHafosIiIkLC4jwyMgIyikLiGFERQ7SsF0UthKbmq69ogeKzUxVxx8v6GygFUVUCKWgfPYQHQc7bWN3TCOdGwTjqoWwJChYa0qY4CRNVMTRSHIMUxaJENJRFdTFiVA0pE7wM1FB9PFJdRUJBik9U8CrktYgAP2xgBPmFLvAI/XKejVNI/MxldlaOK5KS4hfOn+ZgvwQlVUbweHJiCmKWv53//Y8Qf7h4Eq58d+63v/7+43cnfvrh9K8/nzsBQH+7ePr3S2dA4EQw5l9+/R30199OwPov3//I8m9/BY5/+fXcz8cthe37E+f/+vPJ73459dPvp388df5vv5/56fSFU6xXTlxk/+HkuV/OXrpwlfcsrzhskM5zi7ALiPGKSgiJSwkJi/ILCkhICMDuQUZaXE5WWv5454mQl0HKy4BhdNRV9fXU9WnaRHe6Uby7baqXZawjOdxKL8aekuxGz/SxAqW4m8Y6UCOs9SPsDcLtSMFWun6mWh6GWCd9JTsdRWttOQ2MrAZGWktVioiVJmvI0PHyMIHakRBG+mgddTllBRFpcT5JUSGwv5SErIS4rLCCyhVBKSmkCgefIDe/AAKB4LzKwcfLiZQQUxQTkRcRYjI9RvnjxXM/XToPguBv507/5fSJf/39l3/59ad/++Xnv/z6y19/+/VvJ37/4dTJn86c/vksDEx/RwkQmTr241//dlwH/vLLn346/cMpVqD54+nL35+8BPFPZ6BicP56/sppNl52fgnQRS6osFIicmheeTV+eXUxlJaCmi5G2wCjqYtUwckoIBUUEIoKSkiEihK4RBmvitbDYchqqhQ9ipepZZCTc6ifd1hyVGxJZtqtrISCuOC86KCCuNDSlOjytNiS5Kj8mOD0YK9EX5dUH4tkL7N4N+NIB3KQpY4XTc2ZpGyvi9DXUtbXQhloI43wSHNdlK0B2pmKcaepWlJxZDwKh5JESIvKS0vJyyEVFbHyimpITX0JBA6tqc8jLMkvLIbBYKGWCgsJ4BTlMXIyytKSCHFRJlCWv507C/r+/DkQBH85ferPJ4Hmbz+cAi6nvz95CtYfTwPEc7+eh/p4kbmt/LbLhBUq6Z9++uXffj7146mLJ1m5wWisAtKXhRXYxZU4JJR5JdHc4kqCslgZFV2QOFJLFkPEEk3ltUyROpY4ij2R7kK2cNMzslbVMlBAqSFQmiCUso4yWl8Va6SubqalZY3H22tQ/U3sYlx90oLD0lOSrhXlXS+5ln0tKSYnLjo/Kb4oPQXgFqYlX4uPSQkLjgvwzQq0zQywAaBAM8xW38dEA1BCptNJmmYkdXN9nLUBzoGCc6Op+9I1A8y17A01AK4mUgolIwnZgESqodC6KAxZUc1ACqWpomnAKSDFwy+Gw2qKCIkKC4oQMGjYYgJQoAn2lBMWZPnh/KWfLl7+9TLHCQ7OU1e5T3PygCA4w8bJTMnfL8DszQ7xWRjpr/Aw/3+CuSXnFhUHQQCnrJz8HPxiAlJIaQxBiWiKNXLEmXqqmXkpaprKqRkjtMywJHuMni0EyjpWeGN3VUMvDRMffetgmlMY3TFE39QVrWkoqaCpiMYronUU0UQE2kAZS8NqWGngHbR1neU1nAkmIVZuCe5+iWERKanJGZmJ8YnhoSlRkZnxcXmpKYVZmaDclOT02JikiPD8cGfQtRCHdD+rOFcaGNOdqupARNoa6toaEhyo2k6GWh40LT86PsicEGpJcCRjjTUU1RXEERLictIIBaQ2StUIpW4ujSZKIQk4vAmXgAy/kDQBbyAjqSAmIqmvjtPFYjSVkOBNSHYwJsspKFvcApcERK+ISfNIK/DLIQUVlIQUla8IiLPxilziEjx/he/CVdgUCrLziV4VlGDOTDAbCcnISaGUpZXQYgoIfklpTj4hSAFReRVFLaqmqZuec4S+e7yeRyKa6Igi2MGqTvVQJbkoalnDqaaRlyotUMMsVM82ytg51tgpmmjiiVQ3FpbTRuJ0FFXx8miCvLIuAkNGq5ngtK00dR0wep7GttGeAVkh4RkJcZl5mdmFWUsZJuMAACAASURBVBl5KXFZMZHgytKs9Mr8a1XXc2/lZhdnpF5PTiiO9QQVxXhcj3ABmtFOVH8z7eOiSdN3MtJ1NiS4GeG9adoBJvhQM0K4BcFZX8UEJ6cuK6ogJi4jpSSP0kPiLJW0nWRVyAhVCpHqICKlKiWDoRlaKSNxkmLyJA21/4jyAp8oq6DEVXE5PlmUCFJVXFlNCqMJ4pdQ5BGVY/48AZs/Dn4JbhFZPnEF5iQP7CQQKHkMFiSuiBSQkmHn5GGHSVZMXhxDRFEc1ayDsXZRaJtIpK6LvLYDrKoUbzTJQ07LHqHjrE7zR1ICVIyCtCwiyPbxhg4xunQ/ZW0rCRQZrU1AaWgpYLXkVLTkMTooNTJG20RNx0LX0MfeNT40PCc+NisjMaP0WnZ1QfbtvNTc6JAbCZE3MxKrc9Nr8jIqs1NKU+PgSkGk640ot8Jod0CZ4W8d42wYYI4HlM5G+s6Guq6GBA+KtrehVoCRVoiJdpiptps+2gwnrykrpiAqKSuNUUQbAkcVPR8FyAy8hbGljyxCRwFyiu6kjFQX4pfSU8NCjqsjFVVkpaFcHif4edgj80twiMjySCEF5NDCiqqiSBxIWFqZXxzBKSjDzisBuiogzSuqICCBhIzmEZMQlJZl/hIMrgR7AlweAWEeQVE+CUUJVT0lqhPWOkTZOkLeIgKh4yqv7YQiuuMM/VUpvkhdNzTJC28WJkv0UTTwUzUOIVrHUO1jiWbBGKKTPNYUo4dX1tFW1NCQxarLYbUQGnpovCGWaILTtKab+Xp6RAR4hUT6B2RFhxUnRZYkhmSFeOZF+hXFh5SnRIIguBbukxHkDoUyO8guJ9geiib0H+jmzM7jbKjnQtFxIWu7k7W8KBr+hppBNM0wE00vA4ylmjxeThIpLi0vo4ZSpavoemIpwYBSXdfWzCZIHkVUUMSb0OzlpFQ4WAXAktpoJTWEAlpG6u8ozwgpXBBDscuocilq8CnhQbwobR6kliACxyunwiGuyCose1FQ+rKI3FVJJLeMMq+IFLeQBL8YVAxlFFZLCactjVCB01NC/GdFxNikkSIYkjLJlWAWpW+Vqm+VYWAeiFC3UCe5UCyDlbSsJZUMMTr22lQPLX0zNZK1qpG7pnWYjkO0lrkfUpMmJodFyMghZeVRcgoQyEtKK0jJQKyCQMFYRMCibPRVg03V0pyJRUFmJeF2hWF2yU5aeX6UylibhnS3+jTXqjjb4lD69QDDHE/KdT/jwiDz68HW6d6m0HlcKFhLbQUTbYSDoYabCcHJQM1FD+dnpBNqSgqmER0MVCg4GbSUoKyosJycMlqNoq7nqEHxIOnZGujb6eAtNNSM8VpmRB0rLIYqLqqKkBNVR8oaqKAMFBW0xMWUhflZLomj2KVVuBTUBJTxwhhdUayeiCoRxCeP5pRCXBaROc8vDmIVlr4qqcgjq8QrJMYtIMInLC4ph0Bh1JRU1aXkkfwiEud5jwsup7iChJIORtdS19jHwCzEwCwMT7KVVMCj1Wl6hk5Q+0RlNJCqFFUtOhpLUFIjoXTMsTQP4KhGdVBQ0RESO4YIApqK0rJ/RIlQlAeUtiRsqLlGhqt+YaBpcZgtoExx1gaUFTHWwBF0O94OUOb7U5koi4ItCkJsMnyOXelKxVnhFc11lV1M8J5mRBeKhqu+GqAMoesHGek6UVQBpYqUoIKEmLISVhNvrKlnq0Z00CGY6eqYa2uZ4LAULU1jiFUxBuL/s02zDpL6zP/83D9Xd1f3+/32NrubhAAD49ru7u7u7iPdPdLT466Mu/swDDJYgAAhBBKSJSEJhIQQwX1wDRHoe1iutlJ7S72q6+nmW0PxqvdHnppGsiUCul7Cc8nFDh5XTSTw0PC4tXDcehQxBU/LpLChDD6CLUJyxIA0LAkMojVZcDCUAPEQZAqakEmgpmVBUzLArQqGwhGpTA6NxUXjSRkQeEIKNCkNngnF4ck8vlin0jl1Jq/W6BEKtQgEhU4Xq9V2BkOCRtNpNBGLJWNRmQyGgCnWi/QBtaNQbvSyWCIMHM2i0BgkymuPAHAAKplk8DRNwWfk6PjNfjnQNF1pn6n1AZW9YdlYmX6pxbu7NwyCub0zb77eAT75o8rBMhfY2AtNAr+C5tNyCx2KqBuEVBRS8aIGaaVZUaaTgMVIz8WzMNkMHEbCl2o0DpnSxRZYxHyDVGgScnVcpgqclVIbn63BIJhqOc+mlga0So9IqCEROUho3JvJaW+nZqzJhCTAkCkobAaOmE2kQEjUdDQ6CQZbnZb2ZmLiW0lJ8ZmZqUhkNh6fmpaRnJKWnpGFRGGoNAYAjcGBt6nrs9MTs2GZCDKOIuLxNQq5Xq3Qa+RingiRDaeTaDqllsfkkrBEDp3NZXAENLD48kQyvdaeZ88psThy5CIZE4/jM9lAHJCIR6KJaCwoc6ASyOVx2SohK88g7AhqgaOpCttEpQuo7C9UAHEbG127ekL7Bot3dgeBypGoFqicKLMAldN1gaFyd3O+odgiylExvBpOgV0OUpmv5efKWAUqfkQjLJBx/Dqemo1horNYeLRKKDFqzDKJkU6TiDiqf3wpUcmlS8FBLTWDMw5BE3IpWhHHKRPZOGw5FkPLTo97c138W+vXvZOUGJ+WmgzJzkAiIODiRsBnYaEp8PTVqfF/W/82YE3aulREBgQPB0+Bm1MGuPMj4aDoaFQyBo0Eb1PiU9PWp0PToMCCkM1Wy8Q65SuEXF52egYejVFIpGw6g4wncBhMAFAp5AhkKrPJU+AJVbh8YbVMxSWTJDwBCCYBhcHAEEDl674JXiVioVrEDprE/RHLfK0b2BwtswOVg8Wq0VId0AckvjcUAdkE56GIerhY/1oleGa4wgMmeNQuzdeyQYEHLZICqyygZHuF1FwJMyRj5wpoTiVLxcKCVHIJKCWXa5Aq5Vwpm8iSc1RKnkbGVoroUnAwSM3gTEHSaSSklEWxCLlWNkuJx7Hg2XGJyeuSUtanpCWCYEHhYMlBkih4sOegybBsdFpCxpq31//lrXVvrE15Ow2WCMVmZKYmpScnZKUlY5EwBoXIpJJwKHh2ekpi/Lrk9QlZqZkENF7A5qtlGr3KAGBzeIlJKZlZEAaTTSCSQYTpDBY4g5wymWDNtWpdxba8KqM7LBKpQGaVYimHxsAhUCgIDAh93TpBmSsVMo2YE7ZIRytcS00BoGmoxPJKU4kGqJyttYHS3j9cAmp8ocEJ/P5R5Uilty1sLnPKQ3quU8HIN4vBz/ErWB4B5bXKPCHdpmBreEQRBS0iY5QsupbLVbF5UhpTL9YapXqtUK3kysHZqjSreAoGhkYno+QcGkilVywyMxkyMj4uKysJkJ2dDIenY7FQKhXL4VAEAgaZhQK7Zkr2mncS/vz2uj+tTf5rGjQeiknJTkvKSk2EZqQQ0HA2jcShk4ng9p+Rsmbd2/HrV6emp2GwJB5PpVI69dpcvTaPI1WtS4ckZsHxDC4YKgCGUMYSK/BkDpEpYyjdUneFNq9B4Sym8zVg7GjloJSYIJKILMg/VYLho9WotBIuSBPofdva8sdLzQPFpleaQC1HtdPVluWO3AMjUVDjQCWo+tcq52o9sw25o1U+cH0sdynA5HGrWCGrtMiuyNPwcqTM1wVeKOc6NDyrnKMX0tQskpJB1LJoJh7XLha5tDa3zm5TmowSLXgFZ71IzcEzOAw8KHDQK4NqlVsoAM/HQTITANCsRCQsFY/JplPQfA5ZImSweFgCJTsTujY+8c/vxP/nuqQ30rNXw1CJ8IwkaFoCIjOZjIHx6EQ+aGNYsLKn/G39G28nrkrITEPgqWCTkKvztYZSraFSbHQlgVUfQcRzZSiGEMuW8LU2od6Bp0uIPD1dmy/xN2jC7TJPJUVoykLRdQoVUImGwuGZ2UAl+PFAJWgaep1GJ+WBJQbo294eAir7Cg3gDCIJVE5VmYHKg6OloMaByr4C+VCR7p8qx6r9QGWFWwkmz+uxU+JSvx47JXpJhUleqhW79WKPQeJUC0xCpppB0jLILhEvqFXnmjx5Zq9P53AoTG61NWBwmcVaAYHFYxHBBM/Vq0MaNVCpZlDiiOj4//3n/5EIFg5/cbZUD6HRpBKSiLwOy8xEUNLSUOvWpL0FNL25/q349PUpsDRoNiQ9PT4L8haZvo4vzmJxYEhkekpScvza/5WS+mZqRiKZzTP6I3JnOcdYZioYMpgrmBx3briTq/Ch6KoUHEefFyVKDQyll67JkfprbNX9xkgzRaFPRyNTs5K5YjEcjQF/jGp1rsNukUhUNLqRw3ZrCWYZ2a2R1+aHxurrF1qiW9u8u7usM/X2gSJ5b0i42Gg7OFG+f7purivSVe3rK7IOROwjZe6JKv9ouacjX19m5OSIsC4+I2JU1XltNW5LldNU67FWu8wlYG+XMr1cgoEE1+DhehrRwmeBRcejkDukNIeUXuI2apjkPKNeQaUbhRIGHEvBUoVUpp7NMjIoMgyalgmLw8LW/J83/yObwVYWVlGtAZJEIpUxeKQkIi0dS0qGoeNTM1clpLyZkLwqNWN9JiQVDoW9agiQ1TjiOiYnk8lCEAgIJBwBSVsN0h2fmJCGILK0Pr6rWhkZLJ36WO6uYWjC5mAzWeoW28Isrcdf3qpwhRTOEpEtqivYUNC9qWxgk7Okhi2XowlIOpsDmumr39lSqDIuTy+WKpksNgIl5qHImCwCCqUTK6vz8saqw1tbXPu7rNPVpv4CaU9QNFtr2TdcClQu9pT21fp7Cy2DJQ7gca4hCBiKOhvcsoiWkacQVtgNDX4HUFnpMAKnwGa5TR9R8YJShpdPcXGpbhHXLRO+2hkl4hKXJk8viXpMChopx2hUsQU2uY6No3MofAVbZBWK7GDPpJCFGGIcKM2/vvVfEBpDFSqXBIrZOhNXxCZhUkikBDw+Ho1eA4ethkJWQ7PXQbPXgz4AgUCyIWkQWCIal0xlQNlcAvPVf5ySunoVaHAEMktoDHibxmztS+rWZe/Mp/7BLd7uja6WSYw2YClt45nzZfYwS+VUuyvE9jJ1sC3ctdQ4vSfSNqC02PAUHJ3JkMikHA4Hng3BwtEKvkTM4EET0jFkTCYSjaZwbY5gZ0v7tqG2g0PFHw94p8q1A4Wy7qBsrNK+faDivemW5cGq8aZ8kEoQydn6/C3tJVs7ojN1eZ1BQ7VNCAJY77M35bhAJMusOiAUvAXBjGoEBQo2mEI5Ek6OQuxViB1SoZnPay30FNnURXajiEAIGG06kcap87DJIglHqRUo7WKpk88DS5OMRIlLWP2nv/7tT4lwBENvF7uDHL2VyObA0FAsejUauQqFeAeNiMeiEjGIFCQ0CZqZkJSWmgHNBA9giCgmjy5WiPgSAZlOg8UnU1BkOltuyK2pWThcsvWEsv8Av+9AePlI1f7P86Z3w01Ba00fXulCcrQ4cLPQFzI1RVxbtbao11MzZAnXsGUqOBrFZDMEYOoxGEg4CgXHgfFHwtDSE6GpGDK43ZsKG3sXD+w/+vmRfcuHpxsO9/onywwjJaaeiL2/NrQ41LJv4+DuyQ1zHVHgcbI6sLG5YLmrbHt3OQhmd9hU6xCDJAKPAOCx2KB8HUwgFKQyX0L38MhODsUl5LikAjCdQSpbQi5wZw+adAICOd+Ra9F63bYIi6bXSuxGscEmlIFlSEshiPG4uGTQBNe9syY5FU7jiq1+odmL48uRNA4SsRYGfQeavRaFSCbioCQ8AoOEQDPT3klanwKFwPHgnsqRaPRGp1ukViGIOCGBRsNQE1IQULra17FYsfOUc/4z1eQxTvOYc3qPfXhbui5XXdaBlnsoSp/CFeWoC7iGMo6lhmGtphsjVIUTxxCCLslkUBAIGAyGIJHpZDI3C0JMTcfB4EwEQy52Rssn9m756tb7393ce/CDnZPde3pKJqu8E01Fg621fV2ds7Pz+3bveG/L3KbBNpDH+cbQptYiEMnNGyJAa3uersoqAGEEHhsDzqhZU6iTg2IHqQQ2y3QiUOB2Js5Exdq4DJ9SErYYiu22ep81pFUU2ewajqyisCHHXxsMdQmlBV5zsUcbcEq0VjYHqBTh0XEoaCYK5C05NQtN0HmCpvwKutZNU3ug2KwMRGoaNBWCguGpZDKDDe7aMDRxbXpyGgIFxdGJDIXOGgwUVsiN5lQEhIyAgftJUioEw1GXDm/rOfRDaP64umsPKdgurh61tG+EaEJcfx1E7OC7ShU5tWpXoy7QKfd30Uy1OHmQJHFReAoCmUEh41KS1ycnpxIpTApDkgGjQVACrtTjC1aHGkcbt306cfLu4rd3N3741fZtOw5tnp9qrZgfGZic3dK/sG96z2f7Pzlz4OCHm6YngT7gcbGlEAQTOAWTB6gEqQQqm3PdACAR2ASNEpyB3AaHJqLhg1TamETQK8MmbVWOt6kgXO+xFZt0Nbn5NoW1vqq/oLA3WrOod3QU+ZuDthKv3Gzn8kxMiopOjCOgEWw6LSMjA47C+wsrcys7uLYIx1EGp9PS8fgkJAbcu8EeQ5PoSQItmqHIxCKzsMQ0OA1BkOvt0eKqDq3DkwjNTI5/A4vKRIObn9JU3TvXOn/YWjdL82wwlE2Lc7pcdfNEQynVUgYReWTBBrwuz5rXbQkNKvy9NFM9w1AhNBdz5WYckcGkEfE4FArcdvA0Il3Klbr07spAtG94YLq+b6507v2mjy6Pnnm+8eu7uz8++8H7n00N9G9Z3rfx/W9GDl2a+fv9A9/9vP/vP85v2g3qeqmtGEgE8QSNcrzS119sA3MctMUNIX9HQQ4IJggjOHcX53cW5jY6taV6UY6Y4eHTA3JRoUVf4XfX5uU2euxlFnNdXpFRYo0UdroCnUXVWy25E2FPi19faBfqzEwOUKljU+IwCDiPxYRkZKLQ+ILyhsKGQY6tlOaoQgql6TROAp6eThXgJCaGNkBV+XFiB4ZNg5IY67MoaXCJ2lIerR8w+vLXwzIh2W+TyNnpWcnxqRk0iVHhqmDpo2Rl1Fc6z1BWWQtGgS+mpYJsjjibxtG6fFOgS+Pr5FqaSbpqvr1e66/lyW2ZEKyYxwCXd5FIAkdTCHS5p6ClaXBH6+jeyb6xsvpe+4a5wt1nBn6MbTofW/rk6uLOE1Pjc8v7P99y4v7457/MfRt7/0rsvZN3ZrZ+APojUAk8TtfmApUAMM1BAwUxBOL6ouH2cAB4BIehiuL+0oJqsxykEowdv4gFxk6+XgUKPGw2NbhtpWZTpS8oZiidtkqptsoXWdAHJj2GKrPYp6ZIlHiShozTsAhxWA4/Pj1t1eo3sSioVMjj8sQwHDsRxszMSEmHoxzRJl20S1PWCxPZ+aYAliWCwzLJRBKPI09OwiiUXhxRgKOyIRjcm+vWpGZCKESWlGdQSLw8cYAg9MP4Xh74JwNt3vwWg7VQrs9VucrlOU1sTyND5ctgGAj6qK5i2ly7YCgd5lgi8XA2h4ZSKoU6m0MTKLbXjhbPfFy6/EP+prPtdaPtfdvad37e+/XdiRuxhduxTZefL529M3js0ujXt2eu/brwJLb4LLZw6+X02YcTJ26Oj451dvTWNba3tHQP9/ZPd7YNleVu8CibvYr6yurqrqXaDRubSiq6cy2DxY7Rhkip1l2s1ebp2D49wWcgg8tlicVRYQ3bnLlRs6teKg+xqVqpSOkrtxQveQqPltbuikRninJaQtZgrtbilMrj5DYnnsmAAEEEtIDDZLL4GIoQTpHD4fD1GVCxLQiKEacLv4nkEeVWFENMJOMoVDqFIvjr3zL4AguWwGdwxQQmA0MiwODo7AwkCkZnM40ybZHc1SDxtdIczURdFMVzollGoSFsL+hU53WRDDU59RNcVx3D0yaJTisrF5zNWzz1M2J3NYWAJZPJODITw5LzrRF7zYSjabM8OuWwRQPR3sjUwYZjl/rO/zZ9M7b5+ssdl38Z+uzWyLcPJ6++mH0Qm3sYm70Zm/rx58lTD0bmtnaNLbYNLfZOLk/Pb58bnRqoKW/wmbvCnvaWwZapI20TH3S2DPaVFIJI9tVWt9j81WZjoYHj1REdOqrLqMq15Yec1d6cSJUz0ChXhjlUvUyo8UetxYv+gsO5FTsChZM+d4NbF3BKdSa+OE5qsVN4XDBIkLBMJDQLBseAVGKYGr5EkYWh8k05cJEdJnK9kc2iaf00pQNHpxHoXApdtnYdWqvP5/B1PLGSSKcT6eTMLMjqt5MS1sCxOBVPXSzxtAkC3YzSWWJOD0ITgfF9NFWxytehyR0TuocVxQNUdxuvZMbc86Gt/yPf0BF781aStVoiMZCpwoxsUko2mcjUyMwhsSlMEjltuQ3B1tm6nV91nnzQe/7l0KWXU5d+W7z0y/Dpx8Pf/zxy5eX4rRhg7Fps/Nxv49/9PPDu8e4dn3bu+Hx43+m5/admNh3oau2rChZ1FUfbu7ds2PJTx/YLPaP7uhu628oa68o7+jz+VocxauTn6Jkui8zjD+UW9xdWbS2pbm8rrOyy2KNSvtOgtoZq/OXbQtGPPPWHPGVb3YFuu6nQIjMbBYo4klACUonGIiCZKSkJ8UnJGeAijGVplUYPnCyUWoNgd6Gqc1chBAxDAVMfSseQ0HSxQOHGktWF0U6dMcATyrJgr74KmZUNzc5AY5A8BtfN11cynW0Ud7d68rhj7nP30PuyomGsLIoRlcu8E/7aQ/ScPpy3T1S72zJ60jb+tX/ypLFtL9xYn1PQqbOW0jgWFF6Mo0gYHAWdKSWQObaqwaLJfRs+ugoaZc+FWM+52PCFFzNXYwM/vug/97L/Qqz/4isGAOdjgz+97Pn0VvvHt9qOrPQcvTvywc2h5ZOt3ZvLSzsb8qpr2t+tWr7TcOB529K3bT3LVdWTRaUzPV4fUFlqkuSbJAG/N1g1EO3/qGr+SsPA0kDz8FB+pM5qzvN7AtXd4cb3IlXH88fO5/eeyKvbFshrd5uCYL7HYdg8ulDA5jIIWERmalJKKtiBqDCyjMA3rckgc1VetsorMITfhnJR4pwsvnc9loHkqAX6EJ5pCZd0KdQuGoubkpackZ0CLs4cpkQicog1JVJ3p7ps0dR2MO/AzcK9l0IbTxhqFgnaWoSgjGcfdVd94B88rG7cLW09KGg9zGs+5J46VbxwWt+0PbduyREZA82BJvMjqLJMNBWKI2OpDH5ln21kb/mhi22nf2//MdZ1PjZ8Izb3INZ+PtZxLtb+Q6zj7CvAof2n2IZzsY4zsaaTsZpPf6s9+rz5wP2WzWfr+g9U1i+UBRqK2g6Gdz0r+TjW8P79loUvqnsOF7V+2JFX0Oj2lJr1+SaD31+cUzdfMH62eNvPlZOHO7u29Za0VftCeUVlgZbp/JYjeRVfBLf/UrhppWT4i4KahYCvxqUPxGURKaDAOTwmDg1LTVy3PiE1PhW1NpMCpRn+ay2aLrJJNH6dsyQBKUZJghmCUAZbg5V52PqiZKRMbYrgSUIcnpwBEp0aD4dB8FgGDidDM9xMywZr26HotiuFuy/pet5nBAfpzhaOo5Vt66Db+1muCUf7u7rm3cbuo8quY+LWw76Jr8LTJ6SlM5ryTYqSOWnBMMffjFDnJLNV6QIl0WB1b/uo8NAPjV896/iHrDag71Ks+3qs5nys7sdYw7ex5lMvAXWnX1Z9F6v4IVb/fazydKzkeCxy5LfyvQ+qNv5Q1Xe0onG5orAz1HvU/d7vOV/GKk7Emg7eaFg6Vzl9sa20tT5YVuLw55q8Tme5tWTO3HnSPHU3MPllWdeB+tKxkmCDt6LL2bnT1vx3U/Ep+65YzvbnxXPnizbsCwQ7XIbCuFXpWdlYDAaHzExLTIxfnZqWnQ6nJCPYWEn+nxNINJ5ZqvJaPaVZZD3b3kT39GaLHVRziczblI43iDThbBgVBkdmpCelp69PTUlKWJe5Jh63NksOk1YJK3c5J8/a2g/SfX0QSRFBVSxwNHDdG8iOTryzj5/XIy6ZsnS+b+r5SNG839V/1NKyA64uFVfv4FdskTYsG/v2Gvp2SDZMyzqmTGOb26/83HU51nMl1n0x1vZjrO5srOxMLPLNs6KfYtGzsepTsYYvY3UnXlR8+aLw9Iv8My8iX8eKT8UiJ2Jln8Qq9z+tWvipvOtItGa5tnIwd+hjw/7fjF/Gcr6KVR69U/vurYpt92sbp6vLekpzq8KuqN/XbC9dMnV8pRu7ZZy9nD9wsrx+V1HlZKBji3P8uLHrR3nJT5KtMcv2l6HNK5GBj0PRcb+zOu6NBHBnBDYgQCUkI5VG5wiVNp7aR1aX/Nc6CpqsYLG1akN+Bl4jCnTLS+ZTBA6up85TPclQF1t89TAMC0ybhPWrcTgIFJKVnAiJTyQlIQ1QeS0hbyO9+gDPN0Q3NbMM1WJbDctYhlWXEB2tovIFd9OCqW6jtmGZXjSH9g3pGrf7Onfx/C263o+l7QcNo59ED11t+/ZJ05mH9d/ebjn3sOrcw4rvnlSc+rXqq1jd6Vj1t7Hot7Hw6Wd538cKv4lVgFo+8bLqs9+jJ37L+/IX96nngc9+DX4Ri56KVX8Ra/jw99pNF8o7DhdXbK6pHfQMfSje80jw95jh+M/BD25Edl0v3nq3vHVrec0kyGxZXnOkeCjUtC8wds679FS3+XH+1OWqrk/LOvaFpz7yb7lgGbsjr1lhborplmPB5YdlkydL6pcKczfE/SX+/8Snr6Py2BS2mMLUaEwRBtfLFxdoywdwCueq1GwijflqnZT7rMMf6WbO4iTuZKoh2L2TbKvBKfLWZZEIGCwNngGHkpJTUW/FI95Ko2cxnUxnqyg8wQ1Nquv2uzuOGEo3CRzdAlsPUdUOEXeQHRv1A/uErTs0fUf1vcc5pbukZdvtjXsM5RudQyed02c8u66EPn0C4lZ5LlbxXazs1Muyb2Klp18R/TpWAuJ2Mlb81SsKPo+FP3tF6Hgs+PdY/qexcug87QAADG1JREFUvE9eAvKP/Zb76e85x1/kfPJb4P0ngeXbgalLOYM/Oocue6du5W97UvDei+AHMc8HL4z7n6n3PNTM3dYNfKNvfNcQnTSWThma9hiGzugW7mp3PDIv3vOM3MztvprTdcU1dF0/t6LYcle27bFsyyPFxvvKqdvq4Ru63qtxq9e/A8ciBQo1R2bQOCNcdUhuryeKw6L8VrzSlYwg0HhCCJG1hqySNmyV9n5qKmhLphllwU6oLCz21klNuQq5hopC4FFEOJSQlklIQ/LRPA/HVi/K7xcER5j5M7KieZa1na6qUrq6xfY+srab7Z5Vdu4QNG6zjn9euP1a3vxPwcmvc3uPSAvG1a0fmUZOundeCR57UgTEAY/fxspPxYq+fEXhF7GCE7Hw57HQZy8BweMvco+9Iufj3wMf/eY/+qvvyC8A74fP/Yefg7feY795j/7iOfjEt3wnMHM1MHLBNX7dN3s7Z8uj/Hd/8b/3q33/c/3ex8rd9w1bn5tnr9n6PrO37X1F/+eWueum5V8VOx/rlx7Yx1fc/dddfdesozfVC3fEW+8JtjwSLj0UL9yXTN9RjK2oBm7ErXlnLY3K4ssMDKnVXzmQyrBaa+ZSBSGqNYqXuqBkHk9uSMMw/zODQcvrZ1Ut851Vb0CEWE1htsAn9daacqrEchMkC05BYvEI/Kvvb+KESLoRLfBjVRG8vjpJVAmRVSaTnVkki1BXLjY0kCRVNO0Gduk0MTwh6zySu+1aaPlG4abzrs4PKLYOXsV7mr4Tnl3XQ5/8HPzyd0DRVy/LTsbyPv0dkPvJbznHfg18/Iv/o+cA39Gf3R/8CnAd+sX5/nPHwZ/tB54BbPufOvc9fXU49BzgeO+pa/m+b37FP3HdPXfHs/Gee+mBc/mRdccj/c6Hqh335dvvqpdj+k2PLVMXHCNfA8BBt/gIfCjc+Vi6+YF25o5x+KZh6IZq8pZw4x3O1nv0xfvMhXvsubu8qTvC8duSkZW4VX96i0ZgkSjCbILYWz3039O5/sF9a8RhgjqEFjqgVKlI5wGvf85ik53N5EDfWpLuf6awaJYyuqmErg3yDPlgZUmGkFloHA1NpOKZZJoURdOkk3XpdCdMFF4vKkWoq7PZfijFzJUFmeIQiuEnS8o44UlMYJTdfFA/+71m6ox59KSh7SDF0csrP2AY/DrvvftFn73I+exXz7GnuZ88B+c/Js5zGBh85jr0FABiBbC997N13zPL3qfmPU9M7z5+xdaHxh2PtbufaPc81e96Ytn2yLlw3z19x7npsWMR1OwD3cZ7yo13ZIt3ZEt3JZvvchdeiGafKqZXNOOXALLJm/ypR6zZX1nb7nM33RXPrMjGb0rHbggmbzDnb9GWbhOmV4hTK+SpFfrkbebEbc7Y7bh3/vOvJAQBCiWuSsHog03/LZFSMHYQaqokKvMQHGsmUSGzFlClnmSCmueup1jrINLQOzgNw1TCNhfD2Wa2PpxJ16dRNGQEBgPFgGWIwTWQhW44xw2XhMjmekpoRle/rC0eEVoqxLoiEteNorv4umpJcJZXssU0dca3/6F26ZJ2/LSp+6ggNKNqPu6avlBw6Oei4zHfJ7/aPnjk+uBx7hGg7zfAHwP4OoOWPc8B5nd/Nu1+Ztz11LDzCUAPJC48UG16CNqZFDS1bY/VS4+M8w+tsw+NS4/1iw9V83cl07eEUzcEMzcFs7eEcyu0yWesySe8iXsgYoKxFfbobcrwPcLwA9rCXfrMbdbkCnvsJmv0Bn3sBnniBnH6JnbwOm7oBmHoBmnoJmXoFn1oJS551d/wcCgciohPhAh1vjVwfnjDRoG3kSzPRXIdEKpe463lG4oQTLPKV883R3UVk1nCQDrdCGHq3oYw+fbydJ47lZ+blgx7Z1VafBIWQdfhZUGErAijr+fkjgjbPgQ7o6N9rySng6mJQCjWdKKVrasBi7oosiOw/WbJyZjj0BPD4jl99yfsvBl73w/++ZvB/c/zj750fviL5eAT2/7H7v1PHQd++f8DCDDsfKbf8RSg2/5Eu/xYs+2ReutDgGrqkWzmkWD+EXfxMUC48Fgx90Qz80Qyf188d08wfZs7cZMzfuM14MyaeMiefMCdeMCdvMcev8MYvk0evEnsv0kZAaZuAKiD1ykD14j9Vwl9V/D9V/Ad/w9C51UAsetaXGbSX1CQBCIGlpWR+Y9vDWttrkqjrZIk9BFFPoI4xxLuYusimUS11lmpspSoy6fxhlKCIsBS+99IJrIspSmCfKSlBUUUr0kmgPEN43pJpjqUoRlp72UWbGR2faEdOS2q2YGzNKJkxalUZxLRRdHWSO1T7LzN+qkfPMdeGA49MW2/Zhr+khNccA9ddE1ds2+5Y9/z2HzgKcD63hNwNu5+bNj1CAC6m27HA+32+5rlewDl5ocAxdID+ab7ssV70o13JQt3AMqJJ5LJx9zpR/TZhwDWzEPB1CPwCWPyFnPiFezxW6x/BI05ch3AH73FHV1hjawAibTBW5S+q5SeS5Su8+SOy5TOK8TuK4TuK/iuy7iOi4S2C7iWc5TGSwBS4yViw0VC40Vc44W4jJT/yE77C4MEwcGysdlojcQsYuqM8gCWa6fJg1xDmbt0lKooWAfhK8yFJmcEZ22SBLujnRtreuaSMAKaMZouK5HXbncGm8FVD8nzclwt8sgsIzRDDi1yKvfSB78XDn1LiGzO1jfhDDUoeSlMXMJ0dOaUHRQV7OR1fy7ZuSLdd8918GFo21Vzy2HnwHnz8Hn11EXN5pv6vQ8tB1/NENu7IGv3AaotwN1dxdId+abbANniinjuDkA0e1s4syKYvsWfAj3uJm/yhnr8mXjiCXvyEXX6IWnqAW0KhO6RcOIxcfgaefQGbfwWY3yFPX6bNXKLMXSDOXid13+B3X+B2nuZ0HMJ23ke3/4TofUbUstpatN5cusF4oaLhPaL+A2vJOIbfyTUfk+vuUSruUStvkiuvkCoPo+rOhf39tpVKKaA560gu1tM9Vu1hcNZWLUZ9EGaGs+WExgsg9XIkynQDKXMswEjq4UwvBRxfjjaa3OU8IU2oSKXKgnai0cN/iqWKoco9TGMpXRrLUZfTXZ1ycs2aqeOyafPcru/JfoXcewwlqCHcvOSNM1J7gVo5F1K75fizTc0e55qdz9TbXogm1rhjlzmj10VT92Uz91RbbyvXnyg2fQQoFy4B1DM3wWfy2ZvS2dWAKDfccbugL4GAIFiDgMvN+mDNwDM/usARt81eu9VWs8VALX7MqXrEmPDDQC97Tqt9Rq15Sql+QqA3HSZUH/h31PxAwBf/j2u7Cy29DtM9Ay65Nt/SxwEhaDJ9cpwKyPQqa9Z0hQMZeCUam0ujmsicpUoEkUkF+PpTChJrPB1kLUtWTQ3kuE0u6rEUheJomQKXFiOVxPoYiq8GI4VJ/IKXfWy/F62r5sXHNXXLatGPpRPnuH1fs8o2EWTV1LZbqw8km3txZcdoDUf442flS/fVr/7RLXjsXzhrmTiJvAonLgOHAFlr/X90eBrieBvgWvR5A0A0PdPg7SB69T+awBQnv9ikNx5kdRxAQD0vTYI9L0uz1cVWn8BW/PTv6f0uz8aREW+QRafBkDDX/0LcVypQmoPWipH2MEBWdm8MjyQRdIIpE6yyE7mq7NQGAKVmAZDpKLYqkAX3diO5OZmEU0CeQ6BJEdhhCyhG8P2SJ0tRL4TyTRT5EFdqNdcPiMJjwnDk9qaZUXP++LhrwVDF0R1RyXuHr4mQrc0EfPnFH2nVWPfKxevKHfcVex8KNt6XzK7Ihq7DhwBU0AZcPfPAP7RHRAtGL8GjPNGrwD+6Y7ce4XUc5nYfQlA6LoI3L3WR2w/T9hwDt/2E671R8DrrOHrzgNwteeALEz1jwBkxdl/y2t3iKKvAfDCU7CCk6/Fpecc/xfiVBaf1FViq59jhUeZoVFpuB+sODS+Ac8zk3gqIBGOQaxNSUuCM5T+ToqulaWrhFFtdJ4DjuRhcGKJOkiThlS+DrExwlQEBeZKS2TUUr4gyB1h+kfFxZuULQeE3aeEI1fUvaf1ZQsKT7Mgp59Xuds6fdE8f1m9dE22bUW89Y5wcUU0fVM8fgOI+6NHYBC4A+JeA9yBDsAZvsQeughgDV54rQ+4A+A7L+A6zmPbzwGAu9f6sC0/YJq/RzedBaAav3stDl31A6rye2AKUf4dvOwMAFJy+t8C3L3WBwl9mR38Iiv/RGbe54AU3yf/wv8Fe4XaH0Z+k6QAAAAASUVORK5CYII="; byte[] rawInlineImageBytes = Convert.FromBase64String(InlineJpegImage); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs index 31329577fb637..7c294ff0a6c1c 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs @@ -91,7 +91,7 @@ private FileWriter(SerializationInfo info, StreamingContext context) { string tempPath = Path.GetTempFileName(); File.WriteAllText(tempPath, "This better not be written..."); - throw new InvalidOperationException("Unreachable code (SerializationGuard should have kicked in)"); + throw new UnreachableException("Unreachable code (SerializationGuard should have kicked in)"); } public void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/runtimeconfig.template.json b/src/libraries/System.Runtime.Serialization.Formatters/tests/runtimeconfig.template.json deleted file mode 100644 index e3ad204dd9e51..0000000000000 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Drawing.EnableUnixSupport": true - } -} \ No newline at end of file diff --git a/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs b/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs index 3cbae8430c207..018565ccacf3b 100644 --- a/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs +++ b/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs @@ -50,47 +50,47 @@ public static void DCJS_ByteArrayAsRoot() public static void DCJS_CharAsRoot() { // Special characters - Assert.StrictEqual(SerializeAndDeserialize((char)0x2f, @"""\/"""), (char)0x2f); // Expected output string is: \/ - Assert.StrictEqual(SerializeAndDeserialize((char)0x5c, @"""\\"""), (char)0x5c); // \\ - Assert.StrictEqual(SerializeAndDeserialize((char)0x27, @"""'"""), (char)0x27); // ' - Assert.StrictEqual(SerializeAndDeserialize((char)0x22, @"""\"""""), (char)0x22); // \" + Assert.StrictEqual((char)0x2f, SerializeAndDeserialize((char)0x2f, @"""\/""")); // Expected output string is: \/ + Assert.StrictEqual((char)0x5c, SerializeAndDeserialize((char)0x5c, @"""\\""")); // \\ + Assert.StrictEqual((char)0x27, SerializeAndDeserialize((char)0x27, @"""'""")); // ' + Assert.StrictEqual((char)0x22, SerializeAndDeserialize((char)0x22, @"""\""""")); // \" // There are 5 ranges of characters that have output in the form of "\u". // The following tests the start and end character and at least one character in each range // and also in between the ranges. // #1. 0x0000 - 0x001F - Assert.StrictEqual(SerializeAndDeserialize(char.MinValue, @"""\u0000"""), char.MinValue); - Assert.StrictEqual(SerializeAndDeserialize((char)0x10, @"""\u0010"""), (char)0x10); - Assert.StrictEqual(SerializeAndDeserialize((char)0x1f, @"""\u001f"""), (char)0x1f); + Assert.StrictEqual(char.MinValue, SerializeAndDeserialize(char.MinValue, @"""\u0000""")); + Assert.StrictEqual((char)0x10, SerializeAndDeserialize((char)0x10, @"""\u0010""")); + Assert.StrictEqual((char)0x1f, SerializeAndDeserialize((char)0x1f, @"""\u001f""")); // Between #1 and #2 Assert.StrictEqual('a', SerializeAndDeserialize('a', @"""a""")); // 0x0061 // #2. 0x0085 - Assert.StrictEqual(SerializeAndDeserialize((char)0x85, @"""\u0085"""), (char)0x85); + Assert.StrictEqual((char)0x85, SerializeAndDeserialize((char)0x85, @"""\u0085""")); // Between #2 and #3 Assert.StrictEqual('\u00F1', SerializeAndDeserialize('\u00F1', "\"\u00F1\"")); // 0x00F1 // #3. 0x2028 - 0x2029 - Assert.StrictEqual(SerializeAndDeserialize((char)0x2028, @"""\u2028"""), (char)0x2028); - Assert.StrictEqual(SerializeAndDeserialize((char)0x2029, @"""\u2029"""), (char)0x2029); + Assert.StrictEqual((char)0x2028, SerializeAndDeserialize((char)0x2028, @"""\u2028""")); + Assert.StrictEqual((char)0x2029, SerializeAndDeserialize((char)0x2029, @"""\u2029""")); // Between #3 and #4 Assert.StrictEqual('?', SerializeAndDeserialize('?', @"""?""")); // 0x6F22 // #4. 0xD800 - 0xDFFF - Assert.StrictEqual(SerializeAndDeserialize((char)0xd800, @"""\ud800"""), (char)0xd800); - Assert.StrictEqual(SerializeAndDeserialize((char)0xdabc, @"""\udabc"""), (char)0xdabc); - Assert.StrictEqual(SerializeAndDeserialize((char)0xdfff, @"""\udfff"""), (char)0xdfff); + Assert.StrictEqual((char)0xd800, SerializeAndDeserialize((char)0xd800, @"""\ud800""")); + Assert.StrictEqual((char)0xdabc, SerializeAndDeserialize((char)0xdabc, @"""\udabc""")); + Assert.StrictEqual((char)0xdfff, SerializeAndDeserialize((char)0xdfff, @"""\udfff""")); // Between #4 and #5 - Assert.StrictEqual(SerializeAndDeserialize((char)0xeabc, "\"\uEABC\""), (char)0xeabc); + Assert.StrictEqual((char)0xeabc, SerializeAndDeserialize((char)0xeabc, "\"\uEABC\"")); // #5. 0xFFFE - 0xFFFF - Assert.StrictEqual(SerializeAndDeserialize((char)0xfffe, @"""\ufffe"""), (char)0xfffe); - Assert.StrictEqual(SerializeAndDeserialize(char.MaxValue, @"""\uffff"""), char.MaxValue); + Assert.StrictEqual((char)0xfffe, SerializeAndDeserialize((char)0xfffe, @"""\ufffe""")); + Assert.StrictEqual(char.MaxValue, SerializeAndDeserialize(char.MaxValue, @"""\uffff""")); } [Fact] @@ -108,8 +108,8 @@ public static void DCJS_NewLineChars() public static void DCJS_ByteAsRoot() { Assert.StrictEqual(10, SerializeAndDeserialize(10, "10")); - Assert.StrictEqual(SerializeAndDeserialize(byte.MinValue, "0"), byte.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(byte.MaxValue, "255"), byte.MaxValue); + Assert.StrictEqual(byte.MinValue, SerializeAndDeserialize(byte.MinValue, "0")); + Assert.StrictEqual(byte.MaxValue, SerializeAndDeserialize(byte.MaxValue, "255")); } [Fact] @@ -139,26 +139,26 @@ public static void DCJS_DecimalAsRoot() [Fact] public static void DCJS_DoubleAsRoot() { - Assert.StrictEqual(SerializeAndDeserialize(-1.2, "-1.2"), -1.2); + Assert.StrictEqual(-1.2, SerializeAndDeserialize(-1.2, "-1.2")); Assert.StrictEqual(0, SerializeAndDeserialize(0, "0")); Assert.StrictEqual(2.3, SerializeAndDeserialize(2.3, "2.3")); - Assert.StrictEqual(SerializeAndDeserialize(double.MinValue, "-1.7976931348623157E+308"), double.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(double.MaxValue, "1.7976931348623157E+308"), double.MaxValue); + Assert.StrictEqual(double.MinValue, SerializeAndDeserialize(double.MinValue, "-1.7976931348623157E+308")); + Assert.StrictEqual(double.MaxValue, SerializeAndDeserialize(double.MaxValue, "1.7976931348623157E+308")); } [Fact] public static void DCJS_FloatAsRoot() { - Assert.StrictEqual(SerializeAndDeserialize((float)-1.2, "-1.2"), (float)-1.2); - Assert.StrictEqual(SerializeAndDeserialize((float)0, "0"), (float)0); - Assert.StrictEqual(SerializeAndDeserialize((float)2.3, "2.3"), (float)2.3); + Assert.StrictEqual((float)-1.2, SerializeAndDeserialize((float)-1.2, "-1.2")); + Assert.StrictEqual((float)0, SerializeAndDeserialize((float)0, "0")); + Assert.StrictEqual((float)2.3, SerializeAndDeserialize((float)2.3, "2.3")); } [Fact] public static void DCJS_FloatAsRoot_NotNetFramework() { - Assert.StrictEqual(SerializeAndDeserialize(float.MinValue, "-3.4028235E+38"), float.MinValue); - Assert.StrictEqual(SerializeAndDeserialize(float.MaxValue, "3.4028235E+38"), float.MaxValue); + Assert.StrictEqual(float.MinValue, SerializeAndDeserialize(float.MinValue, "-3.4028235E+38")); + Assert.StrictEqual(float.MaxValue, SerializeAndDeserialize(float.MaxValue, "3.4028235E+38")); } [Fact] diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs index d841d36fb244f..6ab67b426a35b 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs @@ -85,8 +85,8 @@ public static void DCS_ByteArrayAsRoot() [Fact] public static void DCS_CharAsRoot() { - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(char.MinValue, @"0"), char.MinValue); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(char.MaxValue, @"65535"), char.MaxValue); + Assert.StrictEqual(char.MinValue, DataContractSerializerHelper.SerializeAndDeserialize(char.MinValue, @"0")); + Assert.StrictEqual(char.MaxValue, DataContractSerializerHelper.SerializeAndDeserialize(char.MaxValue, @"65535")); Assert.StrictEqual('a', DataContractSerializerHelper.SerializeAndDeserialize('a', @"97")); Assert.StrictEqual('\u00F1', DataContractSerializerHelper.SerializeAndDeserialize('\u00F1', @"241")); Assert.StrictEqual('\u6F22', DataContractSerializerHelper.SerializeAndDeserialize('\u6F22', @"28450")); @@ -96,8 +96,8 @@ public static void DCS_CharAsRoot() public static void DCS_ByteAsRoot() { Assert.StrictEqual(10, DataContractSerializerHelper.SerializeAndDeserialize(10, @"10")); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(byte.MinValue, @"0"), byte.MinValue); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(byte.MaxValue, @"255"), byte.MaxValue); + Assert.StrictEqual(byte.MinValue, DataContractSerializerHelper.SerializeAndDeserialize(byte.MinValue, @"0")); + Assert.StrictEqual(byte.MaxValue, DataContractSerializerHelper.SerializeAndDeserialize(byte.MaxValue, @"255")); } [Fact] @@ -124,26 +124,26 @@ public static void DCS_DecimalAsRoot() [Fact] public static void DCS_DoubleAsRoot() { - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(-1.2, @"-1.2"), -1.2); + Assert.StrictEqual(-1.2, DataContractSerializerHelper.SerializeAndDeserialize(-1.2, @"-1.2")); Assert.StrictEqual(0, DataContractSerializerHelper.SerializeAndDeserialize(0, @"0")); Assert.StrictEqual(2.3, DataContractSerializerHelper.SerializeAndDeserialize(2.3, @"2.3")); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(double.MinValue, @"-1.7976931348623157E+308"), double.MinValue); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(double.MaxValue, @"1.7976931348623157E+308"), double.MaxValue); + Assert.StrictEqual(double.MinValue, DataContractSerializerHelper.SerializeAndDeserialize(double.MinValue, @"-1.7976931348623157E+308")); + Assert.StrictEqual(double.MaxValue, DataContractSerializerHelper.SerializeAndDeserialize(double.MaxValue, @"1.7976931348623157E+308")); } [Fact] public static void DCS_FloatAsRoot() { - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize((float)-1.2, @"-1.2"), (float)-1.2); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize((float)0, @"0"), (float)0); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize((float)2.3, @"2.3"), (float)2.3); + Assert.StrictEqual((float)-1.2, DataContractSerializerHelper.SerializeAndDeserialize((float)-1.2, @"-1.2")); + Assert.StrictEqual((float)0, DataContractSerializerHelper.SerializeAndDeserialize((float)0, @"0")); + Assert.StrictEqual((float)2.3, DataContractSerializerHelper.SerializeAndDeserialize((float)2.3, @"2.3")); } [Fact] public static void DCS_FloatAsRoot_NotNetFramework() { - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(float.MinValue, @"-3.4028235E+38"), float.MinValue); - Assert.StrictEqual(DataContractSerializerHelper.SerializeAndDeserialize(float.MaxValue, @"3.4028235E+38"), float.MaxValue); + Assert.StrictEqual(float.MinValue, DataContractSerializerHelper.SerializeAndDeserialize(float.MinValue, @"-3.4028235E+38")); + Assert.StrictEqual(float.MaxValue, DataContractSerializerHelper.SerializeAndDeserialize(float.MaxValue, @"3.4028235E+38")); } [Fact] diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 27cbc4c98d261..b0e071fb0f417 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -277,6 +277,7 @@ public ArgumentException(string? message, string? paramName, System.Exception? i public override string Message { get { throw null; } } public virtual string? ParamName { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public static void ThrowIfNullOrEmpty([System.Diagnostics.CodeAnalysis.NotNullAttribute] string? argument, [System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null) { throw null; } } public partial class ArgumentNullException : System.ArgumentException { @@ -1774,11 +1775,11 @@ public static partial class Convert public static System.DateTime Parse(string s) { throw null; } public static System.DateTime Parse(string s, System.IFormatProvider? provider) { throw null; } public static System.DateTime Parse(string s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles styles) { throw null; } - public static System.DateTime ParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style = System.Globalization.DateTimeStyles.None) { throw null; } - public static System.DateTime ParseExact(System.ReadOnlySpan s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style = System.Globalization.DateTimeStyles.None) { throw null; } - public static System.DateTime ParseExact(string s, string format, System.IFormatProvider? provider) { throw null; } - public static System.DateTime ParseExact(string s, string format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style) { throw null; } - public static System.DateTime ParseExact(string s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style) { throw null; } + public static System.DateTime ParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style = System.Globalization.DateTimeStyles.None) { throw null; } + public static System.DateTime ParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style = System.Globalization.DateTimeStyles.None) { throw null; } + public static System.DateTime ParseExact(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format, System.IFormatProvider? provider) { throw null; } + public static System.DateTime ParseExact(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style) { throw null; } + public static System.DateTime ParseExact(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style) { throw null; } public static System.DateTime SpecifyKind(System.DateTime value, System.DateTimeKind kind) { throw null; } public System.TimeSpan Subtract(System.DateTime value) { throw null; } public System.DateTime Subtract(System.TimeSpan value) { throw null; } @@ -1809,18 +1810,18 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public string ToShortTimeString() { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } - public string ToString(string? format) { throw null; } - public string ToString(string? format, System.IFormatProvider? provider) { throw null; } + public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format) { throw null; } + public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format, System.IFormatProvider? provider) { throw null; } public System.DateTime ToUniversalTime() { throw null; } - public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } + public bool TryFormat(System.Span destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } public static bool TryParse(System.ReadOnlySpan s, out System.DateTime result) { throw null; } public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles styles, out System.DateTime result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.DateTime result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles styles, out System.DateTime result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } - public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } - public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } #if FEATURE_GENERIC_MATH [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] @@ -1944,11 +1945,11 @@ public enum DateTimeKind public static System.DateTimeOffset Parse(string input) { throw null; } public static System.DateTimeOffset Parse(string input, System.IFormatProvider? formatProvider) { throw null; } public static System.DateTimeOffset Parse(string input, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } - public static System.DateTimeOffset ParseExact(System.ReadOnlySpan input, System.ReadOnlySpan format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles = System.Globalization.DateTimeStyles.None) { throw null; } - public static System.DateTimeOffset ParseExact(System.ReadOnlySpan input, string[] formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles = System.Globalization.DateTimeStyles.None) { throw null; } - public static System.DateTimeOffset ParseExact(string input, string format, System.IFormatProvider? formatProvider) { throw null; } - public static System.DateTimeOffset ParseExact(string input, string format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } - public static System.DateTimeOffset ParseExact(string input, string[] formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } + public static System.DateTimeOffset ParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles = System.Globalization.DateTimeStyles.None) { throw null; } + public static System.DateTimeOffset ParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles = System.Globalization.DateTimeStyles.None) { throw null; } + public static System.DateTimeOffset ParseExact(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format, System.IFormatProvider? formatProvider) { throw null; } + public static System.DateTimeOffset ParseExact(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } + public static System.DateTimeOffset ParseExact(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } public System.TimeSpan Subtract(System.DateTimeOffset value) { throw null; } public System.DateTimeOffset Subtract(System.TimeSpan value) { throw null; } int System.IComparable.CompareTo(object? obj) { throw null; } @@ -1959,20 +1960,20 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public System.DateTimeOffset ToOffset(System.TimeSpan offset) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? formatProvider) { throw null; } - public string ToString(string? format) { throw null; } - public string ToString(string? format, System.IFormatProvider? formatProvider) { throw null; } + public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format) { throw null; } + public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format, System.IFormatProvider? formatProvider) { throw null; } public System.DateTimeOffset ToUniversalTime() { throw null; } public long ToUnixTimeMilliseconds() { throw null; } public long ToUnixTimeSeconds() { throw null; } - public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? formatProvider = null) { throw null; } + public bool TryFormat(System.Span destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? formatProvider = null) { throw null; } public static bool TryParse(System.ReadOnlySpan input, out System.DateTimeOffset result) { throw null; } public static bool TryParse(System.ReadOnlySpan input, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, out System.DateTimeOffset result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan input, System.ReadOnlySpan format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } - public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } - public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] System.ReadOnlySpan format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string? format, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true), System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } #if FEATURE_GENERIC_MATH [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] @@ -4826,7 +4827,7 @@ public MissingMethodException(string? message, System.Exception? inner) { } public MissingMethodException(string? className, string? methodName) { } public override string Message { get { throw null; } } } - public partial struct ModuleHandle + public partial struct ModuleHandle : System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -6367,6 +6368,7 @@ internal AdjustmentRule() { } public static System.TimeZoneInfo.AdjustmentRule CreateAdjustmentRule(System.DateTime dateStart, System.DateTime dateEnd, System.TimeSpan daylightDelta, System.TimeZoneInfo.TransitionTime daylightTransitionStart, System.TimeZoneInfo.TransitionTime daylightTransitionEnd) { throw null; } public static System.TimeZoneInfo.AdjustmentRule CreateAdjustmentRule(System.DateTime dateStart, System.DateTime dateEnd, System.TimeSpan daylightDelta, System.TimeZoneInfo.TransitionTime daylightTransitionStart, System.TimeZoneInfo.TransitionTime daylightTransitionEnd, System.TimeSpan baseUtcOffsetDelta) { throw null; } public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.TimeZoneInfo.AdjustmentRule? other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } @@ -9036,6 +9038,12 @@ public void Start() { } public static System.Diagnostics.Stopwatch StartNew() { throw null; } public void Stop() { } } + public sealed partial class UnreachableException : System.Exception + { + public UnreachableException() { } + public UnreachableException(string? message) { } + public UnreachableException(string? message, System.Exception? innerException) { } + } } namespace System.Diagnostics.CodeAnalysis { @@ -9179,6 +9187,22 @@ public RequiresUnreferencedCodeAttribute(string message) { } public string Message { get { throw null; } } public string? Url { get { throw null; } set { } } } + [System.AttributeUsage(System.AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + public sealed class SetsRequiredMembersAttribute : System.Attribute + { + public SetsRequiredMembersAttribute() { } + } + [System.AttributeUsageAttribute(System.AttributeTargets.Parameter | System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public sealed partial class StringSyntaxAttribute : System.Attribute + { + public StringSyntaxAttribute(string syntax) { } + public StringSyntaxAttribute(string syntax, params object?[] arguments) { } + public string Syntax { get { throw null; } } + public object?[] Arguments { get { throw null; } } + public const string DateTimeFormat = "DateTimeFormat"; + public const string Json = "Json"; + public const string Regex = "Regex"; + } [System.AttributeUsageAttribute(System.AttributeTargets.All, Inherited=false, AllowMultiple=true)] [System.Diagnostics.ConditionalAttribute("CODE_ANALYSIS")] public sealed partial class SuppressMessageAttribute : System.Attribute @@ -10396,6 +10420,20 @@ public static void WriteAllText(string path, string? contents) { } public static void WriteAllText(string path, string? contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string? contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string? contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static void SetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime creationTime) { } + public static void SetCreationTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime creationTimeUtc) { } + public static DateTime GetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static DateTime GetCreationTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static void SetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime lastAccessTime) { } + public static void SetLastAccessTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime lastAccessTimeUtc) { } + public static DateTime GetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static DateTime GetLastAccessTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static void SetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime lastWriteTime) { } + public static void SetLastWriteTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, DateTime lastWriteTimeUtc) { } + public static DateTime GetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static DateTime GetLastWriteTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static FileAttributes GetAttributes(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) { throw null; } + public static void SetAttributes(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, FileAttributes fileAttributes) { } } [System.FlagsAttribute] public enum FileAccess @@ -10750,6 +10788,7 @@ public PathTooLongException(string? message, System.Exception? innerException) { public static partial class RandomAccess { public static long GetLength(Microsoft.Win32.SafeHandles.SafeFileHandle handle) { throw null; } + public static void SetLength(Microsoft.Win32.SafeHandles.SafeFileHandle handle, long length) { throw null; } public static long Read(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Collections.Generic.IReadOnlyList> buffers, long fileOffset) { throw null; } public static int Read(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Span buffer, long fileOffset) { throw null; } public static System.Threading.Tasks.ValueTask ReadAsync(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Collections.Generic.IReadOnlyList> buffers, long fileOffset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -10855,8 +10894,10 @@ protected override void Dispose(bool disposing) { } public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override string? ReadLine() { throw null; } public override System.Threading.Tasks.Task ReadLineAsync() { throw null; } + public override System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public override string ReadToEnd() { throw null; } public override System.Threading.Tasks.Task ReadToEndAsync() { throw null; } + public override System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) { throw null; } } public partial class StreamWriter : System.IO.TextWriter { @@ -10920,8 +10961,10 @@ protected override void Dispose(bool disposing) { } public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override string? ReadLine() { throw null; } public override System.Threading.Tasks.Task ReadLineAsync() { throw null; } + public override System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public override string ReadToEnd() { throw null; } public override System.Threading.Tasks.Task ReadToEndAsync() { throw null; } + public override System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) { throw null; } } public partial class StringWriter : System.IO.TextWriter { @@ -10972,8 +11015,10 @@ protected virtual void Dispose(bool disposing) { } public virtual System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual string? ReadLine() { throw null; } public virtual System.Threading.Tasks.Task ReadLineAsync() { throw null; } + public virtual System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public virtual string ReadToEnd() { throw null; } public virtual System.Threading.Tasks.Task ReadToEndAsync() { throw null; } + public virtual System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public static System.IO.TextReader Synchronized(System.IO.TextReader reader) { throw null; } } public abstract partial class TextWriter : System.MarshalByRefObject, System.IAsyncDisposable, System.IDisposable @@ -11636,7 +11681,7 @@ protected CustomAttributeFormatException(System.Runtime.Serialization.Serializat public CustomAttributeFormatException(string? message) { } public CustomAttributeFormatException(string? message, System.Exception? inner) { } } - public readonly partial struct CustomAttributeNamedArgument + public readonly partial struct CustomAttributeNamedArgument : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -11646,13 +11691,14 @@ public readonly partial struct CustomAttributeNamedArgument public System.Reflection.MemberInfo MemberInfo { get { throw null; } } public string MemberName { get { throw null; } } public System.Reflection.CustomAttributeTypedArgument TypedValue { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Reflection.CustomAttributeNamedArgument other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; } public static bool operator !=(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; } public override string ToString() { throw null; } } - public readonly partial struct CustomAttributeTypedArgument + public readonly partial struct CustomAttributeTypedArgument : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -11660,7 +11706,8 @@ public readonly partial struct CustomAttributeTypedArgument public CustomAttributeTypedArgument(System.Type argumentType, object? value) { throw null; } public System.Type ArgumentType { get { throw null; } } public object? Value { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Reflection.CustomAttributeTypedArgument other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; } public static bool operator !=(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; } @@ -12998,6 +13045,11 @@ public sealed partial class DisablePrivateReflectionAttribute : System.Attribute { public DisablePrivateReflectionAttribute() { } } + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + public sealed class DisableRuntimeMarshallingAttribute : Attribute + { + public DisableRuntimeMarshallingAttribute() { } + } [System.AttributeUsageAttribute(System.AttributeTargets.All)] public partial class DiscardableAttribute : System.Attribute { @@ -13174,6 +13226,11 @@ public sealed partial class PreserveBaseOverridesAttribute : System.Attribute { public PreserveBaseOverridesAttribute() { } } + [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public sealed class RequiredMemberAttribute : System.Attribute + { + public RequiredMemberAttribute() { } + } [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple=false)] public sealed partial class ReferenceAssemblyAttribute : System.Attribute { @@ -13189,6 +13246,7 @@ public RuntimeCompatibilityAttribute() { } } public static partial class RuntimeFeature { + public const string ByRefFields = "ByRefFields"; public const string CovariantReturnsOfClasses = "CovariantReturnsOfClasses"; public const string DefaultImplementationsOfInterfaces = "DefaultImplementationsOfInterfaces"; public const string PortablePdb = "PortablePdb"; @@ -13432,6 +13490,7 @@ public enum Architecture Wasm = 4, S390x = 5, LoongArch64 = 6, + Armv6 = 7, } public enum CharSet { @@ -13476,7 +13535,7 @@ public sealed partial class FieldOffsetAttribute : System.Attribute public FieldOffsetAttribute(int offset) { } public int Value { get { throw null; } } } - public partial struct GCHandle + public partial struct GCHandle : System.IEquatable { private int _dummyPrimitive; public bool IsAllocated { get { throw null; } } @@ -13485,6 +13544,7 @@ public partial struct GCHandle public static System.Runtime.InteropServices.GCHandle Alloc(object? value) { throw null; } public static System.Runtime.InteropServices.GCHandle Alloc(object? value, System.Runtime.InteropServices.GCHandleType type) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } + public bool Equals(System.Runtime.InteropServices.GCHandle other) { throw null; } public void Free() { } public static System.Runtime.InteropServices.GCHandle FromIntPtr(System.IntPtr value) { throw null; } public override int GetHashCode() { throw null; } @@ -14753,7 +14813,7 @@ public static partial class Utf8 } namespace System.Threading { - public readonly partial struct CancellationToken + public readonly partial struct CancellationToken : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj index 801f04ca42ea9..051fe609d634b 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj @@ -62,6 +62,7 @@ + @@ -164,6 +165,7 @@ + diff --git a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs index 1880ea5d31c41..d2d9804912e94 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs @@ -60,5 +60,32 @@ public static void Ctor_String_String_Exception() Assert.Contains(message, exception.Message); Assert.Contains(argumentName, exception.Message); } + + [Fact] + public static void ThrowIfNullOrEmpty_ThrowsForInvalidInput() + { + AssertExtensions.Throws(null, () => ArgumentException.ThrowIfNullOrEmpty(null, null)); + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrEmpty(null, "something")); + + AssertExtensions.Throws(null, () => ArgumentException.ThrowIfNullOrEmpty("", null)); + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrEmpty("", "something")); + + ArgumentException.ThrowIfNullOrEmpty(" "); + ArgumentException.ThrowIfNullOrEmpty(" ", "something"); + ArgumentException.ThrowIfNullOrEmpty("abc", "something"); + } + + [Fact] + public static void ThrowIfNullOrEmpty_UsesArgumentExpression_ParameterNameMatches() + { + string someString = null; + AssertExtensions.Throws(nameof(someString), () => ArgumentException.ThrowIfNullOrEmpty(someString)); + + someString = ""; + AssertExtensions.Throws(nameof(someString), () => ArgumentException.ThrowIfNullOrEmpty(someString)); + + someString = "abc"; + ArgumentException.ThrowIfNullOrEmpty(someString); + } } } diff --git a/src/libraries/System.Runtime/tests/System/ArrayTests.cs b/src/libraries/System.Runtime/tests/System/ArrayTests.cs index e0108b81f3e57..372a4b3416388 100644 --- a/src/libraries/System.Runtime/tests/System/ArrayTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArrayTests.cs @@ -1275,6 +1275,9 @@ public static IEnumerable Copy_SZArray_UnreliableConversion_CanPerform // Interface[] -> Class[] yield return new object[] { new NonGenericInterface1[10], 0, new NonGenericClass1[10], 0, 10, new NonGenericClass1[10] }; + + // object[] -> Int32Enum[] when values are all Int32Enum + yield return new object[] { new object[] { Int32Enum.Case3 }, 0, new Int32Enum[1], 0, 1, new Int32Enum[] { Int32Enum.Case3 } }; } public static IEnumerable Copy_Array_UnreliableConversion_CanPerform_TestData() diff --git a/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs b/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs index 935c75e01bb7c..624b9b508a868 100644 --- a/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs +++ b/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs @@ -513,6 +513,16 @@ public static void TryFormatTest() Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten)); Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "r")); Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "O")); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + dateOnly.TryFormat(buff, out charsWritten, "u"); + }); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + dateOnly.TryFormat(buff, out charsWritten, "hh-ss"); + }); + Assert.Throws(() => $"{dateOnly:u}"); + Assert.Throws(() => $"{dateOnly:hh-ss}"); } } } diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttributeTests.cs new file mode 100644 index 0000000000000..f4de6a4c9fece --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttributeTests.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Diagnostics.CodeAnalysis.Tests +{ + public class SetsRequiredMembersAttributeTests + { + [Fact] + public void TestConstructor() + { + new SetsRequiredMembersAttribute(); + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs new file mode 100644 index 0000000000000..ba53ab2c0f3bb --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Diagnostics.CodeAnalysis.Tests +{ + public sealed class StringSyntaxAttributeTests + { + [Theory] + [InlineData(StringSyntaxAttribute.DateTimeFormat)] + [InlineData(StringSyntaxAttribute.Json)] + [InlineData(StringSyntaxAttribute.Regex)] + public void Ctor_Roundtrips(string syntax) + { + var attribute = new StringSyntaxAttribute(syntax); + Assert.Equal(syntax, attribute.Syntax); + Assert.Empty(attribute.Arguments); + + attribute = new StringSyntaxAttribute(syntax, "a", DayOfWeek.Monday); + Assert.Equal(syntax, attribute.Syntax); + Assert.Equal(new object[] { "a", DayOfWeek.Monday }, attribute.Arguments); + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/UnreachableExceptionTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/UnreachableExceptionTests.cs new file mode 100644 index 0000000000000..24fdc34396655 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/UnreachableExceptionTests.cs @@ -0,0 +1,40 @@ +// 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.Diagnostics; +using Xunit; + +namespace System.Tests +{ + public static class UnreachableExceptionTests + { + [Fact] + public static void DefaultConstructor() + { + UnreachableException unreachableException = new UnreachableException(); + + Assert.NotNull(unreachableException.Message); + } + + [Fact] + public static void MessageConstructor() + { + string message = "MessageConstructor"; + UnreachableException unreachableException = new UnreachableException(message); + + Assert.Equal(message, unreachableException.Message); + } + + [Fact] + public static void MessageInnerExceptionConstructor() + { + string message = "MessageConstructor"; + Exception innerException = new Exception(); + UnreachableException unreachableException = new UnreachableException(); + + Assert.Equal(message, unreachableException.Message); + Assert.Same(innerException, unreachableException.InnerException); + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs b/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs index 909f700f5c8da..9fd7ab4f461a9 100644 --- a/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs +++ b/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs @@ -42,6 +42,7 @@ public void SigTermExitCode(int? exitCodeOnSigterm) RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.RedirectStandardOutput = true; + options.CheckExitCode = false; using (RemoteInvokeHandle remoteExecution = RemoteExecutor.Invoke(action, exitCodeOnSigterm?.ToString() ?? string.Empty, options)) { Process process = remoteExecution.Process; diff --git a/src/libraries/System.Runtime/tests/System/IO/EndOfStreamExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/EndOfStreamExceptionTests.cs index c80eab91b3226..fe734e4c95ae0 100644 --- a/src/libraries/System.Runtime/tests/System/IO/EndOfStreamExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/EndOfStreamExceptionTests.cs @@ -35,8 +35,8 @@ public static void EndOfStreamException_Ctor_String_Exception() EndOfStreamException i = new EndOfStreamException(exceptionMessage, ex); Assert.Equal(exceptionMessage, i.Message); - Assert.Equal(i.InnerException.Message, innerExceptionMessage); - Assert.Equal(i.InnerException.HResult, ex.HResult); + Assert.Equal(innerExceptionMessage, i.InnerException.Message); + Assert.Equal(ex.HResult, i.InnerException.HResult); Assert.Equal(COR_E_ENDOFSTREAM, unchecked((uint)i.HResult)); } } diff --git a/src/libraries/System.Runtime/tests/System/NullReferenceExceptionTests.cs b/src/libraries/System.Runtime/tests/System/NullReferenceExceptionTests.cs index 1e852df6281a3..94f5396778d4e 100644 --- a/src/libraries/System.Runtime/tests/System/NullReferenceExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/NullReferenceExceptionTests.cs @@ -36,8 +36,8 @@ public static void NullReferenceException_Ctor_String_Exception() NullReferenceException i = new NullReferenceException(exceptionMessage, ex); Assert.Equal(exceptionMessage, i.Message); - Assert.Equal(i.InnerException.Message, innerExceptionMessage); - Assert.Equal(i.InnerException.HResult, ex.HResult); + Assert.Equal(innerExceptionMessage, i.InnerException.Message); + Assert.Equal(ex.HResult, i.InnerException.HResult); Assert.Equal(E_POINTER, unchecked((uint)i.HResult)); } } diff --git a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs index 4460797182c87..c406e36ea21c3 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs @@ -52,6 +52,28 @@ public static void Test_CustomAttributeTypedArgument_Constructor() Assert.True(false, "Expected to find MyAttr Attribute"); } + [Fact] + public static void Test_CustomAttributeTypedArgument_Equals() + { + Type t = typeof(MyClass); + foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(t)) + { + foreach (CustomAttributeTypedArgument cata in cad.ConstructorArguments) + { + Assert.True(cata.Equals(cata)); + Assert.True(cata.Equals((object)cata)); + + var notEqualArgument = new CustomAttributeTypedArgument(new [] { new CustomAttributeTypedArgument(0) }); + Assert.False(cata.Equals(notEqualArgument)); + Assert.False(cata.Equals((object)notEqualArgument)); + + return; + } + } + + Assert.True(false, "Expected to find MyAttr Attribute"); + } + [Fact] public static void Test_CustomAttributeTypedArgument_ToString() { diff --git a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs index f444a5624c6bb..7dd057d8cca0a 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO.Enumeration; +using System.Runtime.Serialization; using System.Text.RegularExpressions; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -30,10 +31,10 @@ public static IEnumerable FieldTestData() yield return new object[] { "FieldDisallowNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "FieldAllowNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldDisallowNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "FieldAllowNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "FieldAllowNull2", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "FieldNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "FieldMaybeNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "FieldMaybeNull2", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "FieldNotNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; } @@ -86,11 +87,12 @@ public static IEnumerable PropertyTestData() yield return new object[] { "PropertyDisallowNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "PropertyAllowNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyDisallowNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "PropertyAllowNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "PropertyAllowNull2", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "PropertyNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "PropertyMaybeNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "PropertyMaybeNull2", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "PropertyNotNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "Item", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; } [Theory] @@ -433,7 +435,7 @@ public void GenericFieldNullableValueTypeTest(string fieldName, NullabilityState Assert.Equal(type, nullability.Type); } - public static IEnumerable GenericNotnullConstraintFieldsTestData() + public static IEnumerable GenericNotNullConstraintFieldsTestData() { yield return new object[] { "FieldNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldUnknown", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; @@ -441,7 +443,7 @@ public static IEnumerable GenericNotnullConstraintFieldsTestData() } [Theory] - [MemberData(nameof(GenericNotnullConstraintFieldsTestData))] + [MemberData(nameof(GenericNotNullConstraintFieldsTestData))] public void GenericNotNullConstraintFieldsTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) { FieldInfo field = typeof(GenericTestConstrainedNotNull).GetField(fieldName, flags)!; @@ -570,7 +572,7 @@ public void GenericListAndDictionaryFieldTest() public static IEnumerable MethodReturnParameterTestData() { - yield return new object[] { "MethodReturnsUnknown", NullabilityState.Unknown, NullabilityState.Unknown}; + yield return new object[] { "MethodReturnsUnknown", NullabilityState.Unknown, NullabilityState.Unknown }; yield return new object[] { "MethodReturnsNullNon", NullabilityState.Nullable, NullabilityState.NotNull }; yield return new object[] { "MethodReturnsNullNull", NullabilityState.Nullable, NullabilityState.Nullable }; yield return new object[] { "MethodReturnsNonNull", NullabilityState.NotNull, NullabilityState.Nullable }; @@ -671,7 +673,7 @@ public void MethodParametersTest(string methodName, NullabilityState stringState public static IEnumerable MethodGenericParametersTestData() { - yield return new object[] { "MethodParametersUnknown", NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown}; + yield return new object[] { "MethodParametersUnknown", NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown }; yield return new object[] { "MethodArgsNullGenericNullDictValueGeneric", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable }; yield return new object[] { "MethodArgsGenericDictValueNullGeneric", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull }; } @@ -710,7 +712,7 @@ public void NullablePublicOnlyStringTypeTest(string methodName, NullabilityState Assert.Equal(param1State, param1.ReadState); Assert.Equal(param2State, param2.ReadState); Assert.Equal(param3State, param3.ReadState); - if (param2.ElementType != null) + if (param2.ElementType != null) { Assert.Equal(NullabilityState.Nullable, param2.ElementType.ReadState); } @@ -739,7 +741,7 @@ public void NullablePublicOnlyOtherTypesTest() PropertyInfo publicGetPrivateSetNullableProperty = typeof(FileSystemEntry).GetProperty("Directory", flags)!; info = nullabilityContext.Create(publicGetPrivateSetNullableProperty); Assert.Equal(NullabilityState.NotNull, info.ReadState); - Assert.Equal(NullabilityState.Unknown, info.WriteState); + Assert.Equal(NullabilityState.NotNull, info.WriteState); MethodInfo protectedNullableReturnMethod = type.GetMethod("GetPropertyImpl", flags)!; info = nullabilityContext.Create(protectedNullableReturnMethod.ReturnParameter); @@ -748,8 +750,8 @@ public void NullablePublicOnlyOtherTypesTest() MethodInfo privateValueTypeReturnMethod = type.GetMethod("BinarySearch", flags)!; info = nullabilityContext.Create(privateValueTypeReturnMethod.ReturnParameter); - Assert.Equal(NullabilityState.Unknown, info.ReadState); - Assert.Equal(NullabilityState.Unknown, info.WriteState); + Assert.Equal(NullabilityState.NotNull, info.ReadState); + Assert.Equal(NullabilityState.NotNull, info.WriteState); Type regexType = typeof(Regex); FieldInfo protectedInternalNullableField = regexType.GetField("pattern", flags)!; @@ -761,13 +763,18 @@ public void NullablePublicOnlyOtherTypesTest() info = nullabilityContext.Create(privateNullableField); Assert.Equal(NullabilityState.Unknown, info.ReadState); Assert.Equal(NullabilityState.Unknown, info.WriteState); + + ConstructorInfo privateConstructor = typeof(IndexOutOfRangeException) + .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, new[] { typeof(SerializationInfo), typeof(StreamingContext) })!; + info = nullabilityContext.Create(privateConstructor.GetParameters()[0]); + Assert.Equal(NullabilityState.Unknown, info.WriteState); } public static IEnumerable DifferentContextTestData() { yield return new object[] { "PropertyDisabled", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; - yield return new object[] { "PropertyDisabledAllowNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; - yield return new object[] { "PropertyDisabledMaybeNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyDisabledAllowNull", NullabilityState.Unknown, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "PropertyDisabledMaybeNull", NullabilityState.Nullable, NullabilityState.Unknown, typeof(string) }; yield return new object[] { "PropertyEnabledAllowNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; @@ -850,6 +857,42 @@ public void AttributedParametersTest() Assert.Equal(NullabilityState.NotNull, nullabilityContext.Create(tryGetOutParameters[0]).ReadState); } + public static IEnumerable NestedGenericsCorrectOrderData() + { + yield return new object[] { + "MethodReturnsNonTupleNonTupleNullStringNullStringNullString", + new[] { NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.Nullable }, + new[] { typeof(Tuple, string>), typeof(Tuple), typeof(string), typeof(string), typeof(string) } + }; + yield return new object[] { + "MethodReturnsNonTupleNonTupleNullStringNullStringNonString", + new[] { NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull }, + new[] { typeof(Tuple, string>), typeof(Tuple), typeof(string), typeof(string), typeof(string) } + }; + } + + [Theory] + [MemberData(nameof(NestedGenericsCorrectOrderData))] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void NestedGenericsCorrectOrderTest(string methodName, NullabilityState[] nullStates, Type[] types) + { + NullabilityInfo parentInfo = nullabilityContext.Create(typeof(TypeWithNotNullContext).GetMethod(methodName)!.ReturnParameter); + var dataIndex = 0; + Examine(parentInfo); + Assert.Equal(nullStates.Length, dataIndex); + Assert.Equal(types.Length, dataIndex); + + void Examine(NullabilityInfo info) + { + Assert.Equal(types[dataIndex], info.Type); + Assert.Equal(nullStates[dataIndex++], info.ReadState); + for (var i = 0; i < info.GenericTypeArguments.Length; i++) + { + Examine(info.GenericTypeArguments[i]); + } + } + } + public static IEnumerable NestedGenericsReturnParameterData() { // public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; @@ -948,6 +991,105 @@ public void TestValueTupleGenericTypeParameters(string fieldName, NullabilitySta Assert.Equal(param1, tupleInfo.GenericTypeArguments[0].ReadState); Assert.Equal(param2, tupleInfo.GenericTypeArguments[1].ReadState); } + + public static IEnumerable GenericInheritanceTestData() + { + yield return new object?[] { typeof(ListOfUnconstrained), NullabilityState.Nullable, null }; + yield return new object?[] { typeof(ListUnconstrainedOfNullable), NullabilityState.Nullable, null }; + yield return new object?[] { typeof(ListUnconstrainedOfNullableOfObject<>), NullabilityState.NotNull, null }; + yield return new object?[] { typeof(ListOfArrayOfNullableString), NullabilityState.NotNull, NullabilityState.Nullable }; + yield return new object?[] { typeof(ListOfNotNull>), NullabilityState.NotNull, NullabilityState.NotNull }; + yield return new object?[] { typeof(ListOfListOfObject), NullabilityState.NotNull, NullabilityState.NotNull }; + yield return new object?[] { typeof(ListMultiGenericOfNotNull), NullabilityState.NotNull, null }; + } + + [Theory] + [MemberData(nameof(GenericInheritanceTestData))] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void TestGenericInheritance(Type listType, NullabilityState parameterState, NullabilityState? subState) + { + var addParameterInfo = nullabilityContext.Create(listType.GetMethod("Add")!.GetParameters()[0]); + Validate(addParameterInfo); + + var copyToParameterInfo = nullabilityContext.Create( + listType.GetMethod("CopyTo", new[] { addParameterInfo.Type.MakeArrayType() })! + .GetParameters()[0]); + Assert.Equal(NullabilityState.NotNull, copyToParameterInfo.ReadState); + Assert.Equal(NullabilityState.NotNull, copyToParameterInfo.WriteState); + Assert.NotNull(copyToParameterInfo.ElementType); + Validate(copyToParameterInfo.ElementType!); + + void Validate(NullabilityInfo info) + { + Assert.Equal(parameterState, info.ReadState); + Assert.Equal(parameterState, info.WriteState); + if (subState != null) + { + NullabilityInfo subInfo = info.ElementType ?? info.GenericTypeArguments[0]; + Assert.Equal(subState, subInfo.ReadState); + Assert.Equal(subState, subInfo.WriteState); + Assert.True(info.GenericTypeArguments.Length <= 1); + } + else + { + Assert.Null(info.ElementType); + Assert.Empty(info.GenericTypeArguments); + } + } + } + + [Fact] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void TestDeeplyNestedGenericInheritance() + { + var copyToMethodInfo = nullabilityContext.Create( + typeof(ListOfTupleOfDictionaryOfStringNullableBoolIntNullableObject).GetMethod("CopyTo", new[] { typeof((Dictionary, int, object?)[]) })! + .GetParameters()[0]); + + Validate(copyToMethodInfo, typeof((Dictionary, int, object?)[]), NullabilityState.NotNull); + Assert.NotNull(copyToMethodInfo.ElementType); + + var tupleInfo = copyToMethodInfo.ElementType!; + Validate(tupleInfo, typeof((Dictionary, int, object?)), NullabilityState.NotNull); + + var dictionaryInfo = tupleInfo.GenericTypeArguments[0]; + Validate(dictionaryInfo, typeof(Dictionary), NullabilityState.NotNull); + + var stringInfo = dictionaryInfo.GenericTypeArguments[0]; + Validate(stringInfo, typeof(string), NullabilityState.NotNull); + + var nullableBoolInfo = dictionaryInfo.GenericTypeArguments[1]; + Validate(nullableBoolInfo, typeof(bool?), NullabilityState.Nullable); + + var intInfo = tupleInfo.GenericTypeArguments[1]; + Validate(intInfo, typeof(int), NullabilityState.NotNull); + + var objectInfo = tupleInfo.GenericTypeArguments[2]; + Validate(objectInfo, typeof(object), NullabilityState.Nullable); + + void Validate(NullabilityInfo info, Type type, NullabilityState state) + { + Assert.Equal(type, info.Type); + Assert.Equal(state, info.ReadState); + Assert.Equal(state, info.WriteState); + Assert.Equal(type.IsGenericType && type.GetGenericTypeDefinition() != typeof(Nullable<>) ? type.GetGenericArguments().Length : 0, info.GenericTypeArguments.Length); + Assert.Equal(type.IsArray, info.ElementType is not null); + } + } + + [Fact] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void TestNestedGenericInheritanceWithMultipleParameters() + { + var item3Info = nullabilityContext.Create(typeof(DerivesFromTupleOfNestedGenerics).GetProperty("Item3")!); + + Assert.Equal(typeof(IDisposable[]), item3Info.Type); + Assert.Equal(NullabilityState.Nullable, item3Info.ReadState); + Assert.Equal(NullabilityState.Unknown, item3Info.WriteState); // read-only property + + Assert.Equal(NullabilityState.NotNull, item3Info.ElementType!.ReadState); + Assert.Equal(NullabilityState.NotNull, item3Info.ElementType.WriteState); + } } #pragma warning disable CS0649, CS0067, CS0414 @@ -987,7 +1129,7 @@ public class TypeWithNoContext [AllowNull] public string PropertyEnabledAllowNull { get; set; } [NotNull] public string? PropertyEnabledNotNull { get; set; } = null!; [DisallowNull] public string? PropertyEnabledDisallowNull { get; set; } = null!; - [MaybeNull] public string PropertyEnabledMaybeNull { get; set; } + [MaybeNull] public string PropertyEnabledMaybeNull { get; set; } public string? PropertyEnabledNullable { get; set; } public string PropertyEnabledNonNullable { get; set; } = null!; #nullable disable @@ -1023,14 +1165,15 @@ public void MethodParametersUnknown(string s, IDictionary dict) [AllowNull] public string PropertyAllowNull { get; set; } [NotNull] public string? PropertyNotNull { get; set; } [MaybeNull] public string PropertyMaybeNull { get; set; } - // only AllowNull matter + // only DisallowNull matters [AllowNull, DisallowNull] public string PropertyAllowNull2 { get; set; } - // only DisallowNull matter + // only AllowNull matters [AllowNull, DisallowNull] public string? PropertyDisallowNull2 { get; set; } - // only NotNull matter + // only NotNull matters [NotNull, MaybeNull] public string? PropertyNotNull2 { get; set; } - // only MaybeNull matter + // only NotNull matters [NotNull, MaybeNull] public string PropertyMaybeNull2 { get; set; } + [DisallowNull] public string? this[int i] { get => null; set { } } private protected string?[]?[]? PropertyJaggedArrayNullNullNull { get; set; } public static string?[]?[] PropertyJaggedArrayNullNullNon { get; set; } = null!; public string?[][]? PropertyJaggedArrayNullNonNull { get; set; } @@ -1089,6 +1232,8 @@ public void MethodParametersUnknown(string s, IDictionary dict) public IEnumerable?, int>?>? MethodReturnsEnumerableNullStructNullNonNullTupleNonNullNull() => null; public IEnumerable?, int>?>? MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull() => null; public IEnumerable<(GenericStruct str, int? count)> MethodReturnsEnumerableNonValueTupleNonNullNonStructNonNullNon() => null!; + public Tuple, string?> MethodReturnsNonTupleNonTupleNullStringNullStringNullString() => null!; + public Tuple, string> MethodReturnsNonTupleNonTupleNullStringNullStringNonString() => null!; public void MethodNullNonNullNonNon(string? s, IDictionary dict) { } public void MethodNonNullNonNullNotNull(string s, [NotNull] IDictionary? dict) { dict = new Dictionary(); } public void MethodNullNonNullNullNon(string? s, IDictionary dict) { } @@ -1136,7 +1281,7 @@ public void MethodParametersUnknown(T s, IDictionary dict) { } [DisallowNull] public T? FieldDisallowNull; [AllowNull] protected T FieldAllowNull; [NotNull] public T? FieldNotNull = default; - [MaybeNull] protected internal T FieldMaybeNull = default!; + [MaybeNull] protected internal T FieldMaybeNull = default!; public List FieldListOfT = default!; public Dictionary FieldDictionaryStringToT = default!; @@ -1175,4 +1320,33 @@ internal class GenericTestConstrainedStruct where T : struct public T PropertyNullableEnabled { get; set; } public T? PropertyNullable { get; set; } } + + public class ListOfUnconstrained : List { } + + public class ListUnconstrainedOfNullable : ListOfUnconstrained where T : class? { } + + public class ListUnconstrainedOfNullableOfObject : ListUnconstrainedOfNullable { } + + public class ListOfArrayOfNullableString : List { } + + public class ListOfNotNull : List where T : notnull { } + + public class ListOfListOfObject : List> { } + + public class ListMultiGenericOfNotNull : List + where T : class? + where U : class + where V : class? + { + } + + public class ListOfTupleOfDictionaryOfStringNullableBoolIntNullableObject : List<(Dictionary, int, object?)> { } + + public class DerivesFromTupleOfNestedGenerics : Tuple, Dictionary>, IDisposable[]?> + { + public DerivesFromTupleOfNestedGenerics(List item1, Dictionary> item2, IDisposable[]? item3) + : base(item1, item2, item3) + { + } + } } diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs index 4e641224dffc4..dbba5a966f7b0 100644 --- a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -320,5 +320,11 @@ public static void InterpolatedStringHandlerArgumentAttributeTests(string firstP Assert.Equal(firstParameterName, attr2.Arguments[0]); Assert.Equal("param2", attr2.Arguments[1]); } + + [Fact] + public static void RequiredMemberAttributeTests() + { + new RequiredMemberAttribute(); + } } } diff --git a/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.cs b/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.cs index 89bf734808fe2..23f37e4949ab4 100644 --- a/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.cs +++ b/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.cs @@ -2268,8 +2268,6 @@ public static unsafe void FailureOnLargeString() string s = new string('x', 500_000_000); sb.Append(s); // This should throw, not AV }); - - return RemoteExecutor.SuccessExitCode; // workaround https://github.com/dotnet/arcade/issues/5865 }).Dispose(); } } diff --git a/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs b/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs index b39e94e00d1dc..f74a401274748 100644 --- a/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs @@ -483,6 +483,17 @@ public static void TryFormatTest() Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten)); Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "r")); Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "O")); + + Assert.Throws(() => { + Span buff = stackalloc char[100]; + timeOnly.TryFormat(buff, out charsWritten, "u"); + }); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + timeOnly.TryFormat(buff, out charsWritten, "dd-yyyy"); + }); + Assert.Throws(() => $"{timeOnly:u}"); + Assert.Throws(() => $"{timeOnly:dd-yyyy}"); } } } diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index b352a529d6b00..e3e5bdd4564f3 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2489,6 +2489,7 @@ public static void GetSystemTimeZones_AllTimeZonesHaveOffsetInValidRange() // 0x3E, 0x2C, 0x30, 0x2F, 0x30, 0x2C, 0x4A, 0x33, 0x36, 0x35, 0x2F, 0x32, 0x35, 0x0A }; + [ActiveIssue("https://github.com/dotnet/runtime/issues/64134")] [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [PlatformSpecific(TestPlatforms.AnyUnix)] [InlineData("<+00>0<+01>,0/0,J365/25", 1, 1, true)] @@ -2921,6 +2922,20 @@ public static void AdjustmentRuleBaseUtcOffsetDeltaTest() Assert.Equal(new TimeSpan(2, 0, 0), customTimeZone.GetUtcOffset(new DateTime(2021, 3, 10, 2, 0, 0))); } + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64111", TestPlatforms.Linux)] + public static void NoBackwardTimeZones() + { + ReadOnlyCollection tzCollection = TimeZoneInfo.GetSystemTimeZones(); + HashSet tzDisplayNames = new HashSet(); + + foreach (TimeZoneInfo timezone in tzCollection) + { + tzDisplayNames.Add(timezone.DisplayName); + } + Assert.Equal(tzCollection.Count, tzDisplayNames.Count); + } + private static bool IsEnglishUILanguage => CultureInfo.CurrentUICulture.Name.Length == 0 || CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "en"; private static bool IsEnglishUILanguageAndRemoteExecutorSupported => IsEnglishUILanguage && RemoteExecutor.IsSupported; diff --git a/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.Forwards.cs b/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.Forwards.cs new file mode 100644 index 0000000000000..2bdc10900f7aa --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.Forwards.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Win32.SafeHandles.SafeNCryptHandle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.AesCng))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngAlgorithm))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngAlgorithmGroup))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngExportPolicies))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKey))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyBlobFormat))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyCreationOptions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyCreationParameters))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyHandleOpenOptions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyOpenOptions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngKeyUsages))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngProperty))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngPropertyCollection))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngPropertyOptions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngUIPolicy))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CngUIProtectionLevels))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.DSACng))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDiffieHellmanCng))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDiffieHellmanCngPublicKey))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDsaCng))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECKeyXmlFormat))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.RSACng))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.TripleDESCng))] diff --git a/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.cs b/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.cs deleted file mode 100644 index 66568a4158949..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.cs +++ /dev/null @@ -1,390 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the https://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -namespace Microsoft.Win32.SafeHandles -{ - public abstract partial class SafeNCryptHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid - { - protected SafeNCryptHandle() : base (default(bool)) { } - protected SafeNCryptHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) : base (default(bool)) { } - public override bool IsInvalid { get { throw null; } } - protected override bool ReleaseHandle() { throw null; } - protected abstract bool ReleaseNativeHandle(); - } - public sealed partial class SafeNCryptKeyHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - public SafeNCryptKeyHandle() { } - public SafeNCryptKeyHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) { } - protected override bool ReleaseNativeHandle() { throw null; } - } - public sealed partial class SafeNCryptProviderHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - public SafeNCryptProviderHandle() { } - protected override bool ReleaseNativeHandle() { throw null; } - } - public sealed partial class SafeNCryptSecretHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - public SafeNCryptSecretHandle() { } - protected override bool ReleaseNativeHandle() { throw null; } - } -} -namespace System.Security.Cryptography -{ - public sealed partial class AesCng : System.Security.Cryptography.Aes - { - public AesCng() { } - public AesCng(string keyName) { } - public AesCng(string keyName, System.Security.Cryptography.CngProvider provider) { } - public AesCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { } - public override byte[] Key { get { throw null; } set { } } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - protected override void Dispose(bool disposing) { } - public override void GenerateIV() { } - public override void GenerateKey() { } - } - public sealed partial class CngAlgorithm : System.IEquatable - { - public CngAlgorithm(string algorithm) { } - public string Algorithm { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellman { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP256 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP384 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP521 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDsa { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDsaP256 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDsaP384 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm ECDsaP521 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm MD5 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm Rsa { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm Sha1 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm Sha256 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm Sha384 { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithm Sha512 { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngAlgorithm? other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Security.Cryptography.CngAlgorithm? left, System.Security.Cryptography.CngAlgorithm? right) { throw null; } - public static bool operator !=(System.Security.Cryptography.CngAlgorithm? left, System.Security.Cryptography.CngAlgorithm? right) { throw null; } - public override string ToString() { throw null; } - } - public sealed partial class CngAlgorithmGroup : System.IEquatable - { - public CngAlgorithmGroup(string algorithmGroup) { } - public string AlgorithmGroup { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithmGroup DiffieHellman { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithmGroup Dsa { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithmGroup ECDiffieHellman { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithmGroup ECDsa { get { throw null; } } - public static System.Security.Cryptography.CngAlgorithmGroup Rsa { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngAlgorithmGroup? other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Security.Cryptography.CngAlgorithmGroup? left, System.Security.Cryptography.CngAlgorithmGroup? right) { throw null; } - public static bool operator !=(System.Security.Cryptography.CngAlgorithmGroup? left, System.Security.Cryptography.CngAlgorithmGroup? right) { throw null; } - public override string ToString() { throw null; } - } - [System.FlagsAttribute] - public enum CngExportPolicies - { - None = 0, - AllowExport = 1, - AllowPlaintextExport = 2, - AllowArchiving = 4, - AllowPlaintextArchiving = 8, - } - public sealed partial class CngKey : System.IDisposable - { - internal CngKey() { } - public System.Security.Cryptography.CngAlgorithm Algorithm { get { throw null; } } - public System.Security.Cryptography.CngAlgorithmGroup? AlgorithmGroup { get { throw null; } } - public System.Security.Cryptography.CngExportPolicies ExportPolicy { get { throw null; } } - public Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle Handle { get { throw null; } } - public bool IsEphemeral { get { throw null; } } - public bool IsMachineKey { get { throw null; } } - public string? KeyName { get { throw null; } } - public int KeySize { get { throw null; } } - public System.Security.Cryptography.CngKeyUsages KeyUsage { get { throw null; } } - public System.IntPtr ParentWindowHandle { get { throw null; } set { } } - public System.Security.Cryptography.CngProvider? Provider { get { throw null; } } - public Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle ProviderHandle { get { throw null; } } - public System.Security.Cryptography.CngUIPolicy UIPolicy { get { throw null; } } - public string? UniqueName { get { throw null; } } - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm) { throw null; } - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string? keyName) { throw null; } - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string? keyName, System.Security.Cryptography.CngKeyCreationParameters? creationParameters) { throw null; } - public void Delete() { } - public void Dispose() { } - public static bool Exists(string keyName) { throw null; } - public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider) { throw null; } - public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions options) { throw null; } - public byte[] Export(System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } - public System.Security.Cryptography.CngProperty GetProperty(string name, System.Security.Cryptography.CngPropertyOptions options) { throw null; } - public bool HasProperty(string name, System.Security.Cryptography.CngPropertyOptions options) { throw null; } - public static System.Security.Cryptography.CngKey Import(byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } - public static System.Security.Cryptography.CngKey Import(byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format, System.Security.Cryptography.CngProvider provider) { throw null; } - public static System.Security.Cryptography.CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, System.Security.Cryptography.CngKeyHandleOpenOptions keyHandleOpenOptions) { throw null; } - public static System.Security.Cryptography.CngKey Open(string keyName) { throw null; } - public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider) { throw null; } - public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { throw null; } - public void SetProperty(System.Security.Cryptography.CngProperty property) { } - } - public sealed partial class CngKeyBlobFormat : System.IEquatable - { - public CngKeyBlobFormat(string format) { } - public static System.Security.Cryptography.CngKeyBlobFormat EccFullPrivateBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat EccFullPublicBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat EccPrivateBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat EccPublicBlob { get { throw null; } } - public string Format { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat GenericPrivateBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat GenericPublicBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat OpaqueTransportBlob { get { throw null; } } - public static System.Security.Cryptography.CngKeyBlobFormat Pkcs8PrivateBlob { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngKeyBlobFormat? other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Security.Cryptography.CngKeyBlobFormat? left, System.Security.Cryptography.CngKeyBlobFormat? right) { throw null; } - public static bool operator !=(System.Security.Cryptography.CngKeyBlobFormat? left, System.Security.Cryptography.CngKeyBlobFormat? right) { throw null; } - public override string ToString() { throw null; } - } - [System.FlagsAttribute] - public enum CngKeyCreationOptions - { - None = 0, - MachineKey = 32, - OverwriteExistingKey = 128, - } - public sealed partial class CngKeyCreationParameters - { - public CngKeyCreationParameters() { } - public System.Security.Cryptography.CngExportPolicies? ExportPolicy { get { throw null; } set { } } - public System.Security.Cryptography.CngKeyCreationOptions KeyCreationOptions { get { throw null; } set { } } - public System.Security.Cryptography.CngKeyUsages? KeyUsage { get { throw null; } set { } } - public System.Security.Cryptography.CngPropertyCollection Parameters { get { throw null; } } - public System.IntPtr ParentWindowHandle { get { throw null; } set { } } - public System.Security.Cryptography.CngProvider Provider { get { throw null; } set { } } - public System.Security.Cryptography.CngUIPolicy? UIPolicy { get { throw null; } set { } } - } - [System.FlagsAttribute] - public enum CngKeyHandleOpenOptions - { - None = 0, - EphemeralKey = 1, - } - [System.FlagsAttribute] - public enum CngKeyOpenOptions - { - None = 0, - UserKey = 0, - MachineKey = 32, - Silent = 64, - } - [System.FlagsAttribute] - public enum CngKeyUsages - { - None = 0, - Decryption = 1, - Signing = 2, - KeyAgreement = 4, - AllUsages = 16777215, - } - public partial struct CngProperty : System.IEquatable - { - private object _dummy; - private int _dummyPrimitive; - public CngProperty(string name, byte[]? value, System.Security.Cryptography.CngPropertyOptions options) { throw null; } - public readonly string Name { get { throw null; } } - public readonly System.Security.Cryptography.CngPropertyOptions Options { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public bool Equals(System.Security.Cryptography.CngProperty other) { throw null; } - public override int GetHashCode() { throw null; } - public byte[]? GetValue() { throw null; } - public static bool operator ==(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) { throw null; } - public static bool operator !=(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) { throw null; } - } - public sealed partial class CngPropertyCollection : System.Collections.ObjectModel.Collection - { - public CngPropertyCollection() { } - } - [System.FlagsAttribute] - public enum CngPropertyOptions - { - Persist = -2147483648, - None = 0, - CustomProperty = 1073741824, - } - public sealed partial class CngProvider : System.IEquatable - { - public CngProvider(string provider) { } - public static System.Security.Cryptography.CngProvider MicrosoftPlatformCryptoProvider { get { throw null; } } - public static System.Security.Cryptography.CngProvider MicrosoftSmartCardKeyStorageProvider { get { throw null; } } - public static System.Security.Cryptography.CngProvider MicrosoftSoftwareKeyStorageProvider { get { throw null; } } - public string Provider { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngProvider? other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Security.Cryptography.CngProvider? left, System.Security.Cryptography.CngProvider? right) { throw null; } - public static bool operator !=(System.Security.Cryptography.CngProvider? left, System.Security.Cryptography.CngProvider? right) { throw null; } - public override string ToString() { throw null; } - } - public sealed partial class CngUIPolicy - { - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel) { } - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName) { } - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description) { } - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description, string? useContext) { } - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description, string? useContext, string? creationTitle) { } - public string? CreationTitle { get { throw null; } } - public string? Description { get { throw null; } } - public string? FriendlyName { get { throw null; } } - public System.Security.Cryptography.CngUIProtectionLevels ProtectionLevel { get { throw null; } } - public string? UseContext { get { throw null; } } - } - [System.FlagsAttribute] - public enum CngUIProtectionLevels - { - None = 0, - ProtectKey = 1, - ForceHighProtection = 2, - } - public sealed partial class DSACng : System.Security.Cryptography.DSA - { - public DSACng() { } - public DSACng(int keySize) { } - public DSACng(System.Security.Cryptography.CngKey key) { } - public System.Security.Cryptography.CngKey Key { get { throw null; } } - public override string? KeyExchangeAlgorithm { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override string SignatureAlgorithm { get { throw null; } } - public override byte[] CreateSignature(byte[] rgbHash) { throw null; } - protected override void Dispose(bool disposing) { } - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } - public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } - } - public sealed partial class ECDiffieHellmanCng : System.Security.Cryptography.ECDiffieHellman - { - public ECDiffieHellmanCng() { } - public ECDiffieHellmanCng(int keySize) { } - public ECDiffieHellmanCng(System.Security.Cryptography.CngKey key) { } - public ECDiffieHellmanCng(System.Security.Cryptography.ECCurve curve) { } - public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get { throw null; } set { } } - public byte[]? HmacKey { get { throw null; } set { } } - public System.Security.Cryptography.CngKey Key { get { throw null; } } - public System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get { throw null; } set { } } - public override int KeySize { get { throw null; } set { } } - public byte[]? Label { get { throw null; } set { } } - public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get { throw null; } } - public byte[]? SecretAppend { get { throw null; } set { } } - public byte[]? SecretPrepend { get { throw null; } set { } } - public byte[]? Seed { get { throw null; } set { } } - public bool UseSecretAgreementAsHmacKey { get { throw null; } } - public override byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } - public override byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? hmacKey, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } - public byte[] DeriveKeyMaterial(System.Security.Cryptography.CngKey otherPartyPublicKey) { throw null; } - public override byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) { throw null; } - public override byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) { throw null; } - public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.CngKey otherPartyPublicKey) { throw null; } - public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) { throw null; } - protected override void Dispose(bool disposing) { } - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } - public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) { } - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } - public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) { throw null; } - } - public sealed partial class ECDiffieHellmanCngPublicKey : System.Security.Cryptography.ECDiffieHellmanPublicKey - { - // ECDiffieHellmanPublicKey parameter-less ctor only exist on .NET Framework 4.7+ - private ECDiffieHellmanCngPublicKey() : base(null) { } - public System.Security.Cryptography.CngKeyBlobFormat BlobFormat { get { throw null; } } - protected override void Dispose(bool disposing) { } - public override System.Security.Cryptography.ECParameters ExportExplicitParameters() { throw null; } - public override System.Security.Cryptography.ECParameters ExportParameters() { throw null; } - public static System.Security.Cryptography.ECDiffieHellmanPublicKey FromByteArray(byte[] publicKeyBlob, System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } - public static System.Security.Cryptography.ECDiffieHellmanCngPublicKey FromXmlString(string xml) { throw null; } - public System.Security.Cryptography.CngKey Import() { throw null; } - public override string ToXmlString() { throw null; } - } - public enum ECDiffieHellmanKeyDerivationFunction - { - Hash = 0, - Hmac = 1, - Tls = 2, - } - public sealed partial class ECDsaCng : System.Security.Cryptography.ECDsa - { - public ECDsaCng() { } - public ECDsaCng(int keySize) { } - public ECDsaCng(System.Security.Cryptography.CngKey key) { } - public ECDsaCng(System.Security.Cryptography.ECCurve curve) { } - public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get { throw null; } set { } } - public System.Security.Cryptography.CngKey Key { get { throw null; } } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - protected override void Dispose(bool disposing) { } - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } - public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) { } - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } - public byte[] SignData(byte[] data) { throw null; } - public byte[] SignData(byte[] data, int offset, int count) { throw null; } - public byte[] SignData(System.IO.Stream data) { throw null; } - public override byte[] SignHash(byte[] hash) { throw null; } - public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) { throw null; } - public bool VerifyData(byte[] data, byte[] signature) { throw null; } - public bool VerifyData(byte[] data, int offset, int count, byte[] signature) { throw null; } - public bool VerifyData(System.IO.Stream data, byte[] signature) { throw null; } - public override bool VerifyHash(byte[] hash, byte[] signature) { throw null; } - } - public enum ECKeyXmlFormat - { - Rfc4050 = 0, - } - public sealed partial class RSACng : System.Security.Cryptography.RSA - { - public RSACng() { } - public RSACng(int keySize) { } - public RSACng(System.Security.Cryptography.CngKey key) { } - public System.Security.Cryptography.CngKey Key { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override byte[] Decrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - protected override void Dispose(bool disposing) { } - public override byte[] Encrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } - public override byte[] SignHash(byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - public override bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - } - public sealed partial class TripleDESCng : System.Security.Cryptography.TripleDES - { - public TripleDESCng() { } - public TripleDESCng(string keyName) { } - public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider) { } - public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { } - public override byte[] Key { get { throw null; } set { } } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - protected override void Dispose(bool disposing) { } - public override void GenerateIV() { } - public override void GenerateKey() { } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj b/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj index a473a5b9cbae8..a333acc015182 100644 --- a/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj @@ -4,11 +4,10 @@ enable - + - - \ No newline at end of file + diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/Helpers.cs deleted file mode 100644 index 3cbf93ae7510d..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/Helpers.cs +++ /dev/null @@ -1,178 +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.Diagnostics; -using System.Globalization; -using System.Security.Cryptography; -using System.Runtime.InteropServices; - -using Microsoft.Win32.SafeHandles; - -using ErrorCode = Interop.NCrypt.ErrorCode; - -namespace Internal.Cryptography -{ - internal static partial class Helpers - { - public static bool UsesIv(this CipherMode cipherMode) - { - return cipherMode != CipherMode.ECB; - } - - public static byte[]? GetCipherIv(this CipherMode cipherMode, byte[]? iv) - { - if (cipherMode.UsesIv()) - { - if (iv == null) - { - throw new CryptographicException(SR.Cryptography_MissingIV); - } - - return iv; - } - - return null; - } - - // - // The C# construct - // - // fixed (byte* p = new byte[0]) - // - // sets "p" to 0 rather than a valid address. Sometimes, we actually want a non-NULL pointer instead. (Some CNG apis actually care whether the buffer pointer is - // NULL or not, even if the accompanying size argument is 0.) - // - // This helper enables the syntax: - // - // fixed (byte* p = new byte[0].MapZeroLengthArrayToNonNullPointer()) - // - // which always sets "p" to a non-NULL pointer for a non-null byte array. - // - public static byte[]? MapZeroLengthArrayToNonNullPointer(this byte[]? src) - { - if (src != null && src.Length == 0) - return new byte[1]; - return src; - } - - public static SafeNCryptProviderHandle OpenStorageProvider(this CngProvider provider) - { - string providerName = provider.Provider; - SafeNCryptProviderHandle providerHandle; - ErrorCode errorCode = Interop.NCrypt.NCryptOpenStorageProvider(out providerHandle, providerName, 0); - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - return providerHandle; - } - - /// - /// Returns a CNG key property. - /// - /// - /// null - if property not defined on key. - /// throws - for any other type of error. - /// - public static byte[]? GetProperty(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) - { - unsafe - { - int numBytesNeeded; - ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, null, 0, out numBytesNeeded, options); - if (errorCode == ErrorCode.NTE_NOT_FOUND) - return null; - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - - byte[] propertyValue = new byte[numBytesNeeded]; - fixed (byte* pPropertyValue = propertyValue) - { - errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, pPropertyValue, propertyValue.Length, out numBytesNeeded, options); - } - if (errorCode == ErrorCode.NTE_NOT_FOUND) - return null; - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - - Array.Resize(ref propertyValue, numBytesNeeded); - return propertyValue; - } - } - - /// - /// Retrieve a well-known CNG string property. (Note: .NET Framework compat: this helper likes to return special values rather than throw exceptions for missing - /// or ill-formatted property values. Only use it for well-known properties that are unlikely to be ill-formatted.) - /// - public static string? GetPropertyAsString(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) - { - byte[]? value = ncryptHandle.GetProperty(propertyName, options); - if (value == null) - return null; // .NET Framework compat: return null if key not present. - if (value.Length == 0) - return string.Empty; // .NET Framework compat: return empty if property value is 0-length. - unsafe - { - fixed (byte* pValue = &value[0]) - { - string? valueAsString = Marshal.PtrToStringUni((IntPtr)pValue); - return valueAsString; - } - } - } - - /// - /// Retrieve a well-known CNG dword property. (Note: .NET Framework compat: this helper likes to return special values rather than throw exceptions for missing - /// or ill-formatted property values. Only use it for well-known properties that are unlikely to be ill-formatted.) - /// - public static int GetPropertyAsDword(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) - { - byte[]? value = ncryptHandle.GetProperty(propertyName, options); - if (value == null) - return 0; // .NET Framework compat: return 0 if key not present. - return BitConverter.ToInt32(value, 0); - } - - /// - /// Retrieve a well-known CNG pointer property. (Note: .NET Framework compat: this helper likes to return special values rather than throw exceptions for missing - /// or ill-formatted property values. Only use it for well-known properties that are unlikely to be ill-formatted.) - /// - public static IntPtr GetPropertyAsIntPtr(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) - { - unsafe - { - IntPtr value; - ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, &value, IntPtr.Size, out _, options); - if (errorCode == ErrorCode.NTE_NOT_FOUND) - return IntPtr.Zero; - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - return value; - } - } - - /// - /// Modify a CNG key's export policy. - /// - public static void SetExportPolicy(this SafeNCryptKeyHandle keyHandle, CngExportPolicies exportPolicy) - { - unsafe - { - ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ExportPolicy, &exportPolicy, sizeof(CngExportPolicies), CngPropertyOptions.Persist); - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - } - } - - public static int BitSizeToByteSize(this int bits) - { - return (bits + 7) / 8; - } - - public static byte[] GenerateRandom(int count) - { - byte[] buffer = new byte[count]; - RandomNumberGenerator.Fill(buffer); - return buffer; - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/KeyPropertyName.cs b/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/KeyPropertyName.cs deleted file mode 100644 index 03986a9010343..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/KeyPropertyName.cs +++ /dev/null @@ -1,40 +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.Diagnostics; - -namespace Internal.Cryptography -{ - /// - /// Well known names of key properties - /// - internal static class KeyPropertyName - { - internal const string Algorithm = "Algorithm Name"; // NCRYPT_ALGORITHM_PROPERTY - internal const string AlgorithmGroup = "Algorithm Group"; // NCRYPT_ALGORITHM_GROUP_PROPERTY - internal const string ECCCurveName = "ECCCurveName"; // NCRYPT_ECC_CURVE_NAME - internal const string ECCParameters = "ECCParameters"; // BCRYPT_ECC_PARAMETERS - internal const string ExportPolicy = "Export Policy"; // NCRYPT_EXPORT_POLICY_PROPERTY - internal const string KeyType = "Key Type"; // NCRYPT_KEY_TYPE_PROPERTY - internal const string KeyUsage = "Key Usage"; // NCRYPT_KEY_USAGE_PROPERTY - internal const string Length = "Length"; // NCRYPT_LENGTH_PROPERTY - internal const string Name = "Name"; // NCRYPT_NAME_PROPERTY - internal const string ParentWindowHandle = "HWND Handle"; // NCRYPT_WINDOW_HANDLE_PROPERTY - internal const string PublicKeyLength = "PublicKeyLength"; // NCRYPT_PUBLIC_KEY_LENGTH (Win10+) - internal const string ProviderHandle = "Provider Handle"; // NCRYPT_PROVIDER_HANDLE_PROPERTY - internal const string UIPolicy = "UI Policy"; // NCRYPT_UI_POLICY_PROPERTY - internal const string UniqueName = "Unique Name"; // NCRYPT_UNIQUE_NAME_PROPERTY - internal const string UseContext = "Use Context"; // NCRYPT_USE_CONTEXT_PROPERTY - - // - // Properties defined by the CLR - // - - /// - /// Is the key a CLR created ephemeral key, it will contain a single byte with value 1 if the - /// key was created by the CLR as an ephemeral key. - /// - internal const string ClrIsEphemeral = "CLR IsEphemeral"; - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/SymmetricImportExportExtensions.cs b/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/SymmetricImportExportExtensions.cs deleted file mode 100644 index ff988a0da5e07..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/SymmetricImportExportExtensions.cs +++ /dev/null @@ -1,67 +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.IO; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Security.Cryptography; - -namespace Internal.Cryptography -{ - internal static class SymmetricImportExportExtensions - { - - /// - /// Note! This can and likely will throw if the algorithm was given a hardware-based key. - /// - public static byte[] GetSymmetricKeyDataIfExportable(this CngKey cngKey, string algorithm) - { - byte[] keyBlob = cngKey.Export(s_cipherKeyBlobFormat); - using (MemoryStream ms = new MemoryStream(keyBlob)) - { - using (BinaryReader br = new BinaryReader(ms, Encoding.Unicode)) - { - // Read NCRYPT_KEY_BLOB_HEADER - int cbSize = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbSize - if (cbSize != SizeOf_NCRYPT_KEY_BLOB_HEADER_SIZE) - throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); - - int ncryptMagic = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.dwMagic - if (ncryptMagic != Interop.NCrypt.NCRYPT_CIPHER_KEY_BLOB_MAGIC) - throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); - - int cbAlgName = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbAlgName - - br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbKey - - string algorithmName = new string(br.ReadChars((cbAlgName / 2) - 1)); - if (algorithmName != algorithm) - throw new CryptographicException(SR.Format(SR.Cryptography_CngKeyWrongAlgorithm, algorithmName, algorithm)); - - char nullTerminator = br.ReadChar(); - if (nullTerminator != 0) - throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); - - // Read BCRYPT_KEY_DATA_BLOB_HEADER - int bcryptMagic = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.dwMagic - if (bcryptMagic != Interop.BCrypt.BCRYPT_KEY_DATA_BLOB_MAGIC) - throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); - - int dwVersion = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.dwVersion - if (dwVersion != Interop.BCrypt.BCRYPT_KEY_DATA_BLOB_VERSION1) - throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); - - int keyLength = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.cbKeyData - byte[] key = br.ReadBytes(keyLength); - return key; - } - } - } - - private const int SizeOf_NCRYPT_KEY_BLOB_HEADER_SIZE = sizeof(int) + sizeof(int) + sizeof(int) + sizeof(int); - - private static readonly CngKeyBlobFormat s_cipherKeyBlobFormat = new CngKeyBlobFormat(Interop.NCrypt.NCRYPT_CIPHER_KEY_BLOB); - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Cng/src/Resources/Strings.resx deleted file mode 100644 index 4c99946a673e8..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/Resources/Strings.resx +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - Non-negative number required. - - - The destination is too small to hold the encoded value. - - - The method cannot be called with an invalid or closed SafeHandle. - - - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. - - - The OID value was invalid. - - - Value was invalid. - - - Buffer cannot be null. - - - Positive number required. - - - Algorithm '{0}' is not supported on this platform. - - - The KDF for algorithm '{0}' requires a char-based password input. - - - The keys from both parties must be the same size to generate a secret agreement. - - - Keys used with the ECDiffieHellmanCng algorithm must have an algorithm group of ECDiffieHellman. - - - DeriveKeyMaterial requires an ECDiffieHellmanCngPublicKey. - - - ASN.1 Enumerated values only apply to enum types without the [Flags] attribute. - - - Named bit list operations require an enum with the [Flags] attribute. - - - The encoded named bit list value is larger than the value size of the '{0}' enum. - - - Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written. - - - Unused bit count must be between 0 and 7, inclusive. - - - Encode cannot be called while a Sequence or SetOf is still open. - - - Cannot pop the requested tag as it is not currently in progress. - - - The TLS key derivation function requires both the label and seed properties to be set. - - - Keys used with the DSACng algorithm must have an algorithm group of DSA. - - - Keys used with the ECDsaCng algorithm must have an algorithm group of ECDsa. - - - Keys used with the RSACng algorithm must have an algorithm group of RSA. - - - The specified feedback size '{0}' for CipherMode '{1}' is not supported. - - - This key is for algorithm '{0}'. Expected '{1}'. - - - ASN1 corrupted data. - - - The message exceeds the maximum allowable length for the chosen options ({0}). - - - The hash algorithm name cannot be null or empty. - - - The algorithm group '{0}' is invalid. - - - The algorithm name '{0}' is invalid. - - - Specified cipher mode is not valid for this algorithm. - - - The specified DSA parameters are not valid; P, Q, G and Y are all required. - - - The specified DSA parameters are not valid; P, G and Y must be the same length (the key size). - - - The specified DSA parameters are not valid; Q and X (if present) must be the same length. - - - The specified DSA parameters are not valid; J (if present) must be shorter than P. - - - The specified DSA parameters are not valid; Seed, if present, must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q's length must be one of 20, 32 or 64 bytes. - - - The specified curve '{0}' or its parameters are not valid for this platform. - - - The specified Oid is not valid. The Oid.FriendlyName or Oid.Value property must be set. - - - Specified initialization vector (IV) does not match the block size for this algorithm. - - - The key blob format '{0}' is invalid. - - - Specified key is not a valid size for this algorithm. - - - Padding is invalid and cannot be removed. - - - The provider name '{0}' is invalid. - - - The specified RSA parameters are not valid. Exponent and Modulus are required. If D is present, it must have the same length as Modulus. If D is present, P, Q, DP, DQ, and InverseQ are required and must have half the length of Modulus, rounded up, otherwise they must be omitted. - - - Key Blob not in expected format. - - - The key is too small for the requested operation. - - - The CNG key handle being opened was detected to be ephemeral, but the EphemeralKey open option was not specified. - - - Cannot open an invalid handle. - - - The cipher mode specified requires that an initialization vector (IV) be used. - - - TransformBlock may only process bytes in block sized increments. - - - Key is not a valid private key. - - - Key is not a valid public or private key. - - - Error occurred while decoding OAEP padding. - - - The input data is not a complete block. - - - The length of the data to decrypt is not valid for the size of this key. - - - The EncryptedPrivateKeyInfo structure was decoded but was not successfully interpreted, the password may be incorrect. - - - The provided hash value is not the expected size for the specified hash algorithm. - - - The specified PaddingMode is not supported. - - - Attempt to transform beyond end of buffer. - - - CNG provider unexpectedly terminated encryption or decryption prematurely. - - - The algorithm identified by '{0}' is unknown, not valid for the requested usage, or was not handled. - - - '{0}' is not a known hash algorithm. - - - Unknown padding mode used. - - - Specified key is a known weak key for this algorithm and cannot be used. - - - The input to WriteEncodedValue must represent a single encoded value with no trailing data. - - - Windows Cryptography Next Generation (CNG) is not supported on this platform. - - - Only named curves are supported on this platform. - - - Object contains only the public half of a key pair. A private key must also be provided. - - - The specified Characteristic2 curve parameters are not valid. Polynomial, A, B, G.X, G.Y, and Order are required. A, B, G.X, G.Y must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Seed, Cofactor and Hash are optional. Other parameters are not allowed. - - - Destination is too short. - - - The current platform does not support the specified feedback size. - - diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj b/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj index fa3b70f4d35ab..1fe031a388f59 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj @@ -1,380 +1,10 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) - true - enable + $(NetCoreAppCurrent) + true - - - SR.PlatformNotSupported_CryptographyCng - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.manual.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\PBEParameter.xml - - - Common\System\Security\Cryptography\Asn1\PBEParameter.xml.cs - Common\System\Security\Cryptography\Asn1\PBEParameter.xml - - - Common\System\Security\Cryptography\Asn1\PBES2Params.xml - - - Common\System\Security\Cryptography\Asn1\PBES2Params.xml.cs - Common\System\Security\Cryptography\Asn1\PBES2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml.cs - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml.cs - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml - - - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml.cs - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.manual.cs - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml - - - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml.cs - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml - - - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml - - - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml.cs - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml - - - Common\System\Security\Cryptography\Asn1\CurveAsn.xml - - - Common\System\Security\Cryptography\Asn1\CurveAsn.xml.cs - Common\System\Security\Cryptography\Asn1\CurveAsn.xml - - - Common\System\Security\Cryptography\Asn1\FieldID.xml - - - Common\System\Security\Cryptography\Asn1\FieldID.xml.cs - Common\System\Security\Cryptography\Asn1\FieldID.xml - - - Common\System\Security\Cryptography\Asn1\FieldID.xml - - - Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml.cs - Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPkcs8.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPkcs8.cs deleted file mode 100644 index 9b93cf8151023..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPkcs8.cs +++ /dev/null @@ -1,52 +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.Buffers; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Security.Cryptography.Asn1; - -namespace System.Security.Cryptography -{ - internal static partial class CngPkcs8 - { - internal struct Pkcs8Response - { - internal CngKey Key; - - internal string GetAlgorithmGroup() - { - return Key.AlgorithmGroup!.AlgorithmGroup; - } - - internal void FreeKey() - { - Key.Dispose(); - } - } - - private static Pkcs8Response ImportPkcs8(ReadOnlySpan keyBlob) - { - CngKey key = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob); - key.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; - - return new Pkcs8Response - { - Key = key, - }; - } - - private static Pkcs8Response ImportPkcs8( - ReadOnlySpan keyBlob, - ReadOnlySpan password) - { - CngKey key = CngKey.ImportEncryptedPkcs8(keyBlob, password); - key.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; - - return new Pkcs8Response - { - Key = key, - }; - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.cs deleted file mode 100644 index b01714761966d..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.cs +++ /dev/null @@ -1,42 +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 Internal.Cryptography; - -namespace System.Security.Cryptography -{ - public sealed partial class DSACng : DSA - { - private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(DSACng)); - - /// - /// Creates a new DSACng object that will use the specified key. The key's - /// must be Dsa. This constructor - /// creates a copy of the key. Hence, the caller can safely dispose of the - /// passed in key and continue using the DSACng object. - /// - /// Key to use for DSA operations - /// if is not an DSA key - /// if is null. - public DSACng(CngKey key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - - if (key.AlgorithmGroup != CngAlgorithmGroup.Dsa) - throw new ArgumentException(SR.Cryptography_ArgDSARequiresDSAKey, nameof(key)); - - Key = CngAlgorithmCore.Duplicate(key); - } - - protected override void Dispose(bool disposing) - { - _core.Dispose(); - } - - private void ThrowIfDisposed() - { - _core.ThrowIfDisposed(); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs deleted file mode 100644 index deca9cfd932ee..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs +++ /dev/null @@ -1,146 +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 Microsoft.Win32.SafeHandles; - -namespace System.Security.Cryptography -{ - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman - { - public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - - if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey) - { - using (CngKey import = otherKey.Import()) - { - return DeriveKeyMaterial(import); - } - } - - // This deviates from the .NET Framework behavior. .NET Framework can't handle unknown public - // key types, but on .NET Core there are automatically two: the public class produced by - // this class' PublicKey member, and the private class produced by ECDiffieHellman.Create().PublicKey - // - // So let's just work. - ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); - - using (ECDiffieHellmanCng otherPartyCng = new ECDiffieHellmanCng()) - { - otherPartyCng.ImportParameters(otherPartyParameters); - - using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey) - using (CngKey importedKey = otherKey.Import()) - { - return DeriveKeyMaterial(importedKey); - } - } - } - - public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); - if (otherPartyPublicKey.KeySize != KeySize) - throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); - - // Setting the flag to UseSecretAsHmacKey even when the KDF isn't HMAC, because that's what .NET Framework does. - Interop.NCrypt.SecretAgreementFlags flags = - UseSecretAgreementAsHmacKey - ? Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey - : Interop.NCrypt.SecretAgreementFlags.None; - - using (SafeNCryptSecretHandle handle = DeriveSecretAgreementHandle(otherPartyPublicKey)) - { - switch (KeyDerivationFunction) - { - case ECDiffieHellmanKeyDerivationFunction.Hash: - return Interop.NCrypt.DeriveKeyMaterialHash( - handle, - HashAlgorithm.Algorithm, - _secretPrepend, - _secretAppend, - flags); - case ECDiffieHellmanKeyDerivationFunction.Hmac: - return Interop.NCrypt.DeriveKeyMaterialHmac( - handle, - HashAlgorithm.Algorithm, - _hmacKey, - _secretPrepend, - _secretAppend, - flags); - case ECDiffieHellmanKeyDerivationFunction.Tls: - if (_label == null || _seed == null) - { - throw new InvalidOperationException(SR.Cryptography_TlsRequiresLabelAndSeed); - } - - return Interop.NCrypt.DeriveKeyMaterialTls( - handle, - _label, - _seed, - flags); - default: - Debug.Fail($"Unknown KDF ({KeyDerivationFunction})"); - // Match .NET Framework behavior - goto case ECDiffieHellmanKeyDerivationFunction.Tls; - } - } - } - - /// - /// Get a handle to the secret agreement generated between two parties - /// - public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - - if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey) - { - using (CngKey importedKey = otherKey.Import()) - { - return DeriveSecretAgreementHandle(importedKey); - } - } - - ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); - - using (ECDiffieHellmanCng otherPartyCng = new ECDiffieHellmanCng()) - { - otherPartyCng.ImportParameters(otherPartyParameters); - - using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey) - using (CngKey importedKey = otherKey.Import()) - { - return DeriveSecretAgreementHandle(importedKey); - } - } - } - - /// - /// Get a handle to the secret agreement between two parties - /// - public SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) - { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); - if (otherPartyPublicKey.KeySize != KeySize) - throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); - - // This looks strange, but the Handle property returns a duplicate so we need to dispose of it when we're done - using (SafeNCryptKeyHandle localHandle = Key.Handle) - using (SafeNCryptKeyHandle otherPartyHandle = otherPartyPublicKey.Handle) - { - return Interop.NCrypt.DeriveSecretAgreement(localHandle, otherPartyHandle); - } - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs deleted file mode 100644 index baf5046f242e3..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs +++ /dev/null @@ -1,135 +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 Microsoft.Win32.SafeHandles; - -namespace System.Security.Cryptography -{ - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman - { - /// - /// Public key used to generate key material with the second party - /// - public override ECDiffieHellmanPublicKey PublicKey - { - get - { - return ECDiffieHellmanCngPublicKey.FromKey(Key); - } - } - - /// - /// Gets the key that will be used by the ECDH object for any cryptographic operation that it uses. - /// This key object will be disposed if the key is reset, for instance by changing the KeySize - /// property, using ImportParamers to create a new key, or by Disposing of the parent ECDH object. - /// Therefore, you should make sure that the key object is no longer used in these scenarios. This - /// object will not be the same object as the CngKey passed to the ECDHCng constructor if that - /// constructor was used, however it will point at the same CNG key. - /// - public CngKey Key - { - get - { - return GetKey(); - } - - private set - { - if (value == null) - throw new ArgumentNullException(nameof(value)); - if (value.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(value)); - - _core.SetKey(value); - - // LegalKeySizes stores the values for either the current named curve or for the three - // curves that use size instead of name - ForceSetKeySize(value.KeySize); - } - } - - public override void GenerateKey(ECCurve curve) - { - curve.Validate(); - _core.DisposeKey(); - - if (curve.IsNamed) - { - if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); - - // Map curve name to algorithm to support pre-Win10 curves - CngAlgorithm alg = CngKey.EcdhCurveNameToAlgorithm(curve.Oid.FriendlyName); - if (CngKey.IsECNamedCurve(alg.Algorithm)) - { - CngKey key = _core.GetOrGenerateKey(curve); - ForceSetKeySize(key.KeySize); - } - else - { - int keySize; - // Get the proper KeySize from algorithm name - if (alg == CngAlgorithm.ECDiffieHellmanP256) - keySize = 256; - else if (alg == CngAlgorithm.ECDiffieHellmanP384) - keySize = 384; - else if (alg == CngAlgorithm.ECDiffieHellmanP521) - keySize = 521; - else - { - Debug.Fail($"Unknown algorithm {alg}"); - throw new ArgumentException(SR.Cryptography_InvalidKeySize); - } - _core.GetOrGenerateKey(keySize, alg); - ForceSetKeySize(keySize); - } - } - else if (curve.IsExplicit) - { - CngKey key = _core.GetOrGenerateKey(curve); - ForceSetKeySize(key.KeySize); - } - else - { - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); - } - } - - private CngKey GetKey() - { - CngKey key; - - if (_core.IsKeyGeneratedNamedCurve()) - { - // Curve was previously created, so use that - key = _core.GetOrGenerateKey(null); - } - else - { - CngAlgorithm algorithm; - - // Map the current key size to a CNG algorithm name - int keySize = KeySize; - switch (keySize) - { - case 256: - algorithm = CngAlgorithm.ECDiffieHellmanP256; - break; - case 384: - algorithm = CngAlgorithm.ECDiffieHellmanP384; - break; - case 521: - algorithm = CngAlgorithm.ECDiffieHellmanP521; - break; - default: - Debug.Fail("Should not have invalid key size"); - throw new ArgumentException(SR.Cryptography_InvalidKeySize); - } - key = _core.GetOrGenerateKey(keySize, algorithm); - } - - return key; - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.cs deleted file mode 100644 index c6baf43ef1aec..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.cs +++ /dev/null @@ -1,209 +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 Internal.Cryptography; - -namespace System.Security.Cryptography -{ - /// - /// Key derivation functions used to transform the raw secret agreement into key material - /// - public enum ECDiffieHellmanKeyDerivationFunction - { - Hash, - Hmac, - Tls - } - - /// - /// Wrapper for CNG's implementation of elliptic curve Diffie-Hellman key exchange - /// - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman - { - private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(ECDiffieHellmanCng)) { DefaultKeyType = CngAlgorithm.ECDiffieHellman }; - private CngAlgorithm _hashAlgorithm = CngAlgorithm.Sha256; - private ECDiffieHellmanKeyDerivationFunction _kdf = ECDiffieHellmanKeyDerivationFunction.Hash; - private byte[]? _hmacKey; - private byte[]? _label; - private byte[]? _secretAppend; - private byte[]? _secretPrepend; - private byte[]? _seed; - - public ECDiffieHellmanCng(CngKey key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - - if (key.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(key)); - - Key = CngAlgorithmCore.Duplicate(key); - } - - /// - /// Hash algorithm used with the Hash and HMAC KDFs - /// - public CngAlgorithm HashAlgorithm - { - get - { - return _hashAlgorithm; - } - - set - { - if (_hashAlgorithm == null) - { - throw new ArgumentNullException(nameof(value)); - } - - _hashAlgorithm = value; - } - } - - /// - /// KDF used to transform the secret agreement into key material - /// - public ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction - { - get - { - return _kdf; - } - - set - { - if (value < ECDiffieHellmanKeyDerivationFunction.Hash || value > ECDiffieHellmanKeyDerivationFunction.Tls) - { - throw new ArgumentOutOfRangeException(nameof(value)); - } - - _kdf = value; - } - } - - /// - /// Key used with the HMAC KDF - /// - public byte[]? HmacKey - { - get { return _hmacKey; } - set { _hmacKey = value; } - } - - /// - /// Label bytes used for the TLS KDF - /// - public byte[]? Label - { - get { return _label; } - set { _label = value; } - } - - /// - /// Bytes to append to the raw secret agreement before processing by the KDF - /// - public byte[]? SecretAppend - { - get { return _secretAppend; } - set { _secretAppend = value; } - } - - /// - /// Bytes to prepend to the raw secret agreement before processing by the KDF - /// - public byte[]? SecretPrepend - { - get { return _secretPrepend; } - set { _secretPrepend = value; } - } - - /// - /// Seed bytes used for the TLS KDF - /// - public byte[]? Seed - { - get { return _seed; } - set { _seed = value; } - } - - /// - /// Use the secret agreement as the HMAC key rather than supplying a seperate one - /// - public bool UseSecretAgreementAsHmacKey - { - get { return HmacKey == null; } - } - - protected override void Dispose(bool disposing) - { - _core.Dispose(); - } - - private void ThrowIfDisposed() - { - _core.ThrowIfDisposed(); - } - - private void DisposeKey() - { - _core.DisposeKey(); - } - - internal string? GetCurveName(out string? oidValue) - { - return Key.GetCurveName(out oidValue); - } - - private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) - { - Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); - } - - private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) - { - Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); - } - - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - return ECCng.ExportKeyBlob(Key, includePrivateParameters); - } - - private byte[] ExportFullKeyBlob(bool includePrivateParameters) - { - return ECCng.ExportFullKeyBlob(Key, includePrivateParameters); - } - - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - Key = response.Key; - } - - public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) - { - return Key.TryExportKeyBlob( - Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, - destination, - out bytesWritten); - } - - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - return Key.ExportPkcs8KeyBlob(pkcs8Password, kdfCount); - } - - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - return Key.TryExportPkcs8KeyBlob( - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs deleted file mode 100644 index 0ae53b6920413..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Security.Cryptography -{ - /// - /// Public key used to do key exchange with the ECDiffieHellmanCng algorithm - /// - public sealed partial class ECDiffieHellmanCngPublicKey : ECDiffieHellmanPublicKey - { - private readonly CngKeyBlobFormat _format; - private readonly string? _curveName; - private bool _disposed; - - /// - /// Wrap a CNG key - /// - internal ECDiffieHellmanCngPublicKey(byte[] keyBlob, string? curveName, CngKeyBlobFormat format) : base(keyBlob) - { - _format = format; - // Can be null for P256, P384, P521, or an explicit blob - _curveName = curveName; - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _disposed = true; - } - - base.Dispose(disposing); - } - - public override string ToXmlString() - { - throw new PlatformNotSupportedException(); - } - - public static ECDiffieHellmanCngPublicKey FromXmlString(string xml) - { - throw new PlatformNotSupportedException(); - } - - /// - /// Format the key blob is expressed in - /// - public CngKeyBlobFormat BlobFormat - { - get - { - return _format; - } - } - - /// - /// Hydrate a public key from a blob - /// - public static ECDiffieHellmanPublicKey FromByteArray(byte[] publicKeyBlob, CngKeyBlobFormat format) - { - if (publicKeyBlob == null) - throw new ArgumentNullException(nameof(publicKeyBlob)); - if (format == null) - throw new ArgumentNullException(nameof(format)); - - // Verify that the key can import successfully, because we did in the past. - using (CngKey imported = CngKey.Import(publicKeyBlob, format)) - { - if (imported.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) - { - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey); - } - - return new ECDiffieHellmanCngPublicKey(publicKeyBlob, null, format); - } - } - - internal static ECDiffieHellmanCngPublicKey FromKey(CngKey key) - { - CngKeyBlobFormat format; - string? curveName; - byte[] blob = ECCng.ExportKeyBlob(key, false, out format, out curveName); - return new ECDiffieHellmanCngPublicKey(blob, curveName, format); - } - - /// - /// Import the public key into CNG - /// - /// - public CngKey Import() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(ECDiffieHellmanCngPublicKey)); - } - - return CngKey.Import(ToByteArray(), _curveName, BlobFormat); - } - - /// - /// Exports the key and explicit curve parameters used by the ECC object into an object. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// - /// if explicit export is not supported by this platform. Windows 10 or higher is required. - /// - /// The key and explicit curve parameters used by the ECC object. - public override ECParameters ExportExplicitParameters() - { - using (CngKey key = Import()) - { - ECParameters ecparams = default; - byte[] blob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); - ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters: false); - return ecparams; - } - } - - /// - /// Exports the key used by the ECC object into an object. - /// If the key was created as a named curve, the Curve property will contain named curve parameters - /// otherwise it will contain explicit parameters. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// The key and named curve parameters used by the ECC object. - public override ECParameters ExportParameters() - { - using (CngKey key = Import()) - { - ECParameters ecparams = default; - string? curveName = key.GetCurveName(out _); - - if (string.IsNullOrEmpty(curveName)) - { - byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); - ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters: false); - } - else - { - byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters: false); - ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters: false); - ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); - } - - return ecparams; - } - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.Key.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.Key.cs deleted file mode 100644 index aabaf16795753..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.Key.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Security.Cryptography -{ - using Microsoft.Win32.SafeHandles; - using System.Diagnostics; - - public sealed partial class ECDsaCng : ECDsa - { - /// - /// Gets the key that will be used by the ECDsa object for any cryptographic operation that it uses. - /// This key object will be disposed if the key is reset, for instance by changing the KeySize - /// property, using ImportParamers to create a new key, or by Disposing of the parent ECDsa object. - /// Therefore, you should make sure that the key object is no longer used in these scenarios. This - /// object will not be the same object as the CngKey passed to the ECDsaCng constructor if that - /// constructor was used, however it will point at the same CNG key. - /// - public CngKey Key - { - get - { - return GetKey(); - } - - private set - { - if (value == null) - throw new ArgumentNullException(nameof(value)); - - if (!IsEccAlgorithmGroup(value.AlgorithmGroup)) - throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(value)); - _core.SetKey(value); - - // LegalKeySizes stores the values for either the current named curve or for the three - // curves that use size instead of name - ForceSetKeySize(value.KeySize); - } - } - - public override void GenerateKey(ECCurve curve) - { - curve.Validate(); - _core.DisposeKey(); - - if (curve.IsNamed) - { - if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); - - // Map curve name to algorithm to support pre-Win10 curves - CngAlgorithm alg = CngKey.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName); - if (CngKey.IsECNamedCurve(alg.Algorithm)) - { - CngKey key = _core.GetOrGenerateKey(curve); - ForceSetKeySize(key.KeySize); - } - else - { - int keySize; - // Get the proper KeySize from algorithm name - if (alg == CngAlgorithm.ECDsaP256) - keySize = 256; - else if (alg == CngAlgorithm.ECDsaP384) - keySize = 384; - else if (alg == CngAlgorithm.ECDsaP521) - keySize = 521; - else - { - Debug.Fail($"Unknown algorithm {alg}"); - throw new ArgumentException(SR.Cryptography_InvalidKeySize); - } - _core.GetOrGenerateKey(keySize, alg); - ForceSetKeySize(keySize); - } - } - else if (curve.IsExplicit) - { - CngKey key = _core.GetOrGenerateKey(curve); - ForceSetKeySize(key.KeySize); - } - else - { - throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); - } - } - - private CngKey GetKey() - { - CngKey key; - - if (_core.IsKeyGeneratedNamedCurve()) - { - // Curve was previously created, so use that - key = _core.GetOrGenerateKey(null); - } - else - { - CngAlgorithm algorithm; - - // Map the current key size to a CNG algorithm name - int keySize = KeySize; - switch (keySize) - { - case 256: algorithm = CngAlgorithm.ECDsaP256; break; - case 384: algorithm = CngAlgorithm.ECDsaP384; break; - case 521: algorithm = CngAlgorithm.ECDsaP521; break; - default: - Debug.Fail("Should not have invalid key size"); - throw new ArgumentException(SR.Cryptography_InvalidKeySize); - } - key = _core.GetOrGenerateKey(keySize, algorithm); - } - - return key; - } - - private SafeNCryptKeyHandle GetDuplicatedKeyHandle() - { - return Key.Handle; - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.cs deleted file mode 100644 index 19dd910a4cc88..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDsaCng.cs +++ /dev/null @@ -1,154 +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.IO; -using Internal.Cryptography; - -namespace System.Security.Cryptography -{ - public sealed partial class ECDsaCng : ECDsa - { - private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(ECDsaCng)); - private CngAlgorithm _hashAlgorithm = CngAlgorithm.Sha256; - - /// - /// Hash algorithm to use when generating a signature over arbitrary data - /// - public CngAlgorithm HashAlgorithm - { - get - { - return _hashAlgorithm; - } - set - { - _hashAlgorithm = value ?? throw new ArgumentNullException(nameof(value)); - } - } - - /// - /// Creates a new ECDsaCng object that will use the specified key. The key's - /// must be ECDsa. This constructor - /// creates a copy of the key. Hence, the caller can safely dispose of the - /// passed in key and continue using the ECDsaCng object. - /// - /// Key to use for ECDsa operations - /// if is not an ECDsa key - /// if is null. - public ECDsaCng(CngKey key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - - if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) - throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(key)); - - Key = CngAlgorithmCore.Duplicate(key); - } - - protected override void Dispose(bool disposing) - { - _core.Dispose(); - } - - private void ThrowIfDisposed() - { - _core.ThrowIfDisposed(); - } - - private void DisposeKey() - { - _core.DisposeKey(); - } - - private static bool IsEccAlgorithmGroup(CngAlgorithmGroup? algorithmGroup) - { - // Sometimes, when reading from certificates, ECDSA keys get identified as ECDH. - // Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA), - // so either value is acceptable for the ECDSA wrapper object. - // - // It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG. - return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman; - } - - internal string? GetCurveName(out string? oidValue) - { - return Key.GetCurveName(out oidValue); - } - - private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) - { - Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); - } - - private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) - { - Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); - } - - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - return ECCng.ExportKeyBlob(Key, includePrivateParameters); - } - - private byte[] ExportFullKeyBlob(bool includePrivateParameters) - { - return ECCng.ExportFullKeyBlob(Key, includePrivateParameters); - } - - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - Key = response.Key; - } - - public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) - { - return Key.TryExportKeyBlob( - Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, - destination, - out bytesWritten); - } - - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - return Key.ExportPkcs8KeyBlob(pkcs8Password, kdfCount); - } - - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - return Key.TryExportPkcs8KeyBlob( - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - - public void FromXmlString(string xml, ECKeyXmlFormat format) - => throw new PlatformNotSupportedException(); - - public byte[] SignData(byte[] data) - => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); - - public byte[] SignData(byte[] data, int offset, int count) => - SignData(data, offset, count, new HashAlgorithmName(HashAlgorithm.Algorithm)); - - public byte[] SignData(Stream data) - => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); - - public string ToXmlString(ECKeyXmlFormat format) - => throw new PlatformNotSupportedException(); - - public bool VerifyData(byte[] data, byte[] signature) - => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); - - public bool VerifyData(byte[] data, int offset, int count, byte[] signature) - => VerifyData(data, offset, count, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); - - public bool VerifyData(Stream data, byte[] signature) - => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); - } -} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.cs b/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.cs deleted file mode 100644 index 8910ab5453dc1..0000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.cs +++ /dev/null @@ -1,42 +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 Internal.Cryptography; - -namespace System.Security.Cryptography -{ - public sealed partial class RSACng : RSA - { - private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(RSACng)); - - /// - /// Creates a new RSACng object that will use the specified key. The key's - /// must be Rsa. This constructor - /// creates a copy of the key. Hence, the caller can safely dispose of the - /// passed in key and continue using the RSACng object. - /// - /// Key to use for RSA operations - /// if is not an RSA key - /// if is null. - public RSACng(CngKey key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - - if (key.AlgorithmGroup != CngAlgorithmGroup.Rsa) - throw new ArgumentException(SR.Cryptography_ArgRSARequiresRSAKey, nameof(key)); - - Key = CngAlgorithmCore.Duplicate(key); - } - - protected override void Dispose(bool disposing) - { - _core.Dispose(); - } - - private void ThrowIfDisposed() - { - _core.ThrowIfDisposed(); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.Forwards.cs b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.Forwards.cs new file mode 100644 index 0000000000000..b79fa6a3d2e10 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.Forwards.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. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +#pragma warning disable SYSLIB0021 +#pragma warning disable SYSLIB0023 + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.AesCryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CspKeyContainerInfo))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CspParameters))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.CspProviderFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.DESCryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.DSACryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ICspAsymmetricAlgorithm))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.KeyNumber))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.MD5CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.PasswordDeriveBytes))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.RC2CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.RNGCryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.RSACryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.SHA1CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.SHA256CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.SHA384CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.SHA512CryptoServiceProvider))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.TripleDESCryptoServiceProvider))] diff --git a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs deleted file mode 100644 index c266badaac767..0000000000000 --- a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs +++ /dev/null @@ -1,306 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the https://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -namespace System.Security.Cryptography -{ - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class AesCryptoServiceProvider : System.Security.Cryptography.Aes - { - public AesCryptoServiceProvider() { } - public override int BlockSize { get { throw null; } set { } } - public override int FeedbackSize { get { throw null; } set { } } - public override byte[] IV { get { throw null; } set { } } - public override byte[] Key { get { throw null; } set { } } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override System.Security.Cryptography.CipherMode Mode { get { throw null; } set { } } - public override System.Security.Cryptography.PaddingMode Padding { get { throw null; } set { } } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - protected override void Dispose(bool disposing) { } - public override void GenerateIV() { } - public override void GenerateKey() { } - } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public sealed partial class CspKeyContainerInfo - { - public CspKeyContainerInfo(System.Security.Cryptography.CspParameters parameters) { } - public bool Accessible { get { throw null; } } - public bool Exportable { get { throw null; } } - public bool HardwareDevice { get { throw null; } } - public string? KeyContainerName { get { throw null; } } - public System.Security.Cryptography.KeyNumber KeyNumber { get { throw null; } } - public bool MachineKeyStore { get { throw null; } } - public bool Protected { get { throw null; } } - public string? ProviderName { get { throw null; } } - public int ProviderType { get { throw null; } } - public bool RandomlyGenerated { get { throw null; } } - public bool Removable { get { throw null; } } - public string UniqueKeyContainerName { get { throw null; } } - } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public sealed partial class CspParameters - { - public string? KeyContainerName; - public int KeyNumber; - public string? ProviderName; - public int ProviderType; - public CspParameters() { } - public CspParameters(int dwTypeIn) { } - public CspParameters(int dwTypeIn, string? strProviderNameIn) { } - public CspParameters(int dwTypeIn, string? strProviderNameIn, string? strContainerNameIn) { } - public System.Security.Cryptography.CspProviderFlags Flags { get { throw null; } set { } } - [System.CLSCompliantAttribute(false)] - public System.Security.SecureString? KeyPassword { get { throw null; } set { } } - public System.IntPtr ParentWindowHandle { get { throw null; } set { } } - } - [System.FlagsAttribute] - public enum CspProviderFlags - { - NoFlags = 0, - UseMachineKeyStore = 1, - UseDefaultKeyContainer = 2, - UseNonExportableKey = 4, - UseExistingKey = 8, - UseArchivableKey = 16, - UseUserProtectedKey = 32, - NoPrompt = 64, - CreateEphemeralKey = 128, - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class DESCryptoServiceProvider : System.Security.Cryptography.DES - { - public DESCryptoServiceProvider() { } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override void GenerateIV() { } - public override void GenerateKey() { } - } - public sealed partial class DSACryptoServiceProvider : System.Security.Cryptography.DSA, System.Security.Cryptography.ICspAsymmetricAlgorithm - { - public DSACryptoServiceProvider() { } - public DSACryptoServiceProvider(int dwKeySize) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public DSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters? parameters) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public DSACryptoServiceProvider(System.Security.Cryptography.CspParameters? parameters) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get { throw null; } } - public override string? KeyExchangeAlgorithm { get { throw null; } } - public override int KeySize { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public bool PersistKeyInCsp { get { throw null; } set { } } - public bool PublicOnly { get { throw null; } } - public override string SignatureAlgorithm { get { throw null; } } - public static bool UseMachineKeyStore { get { throw null; } set { } } - public override byte[] CreateSignature(byte[] rgbHash) { throw null; } - protected override void Dispose(bool disposing) { } - public byte[] ExportCspBlob(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public void ImportCspBlob(byte[] keyBlob) { } - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } - public byte[] SignData(byte[] buffer) { throw null; } - public byte[] SignData(byte[] buffer, int offset, int count) { throw null; } - public byte[] SignData(System.IO.Stream inputStream) { throw null; } - public byte[] SignHash(byte[] rgbHash, string? str) { throw null; } - public bool VerifyData(byte[] rgbData, byte[] rgbSignature) { throw null; } - public bool VerifyHash(byte[] rgbHash, string? str, byte[] rgbSignature) { throw null; } - public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } - } - public partial interface ICspAsymmetricAlgorithm - { - System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get; } - byte[] ExportCspBlob(bool includePrivateParameters); - void ImportCspBlob(byte[] rawData); - } - public enum KeyNumber - { - Exchange = 1, - Signature = 2, - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class MD5CryptoServiceProvider : System.Security.Cryptography.MD5 - { - public MD5CryptoServiceProvider() { } - protected override void Dispose(bool disposing) { } - protected override void HashCore(byte[] array, int ibStart, int cbSize) { } - protected override void HashCore(System.ReadOnlySpan source) { } - protected override byte[] HashFinal() { throw null; } - public override void Initialize() { } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } - } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public partial class PasswordDeriveBytes : System.Security.Cryptography.DeriveBytes - { - public PasswordDeriveBytes(byte[] password, byte[]? salt) { } - public PasswordDeriveBytes(byte[] password, byte[]? salt, System.Security.Cryptography.CspParameters? cspParams) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] - public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] - public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } - public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt) { } - public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, System.Security.Cryptography.CspParameters? cspParams) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] - public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] - public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } - public string HashName { get { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] set { } } - public int IterationCount { get { throw null; } set { } } - public byte[]? Salt { get { throw null; } set { } } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public byte[] CryptDeriveKey(string? algname, string? alghashname, int keySize, byte[] rgbIV) { throw null; } - protected override void Dispose(bool disposing) { } - [System.ObsoleteAttribute("Rfc2898DeriveBytes replaces PasswordDeriveBytes for deriving key material from a password and is preferred in new applications.")] - public override byte[] GetBytes(int cb) { throw null; } - public override void Reset() { } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class RC2CryptoServiceProvider : System.Security.Cryptography.RC2 - { - public RC2CryptoServiceProvider() { } - public override int EffectiveKeySize { get { throw null; } set { } } - public bool UseSalt { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override void GenerateIV() { } - public override void GenerateKey() { } - } - [System.ObsoleteAttribute("RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.", DiagnosticId = "SYSLIB0023", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class RNGCryptoServiceProvider : System.Security.Cryptography.RandomNumberGenerator - { - public RNGCryptoServiceProvider() { } - public RNGCryptoServiceProvider(byte[] rgb) { } - public RNGCryptoServiceProvider(System.Security.Cryptography.CspParameters? cspParams) { } - public RNGCryptoServiceProvider(string str) { } - protected override void Dispose(bool disposing) { } - public override void GetBytes(byte[] data) { } - public override void GetBytes(byte[] data, int offset, int count) { } - public override void GetBytes(System.Span data) { } - public override void GetNonZeroBytes(byte[] data) { } - public override void GetNonZeroBytes(System.Span data) { } - } - public sealed partial class RSACryptoServiceProvider : System.Security.Cryptography.RSA, System.Security.Cryptography.ICspAsymmetricAlgorithm - { - public RSACryptoServiceProvider() { } - public RSACryptoServiceProvider(int dwKeySize) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public RSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters? parameters) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public RSACryptoServiceProvider(System.Security.Cryptography.CspParameters? parameters) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get { throw null; } } - public override string? KeyExchangeAlgorithm { get { throw null; } } - public override int KeySize { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public bool PersistKeyInCsp { get { throw null; } set { } } - public bool PublicOnly { get { throw null; } } - public override string SignatureAlgorithm { get { throw null; } } - public static bool UseMachineKeyStore { get { throw null; } set { } } - public byte[] Decrypt(byte[] rgb, bool fOAEP) { throw null; } - public override byte[] Decrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - public override byte[] DecryptValue(byte[] rgb) { throw null; } - protected override void Dispose(bool disposing) { } - public byte[] Encrypt(byte[] rgb, bool fOAEP) { throw null; } - public override byte[] Encrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - public override byte[] EncryptValue(byte[] rgb) { throw null; } - public byte[] ExportCspBlob(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public void ImportCspBlob(byte[] keyBlob) { } - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } - public byte[] SignData(byte[] buffer, int offset, int count, object halg) { throw null; } - public byte[] SignData(byte[] buffer, object halg) { throw null; } - public byte[] SignData(System.IO.Stream inputStream, object halg) { throw null; } - public override byte[] SignHash(byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - public byte[] SignHash(byte[] rgbHash, string? str) { throw null; } - public bool VerifyData(byte[] buffer, object halg, byte[] signature) { throw null; } - public override bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) { throw null; } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class SHA1CryptoServiceProvider : System.Security.Cryptography.SHA1 - { - public SHA1CryptoServiceProvider() { } - protected override void Dispose(bool disposing) { } - protected override void HashCore(byte[] array, int ibStart, int cbSize) { } - protected override void HashCore(System.ReadOnlySpan source) { } - protected override byte[] HashFinal() { throw null; } - public override void Initialize() { } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class SHA256CryptoServiceProvider : System.Security.Cryptography.SHA256 - { - public SHA256CryptoServiceProvider() { } - protected override void Dispose(bool disposing) { } - protected override void HashCore(byte[] array, int ibStart, int cbSize) { } - protected override void HashCore(System.ReadOnlySpan source) { } - protected override byte[] HashFinal() { throw null; } - public override void Initialize() { } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class SHA384CryptoServiceProvider : System.Security.Cryptography.SHA384 - { - public SHA384CryptoServiceProvider() { } - protected override void Dispose(bool disposing) { } - protected override void HashCore(byte[] array, int ibStart, int cbSize) { } - protected override void HashCore(System.ReadOnlySpan source) { } - protected override byte[] HashFinal() { throw null; } - public override void Initialize() { } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class SHA512CryptoServiceProvider : System.Security.Cryptography.SHA512 - { - public SHA512CryptoServiceProvider() { } - protected override void Dispose(bool disposing) { } - protected override void HashCore(byte[] array, int ibStart, int cbSize) { } - protected override void HashCore(System.ReadOnlySpan source) { } - protected override byte[] HashFinal() { throw null; } - public override void Initialize() { } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } - } - [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public sealed partial class TripleDESCryptoServiceProvider : System.Security.Cryptography.TripleDES - { - public TripleDESCryptoServiceProvider() { } - public override int BlockSize { get { throw null; } set { } } - public override int FeedbackSize { get { throw null; } set { } } - public override byte[] IV { get { throw null; } set { } } - public override byte[] Key { get { throw null; } set { } } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get { throw null; } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override System.Security.Cryptography.CipherMode Mode { get { throw null; } set { } } - public override System.Security.Cryptography.PaddingMode Padding { get { throw null; } set { } } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } - protected override void Dispose(bool disposing) { } - public override void GenerateIV() { } - public override void GenerateKey() { } - } -} diff --git a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj index 91c4d14e1db97..19181bd717eef 100644 --- a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj +++ b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj @@ -5,7 +5,7 @@ enable - + diff --git a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Helpers.cs deleted file mode 100644 index 9b70db3eff419..0000000000000 --- a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Helpers.cs +++ /dev/null @@ -1,45 +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.Security.Cryptography; - -namespace Internal.Cryptography -{ - internal static partial class Helpers - { - public static bool UsesIv(this CipherMode cipherMode) - { - return cipherMode != CipherMode.ECB; - } - - public static byte[]? GetCipherIv(this CipherMode cipherMode, byte[]? iv) - { - if (cipherMode.UsesIv()) - { - if (iv == null) - { - throw new CryptographicException(SR.Cryptography_MissingIV); - } - - return iv; - } - - return null; - } - - public static byte[]? TrimLargeIV(byte[]? currentIV, int blockSizeInBits) - { - int blockSizeBytes = checked((blockSizeInBits + 7) / 8); - - if (currentIV?.Length > blockSizeBytes) - { - byte[] tmp = new byte[blockSizeBytes]; - Buffer.BlockCopy(currentIV, 0, tmp, 0, tmp.Length); - return tmp; - } - - return currentIV; - } - } -} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Csp/src/Resources/Strings.resx deleted file mode 100644 index 0c2d22c90f61a..0000000000000 --- a/src/libraries/System.Security.Cryptography.Csp/src/Resources/Strings.resx +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - Illegal enum value: {0}. - - - Value was invalid. - - - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. - - - Non-negative number required. - - - Positive number required. - - - '{0}' requires Windows Cryptographic API (CAPI), which is not available on this platform. - - - Object contains only the public half of a key pair. A private key must also be provided. - - - The requested key container was not found. - - - The specified cryptographic service provider (CSP) does not support this key algorithm: {0}. - - - The hash algorithm name cannot be null or empty. - - - Length of the DSA signature was not 40 bytes. - - - {0} algorithm hash size is {1} bytes. - - - Specified initialization vector (IV) does not match the block size for this algorithm. - - - Specified key is a known weak key for '{0}' and cannot be used. - - - Specified key is a known semi-weak key for '{0}' and cannot be used. - - - Specified key is not a valid size for this algorithm. - - - Object identifier (OID) is unknown. - - - Padding is invalid and cannot be removed. - - - Specified padding mode is not valid for this algorithm. - - - The cipher mode specified requires that an initialization vector (IV) be used. - - - TransformBlock may only process bytes in block sized increments. - - - Cannot open an invalid handle. - - - The input data is not a complete block. - - - Algorithm is unavailable or is not supported for this operation. - - - The Initialization vector should have the same length as the algorithm block size in bytes. - - - Requested number of bytes exceeds the maximum. - - - Value of '{0}' cannot be changed after the bytes have been retrieved. - - - EffectiveKeySize must be the same as KeySize in this implementation. - - - The length of the data to decrypt is not valid for the size of this key. - - - Attempt to transform beyond end of buffer. - - - '{0}' is not a known hash algorithm. - - - Unknown padding mode used. - - - CryptSetKeyParam failed with error code {0}. - - - CSPParameters cannot be null - - - System.Security.Cryptography.Csp is not supported on this platform. - - - Destination is too short. - - diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj b/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj index 92886ecfd15fe..722700b99b151 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj +++ b/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj @@ -1,139 +1,12 @@ - true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent) - enable + true + $(NetCoreAppCurrent) - - $(NoWarn);CS0809 - SR.SystemSecurityCryptographyCsp_PlatformNotSupported - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Unix.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Unix.cs deleted file mode 100644 index 960e89383a88a..0000000000000 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Unix.cs +++ /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. - -using System.Security.Cryptography; - -namespace Internal.NativeCrypto -{ - internal static partial class CapiHelper - { - public static CryptographicException GetBadDataException() - { - const int NTE_BAD_DATA = unchecked((int)CryptKeyError.NTE_BAD_DATA); - return new CryptographicException(NTE_BAD_DATA); - } - - public static CryptographicException GetEFailException() - { - return new CryptographicException(E_FAIL); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.Forwards.cs b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.Forwards.cs new file mode 100644 index 0000000000000..436f6161c5638 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.Forwards.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.DSAOpenSsl))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDiffieHellmanOpenSsl))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.ECDsaOpenSsl))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.RSAOpenSsl))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.SafeEvpPKeyHandle))] diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.cs b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.cs deleted file mode 100644 index 49a2aa2e1bbf2..0000000000000 --- a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the https://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -namespace System.Security.Cryptography -{ - public sealed class DSAOpenSsl : System.Security.Cryptography.DSA - { - public DSAOpenSsl() { } - public DSAOpenSsl(int keySize) { } - public DSAOpenSsl(System.IntPtr handle) { } - public DSAOpenSsl(System.Security.Cryptography.DSAParameters parameters) { } - public DSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } - public override int KeySize { set { } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override byte[] CreateSignature(byte[] rgbHash) { throw null; } - protected override void Dispose(bool disposing) { } - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } - public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } - } - public sealed class ECDiffieHellmanOpenSsl : System.Security.Cryptography.ECDiffieHellman - { - public ECDiffieHellmanOpenSsl() { } - public ECDiffieHellmanOpenSsl(int keySize) { } - public ECDiffieHellmanOpenSsl(System.IntPtr handle) { } - public ECDiffieHellmanOpenSsl(System.Security.Cryptography.ECCurve curve) { } - public ECDiffieHellmanOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } - public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get { throw null; } } - public override byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } - public override byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? hmacKey, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } - public override byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) { throw null; } - public override byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) { throw null; } - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } - } - public sealed class ECDsaOpenSsl : System.Security.Cryptography.ECDsa - { - public ECDsaOpenSsl() { } - public ECDsaOpenSsl(int keySize) { } - public ECDsaOpenSsl(System.IntPtr handle) { } - public ECDsaOpenSsl(System.Security.Cryptography.ECCurve curve) { } - public ECDsaOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } - public override int KeySize { get { throw null; } set { } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - protected override void Dispose(bool disposing) { } - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } - public override byte[] SignHash(byte[] hash) { throw null; } - public override bool VerifyHash(byte[] hash, byte[] signature) { throw null; } - } - public sealed class RSAOpenSsl : System.Security.Cryptography.RSA - { - public RSAOpenSsl() { } - public RSAOpenSsl(int keySize) { } - public RSAOpenSsl(System.IntPtr handle) { } - public RSAOpenSsl(System.Security.Cryptography.RSAParameters parameters) { } - public RSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } - public override int KeySize { set { } } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } - public override byte[] Decrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - protected override void Dispose(bool disposing) { } - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } - public override byte[] Encrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } - protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } - public override byte[] SignHash(byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - public override bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } - } - public sealed class SafeEvpPKeyHandle : System.Runtime.InteropServices.SafeHandle - { - public SafeEvpPKeyHandle() : base (default(System.IntPtr), default(bool)) { } - public SafeEvpPKeyHandle(System.IntPtr handle, bool ownsHandle) : base (default(System.IntPtr), default(bool)) { } - public static long OpenSslVersion { get { throw null; } } - public override bool IsInvalid { get { throw null; } } - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateHandle() { throw null; } - protected override bool ReleaseHandle() { throw null; } - } -} diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj index 2dd57d852f4c9..225e8cf688082 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj @@ -4,11 +4,10 @@ enable - + - diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.OpenSsl/src/Resources/Strings.resx deleted file mode 100644 index d27bec392771f..0000000000000 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/Resources/Strings.resx +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - Error occurred during a cryptographic operation. - - - The destination is too small to hold the encoded value. - - - The OID value was invalid. - - - Value was invalid. - - - The keys from both parties must be the same size to generate a secret agreement. - - - Object contains only the public half of a key pair. A private key must also be provided. - - - The message exceeds the maximum allowable length for the chosen options ({0}). - - - The hash algorithm name cannot be null or empty. - - - The specified curve '{0}' or its parameters are not valid for this platform. - - - ASN1 corrupted data. - - - The specified DSA parameters are not valid; P, Q, G and Y are all required. - - - The specified DSA parameters are not valid; P, G and Y must be the same length (the key size). - - - The specified DSA parameters are not valid; Q and X (if present) must be the same length. - - - The specified DSA parameters are not valid; J (if present) must be shorter than P. - - - The specified DSA parameters are not valid; Seed, if present, must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q's length must be one of 20, 32 or 64 bytes. - - - Specified key is not a valid size for this algorithm. - - - Specified padding mode is not valid for this algorithm. - - - The specified RSA parameters are not valid. Exponent and Modulus are required. If D is present, it must have the same length as Modulus. If D is present, P, Q, DP, DQ, and InverseQ are required and must have half the length of Modulus, rounded up, otherwise they must be omitted. - - - Key is not a valid private key. - - - Cannot open an invalid handle. - - - The provided RSAPrivateKey value has version '{0}', but version '{1}' is the maximum supported. - - - The TLS key derivation function requires a seed value of exactly 64 bytes. - - - '{0}' is not a known hash algorithm. - - - The string contains a character not in the 7 bit ASCII character set. - - - The key is too small for the requested operation. - - - Error occurred while decoding OAEP padding. - - - The length of the data to decrypt is not valid for the size of this key. - - - The provided hash value is not the expected size for the specified hash algorithm. - - - The input to WriteEncodedValue must represent a single encoded value with no trailing data. - - - ASN.1 Enumerated values only apply to enum types without the [Flags] attribute. - - - Named bit list operations require an enum with the [Flags] attribute. - - - The encoded named bit list value is larger than the value size of the '{0}' enum. - - - Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written. - - - Unused bit count must be between 0 and 7, inclusive. - - - Encode cannot be called while a Sequence or SetOf is still open. - - - Cannot pop the requested tag as it is not currently in progress. - - - Key is not a valid public or private key. - - - Algorithm '{0}' is not supported on this platform. - - - OpenSSL is not supported on this platform. - - diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj index 2f01f9432c0d1..1fe031a388f59 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj @@ -1,173 +1,10 @@ - $(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent) - true - enable + $(NetCoreAppCurrent) + true - - SR.PlatformNotSupported_CryptographyOpenSSL - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.manual.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml.cs - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml.cs - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx index 0b0701deadb05..c85300da29d68 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx @@ -88,27 +88,6 @@ The KDF for algorithm '{0}' requires a char-based password input. - - ASN.1 Enumerated values only apply to enum types without the [Flags] attribute. - - - Named bit list operations require an enum with the [Flags] attribute. - - - The encoded named bit list value is larger than the value size of the '{0}' enum. - - - Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written. - - - Unused bit count must be between 0 and 7, inclusive. - - - Encode cannot be called while a Sequence or SetOf is still open. - - - Cannot pop the requested tag as it is not currently in progress. - The hash value is not correct. @@ -289,9 +268,6 @@ '{0}' is not a known hash algorithm. - - The input to WriteEncodedValue must represent a single encoded value with no trailing data. - Attribute not found. diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index 9ccb53cebf207..c0c2da22f9851 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -490,6 +490,10 @@ System.Security.Cryptography.Pkcs.EnvelopedCms System\Security\Cryptography\Pkcs\Asn1\MessageImprint.xml + + + System\Security\Cryptography\Pkcs\Asn1\OtherCertificateFormat.xml + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml index d9b497ab9d000..9bc76b343264d 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml @@ -15,12 +15,10 @@ other[3] IMPLICIT OtherCertificateFormat } - OtherCertificateFormat ::= SEQUENCE { - otherCertFormat OBJECT IDENTIFIER, - otherCert ANY DEFINED BY otherCertFormat - } - - Except we only support public key certificates, so just trim the choice here. --> + + + + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml.cs index c9107fa3d9c28..0b602a0aa55d5 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/CertificateChoiceAsn.xml.cs @@ -12,6 +12,10 @@ namespace System.Security.Cryptography.Pkcs.Asn1 internal partial struct CertificateChoiceAsn { internal ReadOnlyMemory? Certificate; + internal ReadOnlyMemory? ExtendedCertificate; + internal ReadOnlyMemory? AttributeCertificateV1; + internal ReadOnlyMemory? AttributeCertificateV2; + internal System.Security.Cryptography.Pkcs.Asn1.OtherCertificateFormat? OtherCertificateFormat; #if DEBUG static CertificateChoiceAsn() @@ -28,6 +32,10 @@ static CertificateChoiceAsn() }; ensureUniqueTag(new Asn1Tag((UniversalTagNumber)16), "Certificate"); + ensureUniqueTag(new Asn1Tag(TagClass.ContextSpecific, 0), "ExtendedCertificate"); + ensureUniqueTag(new Asn1Tag(TagClass.ContextSpecific, 1), "AttributeCertificateV1"); + ensureUniqueTag(new Asn1Tag(TagClass.ContextSpecific, 2), "AttributeCertificateV2"); + ensureUniqueTag(new Asn1Tag(TagClass.ContextSpecific, 3), "OtherCertificateFormat"); } #endif @@ -60,6 +68,90 @@ internal void Encode(AsnWriter writer) wroteValue = true; } + if (ExtendedCertificate.HasValue) + { + if (wroteValue) + throw new CryptographicException(); + + // Validator for tag constraint for ExtendedCertificate + { + if (!Asn1Tag.TryDecode(ExtendedCertificate.Value.Span, out Asn1Tag validateTag, out _) || + !validateTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) + { + throw new CryptographicException(); + } + } + + try + { + writer.WriteEncodedValue(ExtendedCertificate.Value.Span); + } + catch (ArgumentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + wroteValue = true; + } + + if (AttributeCertificateV1.HasValue) + { + if (wroteValue) + throw new CryptographicException(); + + // Validator for tag constraint for AttributeCertificateV1 + { + if (!Asn1Tag.TryDecode(AttributeCertificateV1.Value.Span, out Asn1Tag validateTag, out _) || + !validateTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) + { + throw new CryptographicException(); + } + } + + try + { + writer.WriteEncodedValue(AttributeCertificateV1.Value.Span); + } + catch (ArgumentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + wroteValue = true; + } + + if (AttributeCertificateV2.HasValue) + { + if (wroteValue) + throw new CryptographicException(); + + // Validator for tag constraint for AttributeCertificateV2 + { + if (!Asn1Tag.TryDecode(AttributeCertificateV2.Value.Span, out Asn1Tag validateTag, out _) || + !validateTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) + { + throw new CryptographicException(); + } + } + + try + { + writer.WriteEncodedValue(AttributeCertificateV2.Value.Span); + } + catch (ArgumentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + wroteValue = true; + } + + if (OtherCertificateFormat.HasValue) + { + if (wroteValue) + throw new CryptographicException(); + + OtherCertificateFormat.Value.Encode(writer, new Asn1Tag(TagClass.ContextSpecific, 3)); + wroteValue = true; + } + if (!wroteValue) { throw new CryptographicException(); @@ -107,6 +199,28 @@ private static void DecodeCore(ref AsnValueReader reader, ReadOnlyMemory r tmpSpan = reader.ReadEncodedValue(); decoded.Certificate = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); } + else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) + { + tmpSpan = reader.ReadEncodedValue(); + decoded.ExtendedCertificate = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); + } + else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) + { + tmpSpan = reader.ReadEncodedValue(); + decoded.AttributeCertificateV1 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); + } + else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) + { + tmpSpan = reader.ReadEncodedValue(); + decoded.AttributeCertificateV2 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); + } + else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3))) + { + System.Security.Cryptography.Pkcs.Asn1.OtherCertificateFormat tmpOtherCertificateFormat; + System.Security.Cryptography.Pkcs.Asn1.OtherCertificateFormat.Decode(ref reader, new Asn1Tag(TagClass.ContextSpecific, 3), rebind, out tmpOtherCertificateFormat); + decoded.OtherCertificateFormat = tmpOtherCertificateFormat; + + } else { throw new CryptographicException(); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml new file mode 100644 index 0000000000000..704a42f6d64b8 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml.cs new file mode 100644 index 0000000000000..aeb18133756af --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Asn1/OtherCertificateFormat.xml.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma warning disable SA1028 // ignore whitespace warnings for generated code +using System; +using System.Formats.Asn1; +using System.Runtime.InteropServices; + +namespace System.Security.Cryptography.Pkcs.Asn1 +{ + [StructLayout(LayoutKind.Sequential)] + internal partial struct OtherCertificateFormat + { + internal string OtherCertFormat; + internal ReadOnlyMemory OtherCert; + + internal void Encode(AsnWriter writer) + { + Encode(writer, Asn1Tag.Sequence); + } + + internal void Encode(AsnWriter writer, Asn1Tag tag) + { + writer.PushSequence(tag); + + try + { + writer.WriteObjectIdentifier(OtherCertFormat); + } + catch (ArgumentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + try + { + writer.WriteEncodedValue(OtherCert.Span); + } + catch (ArgumentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + writer.PopSequence(tag); + } + + internal static OtherCertificateFormat Decode(ReadOnlyMemory encoded, AsnEncodingRules ruleSet) + { + return Decode(Asn1Tag.Sequence, encoded, ruleSet); + } + + internal static OtherCertificateFormat Decode(Asn1Tag expectedTag, ReadOnlyMemory encoded, AsnEncodingRules ruleSet) + { + try + { + AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet); + + DecodeCore(ref reader, expectedTag, encoded, out OtherCertificateFormat decoded); + reader.ThrowIfNotEmpty(); + return decoded; + } + catch (AsnContentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + } + + internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory rebind, out OtherCertificateFormat decoded) + { + Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); + } + + internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out OtherCertificateFormat decoded) + { + try + { + DecodeCore(ref reader, expectedTag, rebind, out decoded); + } + catch (AsnContentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + } + + private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out OtherCertificateFormat decoded) + { + decoded = default; + AsnValueReader sequenceReader = reader.ReadSequence(expectedTag); + ReadOnlySpan rebindSpan = rebind.Span; + int offset; + ReadOnlySpan tmpSpan; + + decoded.OtherCertFormat = sequenceReader.ReadObjectIdentifier(); + tmpSpan = sequenceReader.ReadEncodedValue(); + decoded.OtherCert = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); + + sequenceReader.ThrowIfNotEmpty(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs index 188ca0039a3c9..bc38187f6edc2 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs @@ -89,8 +89,16 @@ public X509Certificate2Collection Certificates foreach (CertificateChoiceAsn choice in certChoices) { - Debug.Assert(choice.Certificate.HasValue); - coll.Add(new X509Certificate2(choice.Certificate.Value.ToArray())); + if (choice.Certificate.HasValue) + { + coll.Add(new X509Certificate2(choice.Certificate.Value +#if NET5_0_OR_GREATER + .Span +#else + .ToArray() +#endif + )); + } } return coll; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs index c53e966a72d9e..c89cfa54bb8c2 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs @@ -1602,6 +1602,15 @@ public static void CheckNoSignature_FromCoreFx_TamperIssuerName() signers[0].CheckHash(); } + [Fact] + public static void Decode_CanDecodeWithAttributeCertificate() + { + SignedCms cms = new SignedCms(); + cms.Decode(SignedDocuments.TstWithAttributeCertificate); + Assert.Equal(2, cms.Certificates.Count); + cms.CheckSignature(verifySignatureOnly: true); + } + private static void CheckNoSignature(byte[] encoded, bool badOid=false) { SignedCms cms = new SignedCms(); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs index 55d42f6b02ee8..cce3114824794 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs @@ -1472,5 +1472,159 @@ internal static class SignedDocuments "2B78166BDB1612848B535ADC3F0E7BE52991A17F48AFDCCC1698A236BA338930" + "50EBAAC4460DAA35185C16670F597E0E6E0CB0AA83F51AAEF452F3367DD9350A" + "8A49A5A8F79DF8E921303AB5D6646A482F0F59D9980310E1AE3EE8D77CB857").HexToByteArray(); + + internal static readonly byte[] TstWithAttributeCertificate = ( + "308212E306092A864886F70D010702A08212D4308212D0020103310F300D0609" + + "608648016503040201050030820159060B2A864886F70D0109100104A0820148" + + "0482014430820140020101060A2B0601040184590A03013031300D0609608648" + + "01650304020105000420C61245B435391DCDD1EFF021681FA2A46E69410A9E23" + + "09F1B1736BB7C2BB504402066148B8B838B11813323032313130303730343230" + + "30372E3037345A3004800201F4A081D8A481D53081D2310B3009060355040613" + + "025553311330110603550408130A57617368696E67746F6E3110300E06035504" + + "0713075265646D6F6E64311E301C060355040A13154D6963726F736F66742043" + + "6F72706F726174696F6E312D302B060355040B13244D6963726F736F66742049" + + "72656C616E64204F7065726174696F6E73204C696D6974656431263024060355" + + "040B131D5468616C6573205453532045534E3A303834322D344245362D433239" + + "41312530230603550403131C4D6963726F736F66742054696D652D5374616D70" + + "2053657276696365A0820E4A308204F9308203E1A00302010202133300000139" + + "CCE8E8438BF034E1000000000139300D06092A864886F70D01010B0500307C31" + + "0B3009060355040613025553311330110603550408130A57617368696E67746F" + + "6E3110300E060355040713075265646D6F6E64311E301C060355040A13154D69" + + "63726F736F667420436F72706F726174696F6E312630240603550403131D4D69" + + "63726F736F66742054696D652D5374616D70205043412032303130301E170D32" + + "30313031353137323832315A170D3232303131323137323832315A3081D2310B" + + "3009060355040613025553311330110603550408130A57617368696E67746F6E" + + "3110300E060355040713075265646D6F6E64311E301C060355040A13154D6963" + + "726F736F667420436F72706F726174696F6E312D302B060355040B13244D6963" + + "726F736F6674204972656C616E64204F7065726174696F6E73204C696D697465" + + "6431263024060355040B131D5468616C6573205453532045534E3A303834322D" + + "344245362D43323941312530230603550403131C4D6963726F736F6674205469" + + "6D652D5374616D70205365727669636530820122300D06092A864886F70D0101" + + "0105000382010F003082010A0282010100DA13F98CE3259325A18EB32A06FCA2" + + "78F85A1F98374F7F50C1DBBA1EA02759C2E5CFDFD92A80BF405CF8E606F469DD" + + "7822FA856859B627AA3EBE185B7F8A1024E1C34DC8D95C12904DB413FF0E8B09" + + "6BDD0979C5425D9AF2711DE3612613BAF145598ABA66C7A04295F90C1874673B" + + "D2AE4EF0CD9892A27F4AD72B16116D9A117172F559FA08386B3CEF13CEFEB282" + + "33615EB3A8CD8A58EFD34B2F597A88B95F84286D5E802AEC091F4F32499DA540" + + "15F39DDF2BC03CF2EBE058A895E29BE6FE57EEC4DFBE356FA710F5F98E340A47" + + "2E1906AA8D3BFC1D783641AAA8EF7BF210235ED5684292A32AEEB2C57CECB294" + + "278F4AE57EC57F1F2496FE5FA2CF1ECA4F0203010001A382011B30820117301D" + + "0603551D0E04160414999E9B867254C299DA928AB19F46F6502D060CE9301F06" + + "03551D23041830168014D5633A5C8A3190F3437B7C461BC533685A856D553056" + + "0603551D1F044F304D304BA049A0478645687474703A2F2F63726C2E6D696372" + + "6F736F66742E636F6D2F706B692F63726C2F70726F64756374732F4D69635469" + + "6D5374615043415F323031302D30372D30312E63726C305A06082B0601050507" + + "0101044E304C304A06082B06010505073002863E687474703A2F2F7777772E6D" + + "6963726F736F66742E636F6D2F706B692F63657274732F4D696354696D537461" + + "5043415F323031302D30372D30312E637274300C0603551D130101FF04023000" + + "30130603551D25040C300A06082B06010505070308300D06092A864886F70D01" + + "010B05000382010100585C286AF3FF371A85CDC15AED438288BF100DB126FBBA" + + "F6118893A16D20F1D758C8AE566B514077FCA7243D6AC9CFD9C71F473FDD32A9" + + "7293FABCF8835C08B1049694A09BDD71B821586C584084B26DA28CDFDFC687E6" + + "B63667158DF5BB831249C97E21A22BA43EF2490235699B5A3D83C51C0417C21F" + + "0708C5EC43E160381D8A52B3E3CEAEC21828B28AF51AE0D68A56231A830DAB79" + + "6BC0322463FF37294A49868AE5A6205D908344B159027F3C842E67BD0B7B5A99" + + "9B4C497C6B519C17E96ADFDDD498100AB2DFA3C9649AE2C13C21BF38C87AA0FC" + + "78ACD4521DEE7C4DBF1231006DA6C1842A36FAD528CA74FA4C026D8DD8AF6B88" + + "3B3FBDFF550AD270C73082067130820459A003020102020A6109812A00000000" + + "0002300D06092A864886F70D01010B0500308188310B30090603550406130255" + + "53311330110603550408130A57617368696E67746F6E3110300E060355040713" + + "075265646D6F6E64311E301C060355040A13154D6963726F736F667420436F72" + + "706F726174696F6E31323030060355040313294D6963726F736F667420526F6F" + + "7420436572746966696361746520417574686F726974792032303130301E170D" + + "3130303730313231333635355A170D3235303730313231343635355A307C310B" + + "3009060355040613025553311330110603550408130A57617368696E67746F6E" + + "3110300E060355040713075265646D6F6E64311E301C060355040A13154D6963" + + "726F736F667420436F72706F726174696F6E312630240603550403131D4D6963" + + "726F736F66742054696D652D5374616D7020504341203230313030820122300D" + + "06092A864886F70D01010105000382010F003082010A0282010100A91D0DBC77" + + "118A3A20ECFC1397F5FA7F69946B745410D5A50A008285FBED7C684B2C5FC5C3" + + "E561C276B73E662B5BF015532704311F411B1A951DCE09138E7C613059B13044" + + "0FF160888454430CD74DB83808B342DD93ACD67330572682A3450DD0EAF54781" + + "CDBF246032586046F258478632841E746167915F8154B1CF934C92C1C4A65DD1" + + "61136E28C61AF98680BBDF61FC46C1271D246712721A218AAF4B64895062B15D" + + "FD771F3DF05775ACBD8A424D4051D10F9C063E677FF566C00396447EEFD04BFD" + + "6EE59ACAB1A8F27A2A0A31F0DA4E0691B6880835E8781CB0E999CD3CE72F44BA" + + "A7F4DC64BDA401C120099378CDFCBCC0C9445D5E169C01054F224D0203010001" + + "A38201E6308201E2301006092B06010401823715010403020100301D0603551D" + + "0E04160414D5633A5C8A3190F3437B7C461BC533685A856D55301906092B0601" + + "040182371402040C1E0A00530075006200430041300B0603551D0F0404030201" + + "86300F0603551D130101FF040530030101FF301F0603551D23041830168014D5" + + "F656CB8FE8A25C6268D13D94905BD7CE9A18C430560603551D1F044F304D304B" + + "A049A0478645687474703A2F2F63726C2E6D6963726F736F66742E636F6D2F70" + + "6B692F63726C2F70726F64756374732F4D6963526F6F4365724175745F323031" + + "302D30362D32332E63726C305A06082B06010505070101044E304C304A06082B" + + "06010505073002863E687474703A2F2F7777772E6D6963726F736F66742E636F" + + "6D2F706B692F63657274732F4D6963526F6F4365724175745F323031302D3036" + + "2D32332E6372743081A00603551D200101FF04819530819230818F06092B0601" + + "040182372E03308181303D06082B060105050702011631687474703A2F2F7777" + + "772E6D6963726F736F66742E636F6D2F504B492F646F63732F4350532F646566" + + "61756C742E68746D304006082B0601050507020230341E32201D004C00650067" + + "0061006C005F0050006F006C006900630079005F00530074006100740065006D" + + "0065006E0074002E201D300D06092A864886F70D01010B0500038202010007E6" + + "88510DE2C6E0983F8171033D9DA3A1216FB3EBA6CCF531BECF05E2A9FEFA576D" + + "1930B3C2C566C96ADFF5E7F078BDC7A89E25E3F9BCED6B5457082B51824412FB" + + "B9538CCCF460128A76CC4040419BDC5C17FF5CF95E17359824564B74EF4210C8" + + "AFBF7FC67FF2377D5A3F1CF299794A915200AF380F17F52F798165D9A9B56BE4" + + "C7CEF6CA7A006F4B304424223CCFED03A5968F5929BCB6FD04E1709F324A27FD" + + "55AF2FFEB6E58E33BB625F9ADB5740E9F1CE9966908CFF6A627FDDC54A0B9126" + + "E239EC194A71639D7B216DC39CA3A23CFA7F7D966A9078A66DD2E19CF91DFC38" + + "D894F4C6A50A9686A4BD9E1AAE044283B8B5809B223820B525E564ECF7F4BF7E" + + "6359250F7A2E395776A271AA068A0F8916BA61A711CB9AD80E479A80C5D0CDA7" + + "D0EF7D83F0E13B7109DF5D7498220861DAB0501E6FBDF1E100DFE73107A4933A" + + "F7654778E8F8A848ABF7DE727E616B6F77A981CBA709AC39BBECC6CBD882B472" + + "CD1DF4B885011E80FB1B892A5439B25BDAC80D55997A87733B08E6982DEA8DE0" + + "332E1229F5C02F542721F7C8AC4EDA28B8B1A9DB96B2A742A2C9CF19414DE086" + + "F92A9AA3116630D3BB74324BDF637BF5998A2F1BC721AF59B5AEDC443C975071" + + "D7A1D2C555E369DE57C1D1DE30C0FDCCE64DFB0DBF5D4FE99D1E19382FBCCF58" + + "052EEF0DA05035DAEF09271CD5B37E351E08BADA36DBD35F8FDE74884912A182" + + "02D43082023D02010130820100A181D8A481D53081D2310B3009060355040613" + + "025553311330110603550408130A57617368696E67746F6E3110300E06035504" + + "0713075265646D6F6E64311E301C060355040A13154D6963726F736F66742043" + + "6F72706F726174696F6E312D302B060355040B13244D6963726F736F66742049" + + "72656C616E64204F7065726174696F6E73204C696D6974656431263024060355" + + "040B131D5468616C6573205453532045534E3A303834322D344245362D433239" + + "41312530230603550403131C4D6963726F736F66742054696D652D5374616D70" + + "2053657276696365A2230A0101300706052B0E03021A0315000D4D94FE1BDE96" + + "848D743F1DEE4A04C6B3658C07A08183308180A47E307C310B30090603550406" + + "13025553311330110603550408130A57617368696E67746F6E3110300E060355" + + "040713075265646D6F6E64311E301C060355040A13154D6963726F736F667420" + + "436F72706F726174696F6E312630240603550403131D4D6963726F736F667420" + + "54696D652D5374616D70205043412032303130300D06092A864886F70D010105" + + "0500020500E5084E973022180F32303231313030373030333433315A180F3230" + + "3231313030383030333433315A3074303A060A2B0601040184590A0401312C30" + + "2A300A020500E5084E97020100300702010002021DE630070201000202113630" + + "0A020500E509A0170201003036060A2B0601040184590A040231283026300C06" + + "0A2B0601040184590A0302A00A3008020100020307A120A10A30080201000203" + + "0186A0300D06092A864886F70D0101050500038181002AE0DF2A01AAE13A86C0" + + "2DD8ECA787327C8F04A7C13D47256E65C60676B8372EE46362CD35391B6B898E" + + "DC1884082AAA7CF9B1CF40BE2C30146D0080ACB225C50B7C1FE94694732EDEEB" + + "9EDE73DB7D8C0762CBDFABD3ACCC82DD3858AA16C3ED185A40A39E9676772099" + + "346E3362621286651B06D9AD26D574F967F6C7EC335A3182030D308203090201" + + "01308193307C310B3009060355040613025553311330110603550408130A5761" + + "7368696E67746F6E3110300E060355040713075265646D6F6E64311E301C0603" + + "55040A13154D6963726F736F667420436F72706F726174696F6E312630240603" + + "550403131D4D6963726F736F66742054696D652D5374616D7020504341203230" + + "313002133300000139CCE8E8438BF034E1000000000139300D06096086480165" + + "030402010500A082014A301A06092A864886F70D010903310D060B2A864886F7" + + "0D0109100104302F06092A864886F70D01090431220420EA37C01965AB5A8B08" + + "C2A59F8EF2008C2B60F78E7F0385E2DD18A07C63433EF43081FA060B2A864886" + + "F70D010910022F3181EA3081E73081E43081BD04203CA18EE438A3D7247B3142" + + "B1E28105AE7C6A5527F39A7A9F26A6D4A0070FFC9F308198308180A47E307C31" + + "0B3009060355040613025553311330110603550408130A57617368696E67746F" + + "6E3110300E060355040713075265646D6F6E64311E301C060355040A13154D69" + + "63726F736F667420436F72706F726174696F6E312630240603550403131D4D69" + + "63726F736F66742054696D652D5374616D702050434120323031300213330000" + + "0139CCE8E8438BF034E1000000000139302204204A6E54AC16FAF6985726E0CB" + + "5480381C41888386AB1D1BECC241E6BCFCBDD45B300D06092A864886F70D0101" + + "0B0500048201006957F018A5C13CC539EB266EC2725998F4AC0ED50CE1CAA696" + + "CAE377977F45FB8030136A4038B49F7E5A6ADCF72FA3901C26B52815621F52A2" + + "EB2ACFC423087ECD954F34C341342E31BDF30443CAC4F1297AB0181467B90604" + + "DDCF11F9F8930290614E8AA9D868E56971E4F83427819F8A1A11ED87AD1D5469" + + "7AFFE60A8D7B7877CBB1D09F46397769B9D0F8EB605DBFE8F05C47A3F8BC1F65" + + "F9F63553F187194B35E971FEFFB00C9127BDFD0F7FCF2424BE2A108AC5C532EA" + + "6AB46C76047604BA7DF071EE0137B73F4D9DF616095C8F1CA9EB925B6D4C6ABC" + + "FFEB73A81903169C6B487B316AFC951F696831A4B29B9ABCEA7EBCD243A553D2" + + "F8B44FDA1B0AC0").HexToByteArray(); } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs index cda2262f78205..32adea8510ef4 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs @@ -547,7 +547,7 @@ private static void VerifyAttributesAreEqual(AsnEncodedData actual, AsnEncodedDa Assert.Equal(expectedToken.GetSerialNumber().ByteArrayToHex(), actualToken.GetSerialNumber().ByteArrayToHex()); Assert.Equal(expectedToken.Timestamp, actualToken.Timestamp); - Assert.Equal(expectedToken.HashAlgorithmId.Value, Oids.Sha256); + Assert.Equal(Oids.Sha256, expectedToken.HashAlgorithmId.Value); Assert.Equal(expectedToken.HashAlgorithmId.Value, actualToken.HashAlgorithmId.Value); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.Forwards.cs b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.Forwards.cs new file mode 100644 index 0000000000000..6827f78966d52 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.Forwards.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Win32.SafeHandles.SafeX509ChainHandle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.CertificateRequest))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.DSACertificateExtensions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.OpenFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.PublicKey))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.RSACertificateExtensions))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.StoreLocation))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.StoreName))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X500DistinguishedName))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Certificate))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Certificate2))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Certificate2Collection))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509CertificateCollection))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Chain))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainElement))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainElementCollection))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainPolicy))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainStatus))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainStatusFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ChainTrustMode))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ContentType))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Extension))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ExtensionCollection))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509FindType))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509IncludeOption))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509KeyUsageExtension))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509NameType))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509RevocationFlag))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509RevocationMode))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509SignatureGenerator))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509Store))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509VerificationFlags))] diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs deleted file mode 100644 index ba1ff3b66349f..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs +++ /dev/null @@ -1,684 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the https://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -namespace Microsoft.Win32.SafeHandles -{ - public sealed partial class SafeX509ChainHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid - { - public SafeX509ChainHandle() : base (default(bool)) { } - protected override void Dispose(bool disposing) { } - protected override bool ReleaseHandle() { throw null; } - } -} -namespace System.Security.Cryptography.X509Certificates -{ - public sealed partial class CertificateRequest - { - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } - public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } - public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } - public System.Collections.ObjectModel.Collection CertificateExtensions { get { throw null; } } - public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get { throw null; } } - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) { throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) { throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSigned(System.DateTimeOffset notBefore, System.DateTimeOffset notAfter) { throw null; } - public byte[] CreateSigningRequest() { throw null; } - public byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) { throw null; } - } - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] - public static partial class DSACertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) { throw null; } - public static System.Security.Cryptography.DSA? GetDSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public static System.Security.Cryptography.DSA? GetDSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - } - public static partial class ECDsaCertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.ECDsa privateKey) { throw null; } - public static System.Security.Cryptography.ECDsa? GetECDsaPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public static System.Security.Cryptography.ECDsa? GetECDsaPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - } - [System.FlagsAttribute] - public enum OpenFlags - { - ReadOnly = 0, - ReadWrite = 1, - MaxAllowed = 2, - OpenExistingOnly = 4, - IncludeArchived = 8, - } - public sealed partial class PublicKey - { - public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } - public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData parameters, System.Security.Cryptography.AsnEncodedData keyValue) { } - public System.Security.Cryptography.AsnEncodedData EncodedKeyValue { get { throw null; } } - public System.Security.Cryptography.AsnEncodedData EncodedParameters { get { throw null; } } - [System.ObsoleteAttribute("PublicKey.Key is obsolete. Use the appropriate method to get the public key, such as GetRSAPublicKey.", DiagnosticId = "SYSLIB0027", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public System.Security.Cryptography.AsymmetricAlgorithm Key { get { throw null; } } - public System.Security.Cryptography.Oid Oid { get { throw null; } } - public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } - public byte[] ExportSubjectPublicKeyInfo() { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] - public System.Security.Cryptography.DSA? GetDSAPublicKey() { throw null; } - public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPublicKey() { throw null; } - public System.Security.Cryptography.ECDsa? GetECDsaPublicKey() { throw null; } - public System.Security.Cryptography.RSA? GetRSAPublicKey() { throw null; } - public bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) { throw null; } - } - public static partial class RSACertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.RSA privateKey) { throw null; } - public static System.Security.Cryptography.RSA? GetRSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public static System.Security.Cryptography.RSA? GetRSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - } - public enum StoreLocation - { - CurrentUser = 1, - LocalMachine = 2, - } - public enum StoreName - { - AddressBook = 1, - AuthRoot = 2, - CertificateAuthority = 3, - Disallowed = 4, - My = 5, - Root = 6, - TrustedPeople = 7, - TrustedPublisher = 8, - } - public sealed partial class SubjectAlternativeNameBuilder - { - public SubjectAlternativeNameBuilder() { } - public void AddDnsName(string dnsName) { } - public void AddEmailAddress(string emailAddress) { } - public void AddIpAddress(System.Net.IPAddress ipAddress) { } - public void AddUri(System.Uri uri) { } - public void AddUserPrincipalName(string upn) { } - public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical = false) { throw null; } - } - public sealed partial class X500DistinguishedName : System.Security.Cryptography.AsnEncodedData - { - public X500DistinguishedName(byte[] encodedDistinguishedName) { } - public X500DistinguishedName(System.ReadOnlySpan encodedDistinguishedName) { } - public X500DistinguishedName(System.Security.Cryptography.AsnEncodedData encodedDistinguishedName) { } - public X500DistinguishedName(System.Security.Cryptography.X509Certificates.X500DistinguishedName distinguishedName) { } - public X500DistinguishedName(string distinguishedName) { } - public X500DistinguishedName(string distinguishedName, System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) { } - public string Name { get { throw null; } } - public string Decode(System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) { throw null; } - public override string Format(bool multiLine) { throw null; } - } - [System.FlagsAttribute] - public enum X500DistinguishedNameFlags - { - None = 0, - Reversed = 1, - UseSemicolons = 16, - DoNotUsePlusSign = 32, - DoNotUseQuotes = 64, - UseCommas = 128, - UseNewLines = 256, - UseUTF8Encoding = 4096, - UseT61Encoding = 8192, - ForceUTF8Encoding = 16384, - } - public sealed partial class X509BasicConstraintsExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public X509BasicConstraintsExtension() { } - public X509BasicConstraintsExtension(bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical) { } - public X509BasicConstraintsExtension(System.Security.Cryptography.AsnEncodedData encodedBasicConstraints, bool critical) { } - public bool CertificateAuthority { get { throw null; } } - public bool HasPathLengthConstraint { get { throw null; } } - public int PathLengthConstraint { get { throw null; } } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } - } - public partial class X509Certificate : System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable - { - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public X509Certificate() { } - public X509Certificate(byte[] data) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate(byte[] rawData, System.Security.SecureString? password) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate(byte[] rawData, string? password) { } - public X509Certificate(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate(System.IntPtr handle) { } - public X509Certificate(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public X509Certificate(System.Security.Cryptography.X509Certificates.X509Certificate cert) { } - public X509Certificate(string fileName) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate(string fileName, System.Security.SecureString? password) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate(string fileName, string? password) { } - public X509Certificate(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public System.IntPtr Handle { get { throw null; } } - public string Issuer { get { throw null; } } - public string Subject { get { throw null; } } - public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromCertFile(string filename) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromSignedFile(string filename) { throw null; } - public void Dispose() { } - protected virtual void Dispose(bool disposing) { } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } - public virtual bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.X509Certificates.X509Certificate? other) { throw null; } - public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) { throw null; } - [System.CLSCompliantAttribute(false)] - public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, System.Security.SecureString? password) { throw null; } - public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string? password) { throw null; } - protected static string FormatDate(System.DateTime date) { throw null; } - public virtual byte[] GetCertHash() { throw null; } - public virtual byte[] GetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public virtual string GetCertHashString() { throw null; } - public virtual string GetCertHashString(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } - public virtual string GetEffectiveDateString() { throw null; } - public virtual string GetExpirationDateString() { throw null; } - public virtual string GetFormat() { throw null; } - public override int GetHashCode() { throw null; } - [System.ObsoleteAttribute("X509Certificate.GetIssuerName has been deprecated. Use the Issuer property instead.")] - public virtual string GetIssuerName() { throw null; } - public virtual string GetKeyAlgorithm() { throw null; } - public virtual byte[] GetKeyAlgorithmParameters() { throw null; } - public virtual string GetKeyAlgorithmParametersString() { throw null; } - [System.ObsoleteAttribute("X509Certificate.GetName has been deprecated. Use the Subject property instead.")] - public virtual string GetName() { throw null; } - public virtual byte[] GetPublicKey() { throw null; } - public virtual string GetPublicKeyString() { throw null; } - public virtual byte[] GetRawCertData() { throw null; } - public virtual string GetRawCertDataString() { throw null; } - public virtual byte[] GetSerialNumber() { throw null; } - public virtual string GetSerialNumberString() { throw null; } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(byte[] rawData) { } - [System.CLSCompliantAttribute(false)] - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(string fileName) { } - [System.CLSCompliantAttribute(false)] - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public virtual void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public virtual void Reset() { } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } - void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public override string ToString() { throw null; } - public virtual string ToString(bool fVerbose) { throw null; } - public virtual bool TryGetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Span destination, out int bytesWritten) { throw null; } - } - public partial class X509Certificate2 : System.Security.Cryptography.X509Certificates.X509Certificate - { - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public X509Certificate2() { } - public X509Certificate2(byte[] rawData) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate2(byte[] rawData, System.Security.SecureString? password) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate2(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate2(byte[] rawData, string? password) { } - public X509Certificate2(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate2(System.IntPtr handle) { } - public X509Certificate2(System.ReadOnlySpan rawData) { } - public X509Certificate2(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - protected X509Certificate2(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public X509Certificate2(System.Security.Cryptography.X509Certificates.X509Certificate certificate) { } - public X509Certificate2(string fileName) { } - public X509Certificate2(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate2(string fileName, System.Security.SecureString? password) { } - [System.CLSCompliantAttribute(false)] - public X509Certificate2(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public X509Certificate2(string fileName, string? password) { } - public X509Certificate2(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public bool Archived { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public System.Security.Cryptography.X509Certificates.X509ExtensionCollection Extensions { get { throw null; } } - public string FriendlyName { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public bool HasPrivateKey { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X500DistinguishedName IssuerName { get { throw null; } } - public System.DateTime NotAfter { get { throw null; } } - public System.DateTime NotBefore { get { throw null; } } - [System.ObsoleteAttribute("X509Certificate2.PrivateKey is obsolete. Use the appropriate method to get the private key, such as GetRSAPrivateKey, or use the CopyWithPrivateKey method to create a new instance with a private key.", DiagnosticId = "SYSLIB0028", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public System.Security.Cryptography.AsymmetricAlgorithm? PrivateKey { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } - public byte[] RawData { get { throw null; } } - public System.ReadOnlyMemory RawDataMemory { get { throw null; } } - public string SerialNumber { get { throw null; } } - public System.Security.Cryptography.Oid SignatureAlgorithm { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } } - public string Thumbprint { get { throw null; } } - public int Version { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.ECDiffieHellman privateKey) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem, System.ReadOnlySpan password) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath, System.ReadOnlySpan password, string? keyPemFilePath = null) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPemFile(string certPemFilePath, string? keyPemFilePath = null) { throw null; } - public string ExportCertificatePem() { throw null; } - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(byte[] rawData) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.ReadOnlySpan rawData) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(string fileName) { throw null; } - public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPrivateKey() { throw null; } - public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPublicKey() { throw null; } - public string GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType nameType, bool forIssuer) { throw null; } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(byte[] rawData) { } - [System.CLSCompliantAttribute(false)] - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(string fileName) { } - [System.CLSCompliantAttribute(false)] - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public override void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } - public override void Reset() { } - public override string ToString() { throw null; } - public override string ToString(bool verbose) { throw null; } - public bool TryExportCertificatePem(System.Span destination, out int charsWritten) { throw null; } - public bool Verify() { throw null; } - } - public partial class X509Certificate2Collection : System.Security.Cryptography.X509Certificates.X509CertificateCollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable - { - public X509Certificate2Collection() { } - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } - public new System.Security.Cryptography.X509Certificates.X509Certificate2 this[int index] { get { throw null; } set { } } - public int Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } - public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public byte[]? Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) { throw null; } - public byte[]? Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string? password) { throw null; } - public string ExportCertificatePems() { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] - public string ExportPkcs7Pem() { throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Find(System.Security.Cryptography.X509Certificates.X509FindType findType, object findValue, bool validOnly) { throw null; } - public new System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator GetEnumerator() { throw null; } - public void Import(byte[] rawData) { } - public void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - public void Import(System.ReadOnlySpan rawData) { } - public void Import(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - public void Import(System.ReadOnlySpan rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - public void Import(string fileName) { } - public void Import(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - public void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } - public void ImportFromPem(System.ReadOnlySpan certPem) { } - public void ImportFromPemFile(string certPemFilePath) { } - public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - public bool TryExportCertificatePems(System.Span destination, out int charsWritten) { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] - public bool TryExportPkcs7Pem(System.Span destination, out int charsWritten) { throw null; } - } - public sealed partial class X509Certificate2Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - internal X509Certificate2Enumerator() { } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Current { get { throw null; } } - object System.Collections.IEnumerator.Current { get { throw null; } } - public bool MoveNext() { throw null; } - public void Reset() { } - bool System.Collections.IEnumerator.MoveNext() { throw null; } - void System.Collections.IEnumerator.Reset() { } - void System.IDisposable.Dispose() { } - } - public partial class X509CertificateCollection : System.Collections.CollectionBase - { - public X509CertificateCollection() { } - public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) { } - public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509Certificate[] value) { } - public System.Security.Cryptography.X509Certificates.X509Certificate this[int index] { get { throw null; } set { } } - public int Add(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } - public void AddRange(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) { } - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate[] value) { } - public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } - public void CopyTo(System.Security.Cryptography.X509Certificates.X509Certificate[] array, int index) { } - public new System.Security.Cryptography.X509Certificates.X509CertificateCollection.X509CertificateEnumerator GetEnumerator() { throw null; } - public override int GetHashCode() { throw null; } - public int IndexOf(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } - public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate value) { } - protected override void OnValidate(object value) { } - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate value) { } - public partial class X509CertificateEnumerator : System.Collections.IEnumerator - { - public X509CertificateEnumerator(System.Security.Cryptography.X509Certificates.X509CertificateCollection mappings) { } - public System.Security.Cryptography.X509Certificates.X509Certificate Current { get { throw null; } } - object System.Collections.IEnumerator.Current { get { throw null; } } - public bool MoveNext() { throw null; } - public void Reset() { } - bool System.Collections.IEnumerator.MoveNext() { throw null; } - void System.Collections.IEnumerator.Reset() { } - } - } - public partial class X509Chain : System.IDisposable - { - public X509Chain() { } - public X509Chain(bool useMachineContext) { } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] - public X509Chain(System.IntPtr chainContext) { } - public System.IntPtr ChainContext { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509ChainElementCollection ChainElements { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509ChainPolicy ChainPolicy { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainStatus { get { throw null; } } - public Microsoft.Win32.SafeHandles.SafeX509ChainHandle? SafeHandle { get { throw null; } } - public bool Build(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509Chain Create() { throw null; } - public void Dispose() { } - protected virtual void Dispose(bool disposing) { } - public void Reset() { } - } - public partial class X509ChainElement - { - internal X509ChainElement() { } - public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainElementStatus { get { throw null; } } - public string Information { get { throw null; } } - } - public sealed partial class X509ChainElementCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable - { - internal X509ChainElementCollection() { } - public int Count { get { throw null; } } - public bool IsSynchronized { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509ChainElement this[int index] { get { throw null; } } - public object SyncRoot { get { throw null; } } - public void CopyTo(System.Security.Cryptography.X509Certificates.X509ChainElement[] array, int index) { } - public System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator GetEnumerator() { throw null; } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - } - public sealed partial class X509ChainElementEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - internal X509ChainElementEnumerator() { } - public System.Security.Cryptography.X509Certificates.X509ChainElement Current { get { throw null; } } - object System.Collections.IEnumerator.Current { get { throw null; } } - public bool MoveNext() { throw null; } - public void Reset() { } - void System.IDisposable.Dispose() { } - } - public sealed partial class X509ChainPolicy - { - public X509ChainPolicy() { } - public System.Security.Cryptography.OidCollection ApplicationPolicy { get { throw null; } } - public System.Security.Cryptography.OidCollection CertificatePolicy { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection CustomTrustStore { get { throw null; } } - public bool DisableCertificateDownloads { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection ExtraStore { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509RevocationFlag RevocationFlag { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.X509ChainTrustMode TrustMode { get { throw null; } set { } } - public System.TimeSpan UrlRetrievalTimeout { get { throw null; } set { } } - public System.Security.Cryptography.X509Certificates.X509VerificationFlags VerificationFlags { get { throw null; } set { } } - public System.DateTime VerificationTime { get { throw null; } set { } } - public void Reset() { } - } - public partial struct X509ChainStatus - { - private object _dummy; - private int _dummyPrimitive; - public System.Security.Cryptography.X509Certificates.X509ChainStatusFlags Status { readonly get { throw null; } set { } } - [System.Diagnostics.CodeAnalysis.AllowNullAttribute] - public string StatusInformation { get { throw null; } set { } } - } - [System.FlagsAttribute] - public enum X509ChainStatusFlags - { - NoError = 0, - NotTimeValid = 1, - NotTimeNested = 2, - Revoked = 4, - NotSignatureValid = 8, - NotValidForUsage = 16, - UntrustedRoot = 32, - RevocationStatusUnknown = 64, - Cyclic = 128, - InvalidExtension = 256, - InvalidPolicyConstraints = 512, - InvalidBasicConstraints = 1024, - InvalidNameConstraints = 2048, - HasNotSupportedNameConstraint = 4096, - HasNotDefinedNameConstraint = 8192, - HasNotPermittedNameConstraint = 16384, - HasExcludedNameConstraint = 32768, - PartialChain = 65536, - CtlNotTimeValid = 131072, - CtlNotSignatureValid = 262144, - CtlNotValidForUsage = 524288, - HasWeakSignature = 1048576, - OfflineRevocation = 16777216, - NoIssuanceChainPolicy = 33554432, - ExplicitDistrust = 67108864, - HasNotSupportedCriticalExtension = 134217728, - } - public enum X509ChainTrustMode - { - System = 0, - CustomRootTrust = 1, - } - public enum X509ContentType - { - Unknown = 0, - Cert = 1, - SerializedCert = 2, - Pfx = 3, - Pkcs12 = 3, - SerializedStore = 4, - Pkcs7 = 5, - Authenticode = 6, - } - public sealed partial class X509EnhancedKeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public X509EnhancedKeyUsageExtension() { } - public X509EnhancedKeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedEnhancedKeyUsages, bool critical) { } - public X509EnhancedKeyUsageExtension(System.Security.Cryptography.OidCollection enhancedKeyUsages, bool critical) { } - public System.Security.Cryptography.OidCollection EnhancedKeyUsages { get { throw null; } } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } - } - public partial class X509Extension : System.Security.Cryptography.AsnEncodedData - { - protected X509Extension() { } - public X509Extension(System.Security.Cryptography.AsnEncodedData encodedExtension, bool critical) { } - public X509Extension(System.Security.Cryptography.Oid oid, byte[] rawData, bool critical) { } - public X509Extension(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData, bool critical) { } - public X509Extension(string oid, byte[] rawData, bool critical) { } - public X509Extension(string oid, System.ReadOnlySpan rawData, bool critical) { } - public bool Critical { get { throw null; } set { } } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } - } - public sealed partial class X509ExtensionCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable - { - public X509ExtensionCollection() { } - public int Count { get { throw null; } } - public bool IsSynchronized { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Extension this[int index] { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Extension? this[string oid] { get { throw null; } } - public object SyncRoot { get { throw null; } } - public int Add(System.Security.Cryptography.X509Certificates.X509Extension extension) { throw null; } - public void CopyTo(System.Security.Cryptography.X509Certificates.X509Extension[] array, int index) { } - public System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator GetEnumerator() { throw null; } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - } - public sealed partial class X509ExtensionEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - internal X509ExtensionEnumerator() { } - public System.Security.Cryptography.X509Certificates.X509Extension Current { get { throw null; } } - object System.Collections.IEnumerator.Current { get { throw null; } } - public bool MoveNext() { throw null; } - public void Reset() { } - void System.IDisposable.Dispose() { } - } - public enum X509FindType - { - FindByThumbprint = 0, - FindBySubjectName = 1, - FindBySubjectDistinguishedName = 2, - FindByIssuerName = 3, - FindByIssuerDistinguishedName = 4, - FindBySerialNumber = 5, - FindByTimeValid = 6, - FindByTimeNotYetValid = 7, - FindByTimeExpired = 8, - FindByTemplateName = 9, - FindByApplicationPolicy = 10, - FindByCertificatePolicy = 11, - FindByExtension = 12, - FindByKeyUsage = 13, - FindBySubjectKeyIdentifier = 14, - } - public enum X509IncludeOption - { - None = 0, - ExcludeRoot = 1, - EndCertOnly = 2, - WholeChain = 3, - } - [System.FlagsAttribute] - public enum X509KeyStorageFlags - { - DefaultKeySet = 0, - UserKeySet = 1, - MachineKeySet = 2, - Exportable = 4, - UserProtected = 8, - PersistKeySet = 16, - EphemeralKeySet = 32, - } - public sealed partial class X509KeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public X509KeyUsageExtension() { } - public X509KeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedKeyUsage, bool critical) { } - public X509KeyUsageExtension(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags keyUsages, bool critical) { } - public System.Security.Cryptography.X509Certificates.X509KeyUsageFlags KeyUsages { get { throw null; } } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } - } - [System.FlagsAttribute] - public enum X509KeyUsageFlags - { - None = 0, - EncipherOnly = 1, - CrlSign = 2, - KeyCertSign = 4, - KeyAgreement = 8, - DataEncipherment = 16, - KeyEncipherment = 32, - NonRepudiation = 64, - DigitalSignature = 128, - DecipherOnly = 32768, - } - public enum X509NameType - { - SimpleName = 0, - EmailName = 1, - UpnName = 2, - DnsName = 3, - DnsFromAlternativeName = 4, - UrlName = 5, - } - public enum X509RevocationFlag - { - EndCertificateOnly = 0, - EntireChain = 1, - ExcludeRoot = 2, - } - public enum X509RevocationMode - { - NoCheck = 0, - Online = 1, - Offline = 2, - } - public abstract partial class X509SignatureGenerator - { - protected X509SignatureGenerator() { } - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } - protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey(); - public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) { throw null; } - public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForRSA(System.Security.Cryptography.RSA key, System.Security.Cryptography.RSASignaturePadding signaturePadding) { throw null; } - public abstract byte[] GetSignatureAlgorithmIdentifier(System.Security.Cryptography.HashAlgorithmName hashAlgorithm); - public abstract byte[] SignData(byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm); - } - public sealed partial class X509Store : System.IDisposable - { - public X509Store() { } - public X509Store(System.IntPtr storeHandle) { } - public X509Store(System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName) { } - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { } - public X509Store(string storeName) { } - public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } - public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get { throw null; } } - public bool IsOpen { get { throw null; } } - public System.Security.Cryptography.X509Certificates.StoreLocation Location { get { throw null; } } - public string? Name { get { throw null; } } - public System.IntPtr StoreHandle { get { throw null; } } - public void Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } - public void Close() { } - public void Dispose() { } - public void Open(System.Security.Cryptography.X509Certificates.OpenFlags flags) { } - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } - } - public sealed partial class X509SubjectKeyIdentifierExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public X509SubjectKeyIdentifierExtension() { } - public X509SubjectKeyIdentifierExtension(byte[] subjectKeyIdentifier, bool critical) { } - public X509SubjectKeyIdentifierExtension(System.ReadOnlySpan subjectKeyIdentifier, bool critical) { } - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.AsnEncodedData encodedSubjectKeyIdentifier, bool critical) { } - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, bool critical) { } - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { } - public X509SubjectKeyIdentifierExtension(string subjectKeyIdentifier, bool critical) { } - public string? SubjectKeyIdentifier { get { throw null; } } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } - } - public enum X509SubjectKeyIdentifierHashAlgorithm - { - Sha1 = 0, - ShortSha1 = 1, - CapiSha1 = 2, - } - [System.FlagsAttribute] - public enum X509VerificationFlags - { - NoFlag = 0, - IgnoreNotTimeValid = 1, - IgnoreCtlNotTimeValid = 2, - IgnoreNotTimeNested = 4, - IgnoreInvalidBasicConstraints = 8, - AllowUnknownCertificateAuthority = 16, - IgnoreWrongUsage = 32, - IgnoreInvalidName = 64, - IgnoreInvalidPolicy = 128, - IgnoreEndRevocationUnknown = 256, - IgnoreCtlSignerRevocationUnknown = 512, - IgnoreCertificateAuthorityRevocationUnknown = 1024, - IgnoreRootRevocationUnknown = 2048, - AllFlags = 4095, - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.csproj index c3693ce72fe58..71d56f25038d4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.csproj @@ -5,15 +5,10 @@ $(NoWarn);SYSLIB0026 - + - - - - - diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Helpers.cs deleted file mode 100644 index 731440b7c7726..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Helpers.cs +++ /dev/null @@ -1,350 +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.Formats.Asn1; -using System.Globalization; -using System.Security.Cryptography; - -namespace Internal.Cryptography -{ - internal static partial class Helpers - { - internal static ReadOnlySpan AsSpanParameter(this byte[] array, string paramName) - { - if (array == null) - throw new ArgumentNullException(paramName); - - return new ReadOnlySpan(array); - } - - // Encode a byte array as an array of upper-case hex characters. - public static char[] ToHexArrayUpper(this byte[] bytes) - { - char[] chars = new char[bytes.Length * 2]; - HexConverter.EncodeToUtf16(bytes, chars); - return chars; - } - - // Encode a byte array as an upper case hex string. - public static string ToHexStringUpper(this byte[] bytes) => - Convert.ToHexString(bytes); - - // Decode a hex string-encoded byte array passed to various X509 crypto api. - // The parsing rules are overly forgiving but for compat reasons, they cannot be tightened. - public static byte[] DecodeHexString(this string hexString) - { - int whitespaceCount = 0; - - ReadOnlySpan s = hexString; - - if (s.Length != 0 && s[0] == '\u200E') - { - s = s.Slice(1); - } - - for (int i = 0; i < s.Length; i++) - { - if (char.IsWhiteSpace(s[i])) - whitespaceCount++; - } - - uint cbHex = (uint)(s.Length - whitespaceCount) / 2; - byte[] hex = new byte[cbHex]; - byte accum = 0; - bool byteInProgress = false; - int index = 0; - - for (int i = 0; i < s.Length; i++) - { - char c = s[i]; - - if (char.IsWhiteSpace(c)) - { - continue; - } - - accum <<= 4; - accum |= (byte)HexConverter.FromChar(c); - - byteInProgress = !byteInProgress; - - // If we've flipped from 0 to 1, back to 0, we have a whole byte - // so add it to the buffer. - if (!byteInProgress) - { - Debug.Assert(index < cbHex, "index < cbHex"); - - hex[index] = accum; - index++; - } - } - - // .NET Framework compat: - // The .NET Framework algorithm removed all whitespace before the loop, then went up to length/2 - // of what was left. This means that in the event of odd-length input the last char is - // ignored, no exception should be raised. - Debug.Assert(index == cbHex, "index == cbHex"); - - return hex; - } - - public static bool ContentsEqual(this byte[]? a1, byte[]? a2) - { - if (a1 == null) - { - return a2 == null; - } - - if (a2 == null || a1.Length != a2.Length) - { - return false; - } - - for (int i = 0; i < a1.Length; i++) - { - if (a1[i] != a2[i]) - { - return false; - } - } - - return true; - } - - internal static void AddRange(this ICollection coll, IEnumerable newData) - { - foreach (T datum in newData) - { - coll.Add(datum); - } - } - - // - // The following group of helpers emulates the non-public Calendar.IsValidDay() method used by X509Certificate.ToString(bool). - // - public static bool IsValidDay(this Calendar calendar, int year, int month, int day, int era) - { - return (calendar.IsValidMonth(year, month, era) && day >= 1 && day <= calendar.GetDaysInMonth(year, month, era)); - } - - private static bool IsValidMonth(this Calendar calendar, int year, int month, int era) - { - return (calendar.IsValidYear(year, era) && month >= 1 && month <= calendar.GetMonthsInYear(year, era)); - } - - private static bool IsValidYear(this Calendar calendar, int year, int era) - { - return (year >= calendar.GetYear(calendar.MinSupportedDateTime) && year <= calendar.GetYear(calendar.MaxSupportedDateTime)); - } - - internal static void DisposeAll(this IEnumerable disposables) - { - foreach (IDisposable disposable in disposables) - { - disposable.Dispose(); - } - } - - public static void ValidateDer(ReadOnlyMemory encodedValue) - { - try - { - Asn1Tag tag; - AsnReader reader = new AsnReader(encodedValue, AsnEncodingRules.DER); - - while (reader.HasData) - { - tag = reader.PeekTag(); - - // If the tag is in the UNIVERSAL class - // - // DER limits the constructed encoding to SEQUENCE and SET, as well as anything which gets - // a defined encoding as being an IMPLICIT SEQUENCE. - if (tag.TagClass == TagClass.Universal) - { - switch ((UniversalTagNumber)tag.TagValue) - { - case UniversalTagNumber.External: - case UniversalTagNumber.Embedded: - case UniversalTagNumber.Sequence: - case UniversalTagNumber.Set: - case UniversalTagNumber.UnrestrictedCharacterString: - if (!tag.IsConstructed) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - - break; - default: - if (tag.IsConstructed) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - - break; - } - } - - if (tag.IsConstructed) - { - ValidateDer(reader.PeekContentBytes()); - } - - // Skip past the current value. - reader.ReadEncodedValue(); - } - } - catch (AsnContentException e) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); - } - } - - public static ReadOnlyMemory DecodeOctetStringAsMemory(ReadOnlyMemory encodedOctetString) - { - try - { - ReadOnlySpan input = encodedOctetString.Span; - - if (AsnDecoder.TryReadPrimitiveOctetString( - input, - AsnEncodingRules.BER, - out ReadOnlySpan primitive, - out int consumed)) - { - if (consumed != input.Length) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - - if (input.Overlaps(primitive, out int offset)) - { - return encodedOctetString.Slice(offset, primitive.Length); - } - - Debug.Fail("input.Overlaps(primitive) failed after TryReadPrimitiveOctetString succeeded"); - } - - byte[] ret = AsnDecoder.ReadOctetString(input, AsnEncodingRules.BER, out consumed); - - if (consumed != input.Length) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - - return ret; - } - catch (AsnContentException e) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); - } - } - - public static bool AreSamePublicECParameters(ECParameters aParameters, ECParameters bParameters) - { - if (aParameters.Curve.CurveType != bParameters.Curve.CurveType) - return false; - - if (!aParameters.Q.X!.ContentsEqual(bParameters.Q.X!) || - !aParameters.Q.Y!.ContentsEqual(bParameters.Q.Y!)) - { - return false; - } - - ECCurve aCurve = aParameters.Curve; - ECCurve bCurve = bParameters.Curve; - - if (aCurve.IsNamed) - { - // On Windows we care about FriendlyName, on Unix we care about Value - return (aCurve.Oid.Value == bCurve.Oid.Value && aCurve.Oid.FriendlyName == bCurve.Oid.FriendlyName); - } - - if (!aCurve.IsExplicit) - { - // Implicit curve, always fail. - return false; - } - - // Ignore Cofactor (which is derivable from the prime or polynomial and Order) - // Ignore Seed and Hash (which are entirely optional, and about how A and B were built) - if (!aCurve.G.X!.ContentsEqual(bCurve.G.X!) || - !aCurve.G.Y!.ContentsEqual(bCurve.G.Y!) || - !aCurve.Order.ContentsEqual(bCurve.Order) || - !aCurve.A.ContentsEqual(bCurve.A) || - !aCurve.B.ContentsEqual(bCurve.B)) - { - return false; - } - - if (aCurve.IsPrime) - { - return aCurve.Prime.ContentsEqual(bCurve.Prime); - } - - if (aCurve.IsCharacteristic2) - { - return aCurve.Polynomial.ContentsEqual(bCurve.Polynomial); - } - - Debug.Fail($"Missing match criteria for curve type {aCurve.CurveType}"); - return false; - } - } - - internal static class DictionaryStringHelper - { - internal static string ReadAnyAsnString(this AsnReader tavReader) - { - Asn1Tag tag = tavReader.PeekTag(); - - if (tag.TagClass != TagClass.Universal) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - - switch ((UniversalTagNumber)tag.TagValue) - { - case UniversalTagNumber.BMPString: - case UniversalTagNumber.IA5String: - case UniversalTagNumber.NumericString: - case UniversalTagNumber.PrintableString: - case UniversalTagNumber.UTF8String: - case UniversalTagNumber.T61String: - // .NET's string comparisons start by checking the length, so a trailing - // NULL character which was literally embedded in the DER would cause a - // failure in .NET whereas it wouldn't have with strcmp. - return tavReader.ReadCharacterString((UniversalTagNumber)tag.TagValue).TrimEnd('\0'); - - default: - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - } - } - - internal struct PinAndClear : IDisposable - { - private byte[] _data; - private System.Runtime.InteropServices.GCHandle _gcHandle; - - internal static PinAndClear Track(byte[] data) - { - return new PinAndClear - { - _gcHandle = System.Runtime.InteropServices.GCHandle.Alloc( - data, - System.Runtime.InteropServices.GCHandleType.Pinned), - _data = data, - }; - } - - public void Dispose() - { - Array.Clear(_data); - _gcHandle.Free(); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/CertificatePal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/CertificatePal.cs deleted file mode 100644 index 3b78e65f5eeed..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/CertificatePal.cs +++ /dev/null @@ -1,36 +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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using Microsoft.Win32.SafeHandles; - -namespace Internal.Cryptography.Pal -{ - internal sealed partial class CertificatePal - { - public static ICertificatePal FromHandle(IntPtr handle) - { - return AndroidCertificatePal.FromHandle(handle); - } - - public static ICertificatePal FromOtherCert(X509Certificate cert) - { - return AndroidCertificatePal.FromOtherCert(cert); - } - - public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) - { - return AndroidCertificatePal.FromBlob(rawData, password, keyStorageFlags); - } - - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) - { - return AndroidCertificatePal.FromFile(fileName, password, keyStorageFlags); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/CertificatePal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/CertificatePal.cs deleted file mode 100644 index 0689088c77f52..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/CertificatePal.cs +++ /dev/null @@ -1,45 +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.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using Microsoft.Win32.SafeHandles; - -namespace Internal.Cryptography.Pal -{ - internal sealed partial class CertificatePal - { - public static ICertificatePal? FromHandle(IntPtr handle) - { - return FromHandle(handle, true); - } - - internal static ICertificatePal? FromHandle(IntPtr handle, bool throwOnFail) - { - return AppleCertificatePal.FromHandle(handle, throwOnFail); - } - - public static ICertificatePal? FromOtherCert(X509Certificate cert) - { - return AppleCertificatePal.FromOtherCert(cert); - } - - public static ICertificatePal FromBlob( - ReadOnlySpan rawData, - SafePasswordHandle password, - X509KeyStorageFlags keyStorageFlags) - { - return AppleCertificatePal.FromBlob(rawData, password, keyStorageFlags); - } - - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) - { - return AppleCertificatePal.FromFile(fileName, password, keyStorageFlags); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePal.cs deleted file mode 100644 index a7bfa16005f4d..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePal.cs +++ /dev/null @@ -1,34 +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.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32.SafeHandles; - -namespace Internal.Cryptography.Pal -{ - internal sealed partial class CertificatePal - { - public static ICertificatePal FromHandle(IntPtr handle) - { - return OpenSslX509CertificateReader.FromHandle(handle); - } - - public static ICertificatePal FromOtherCert(X509Certificate cert) - { - return OpenSslX509CertificateReader.FromOtherCert(cert); - } - - public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) - { - return OpenSslX509CertificateReader.FromBlob(rawData, password, keyStorageFlags); - } - - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) - { - return OpenSslX509CertificateReader.FromFile(fileName, password, keyStorageFlags); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/FindPal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/FindPal.cs deleted file mode 100644 index a15bf1b5abdd2..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/FindPal.cs +++ /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. - -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal -{ - internal sealed partial class FindPal - { - internal static IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) - { - return new OpenSslCertificateFinder(findFrom, copyTo, validOnly); - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.cs deleted file mode 100644 index 69c26d410e975..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.cs +++ /dev/null @@ -1,30 +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.Text; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; - -using Internal.Cryptography; -using Internal.Cryptography.Pal.Native; - -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal -{ - /// - /// A singleton class that encapsulates the native implementation of various X509 services. (Implementing this as a singleton makes it - /// easier to split the class into abstract and implementation classes if desired.) - /// - internal sealed partial class X509Pal : IX509Pal - { - public static IX509Pal Instance = new X509Pal(); - - private X509Pal() - { - } - } -} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx deleted file mode 100644 index b7e39a57646cf..0000000000000 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - Error occurred during a cryptographic operation. - - - Array may not be empty or null. - - - String cannot be empty or null. - - - The '{0}' string cannot be empty or null. - - - Illegal enum value: {0}. - - - Invalid handle. - - - Invalid type. - - - Non-negative number required. - - - Only single dimensional arrays are supported for the requested action. - - - The destination is too small to hold the encoded value. - - - Value of flags is invalid. - - - The value of 'nameType' is invalid. - - - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. - - - The OID value was invalid. - - - Index was out of range. Must be non-negative and less than the size of the collection. - - - An empty custom trust store is not supported on this platform. - - - The certificate has invalid policy. - - - The certificate chain is incomplete. - - - The certificate's revocation status could not be determined. - - - The certificate chain setting '{0}' is not supported on this platform. - - - The verification flag '{0}' is not supported on this platform. - - - The provided value of {0} bytes does not match the expected size of {1} bytes for the algorithm ({2}). - - - The certificate already has an associated private key. - - - The issuer certificate public key algorithm ({0}) does not match the value for this certificate request ({1}), use the X509SignatureGenerator overload. - - - The issuer certificate does not have a Basic Constraints extension. - - - The provided notBefore value is later than the notAfter value. - - - The value predates 1950 and has no defined encoding. - - - An X509Extension with OID '{0}' has already been specified. - - - The issuer certificate does not have an appropriate value for the Basic Constraints extension. - - - The issuer certificate's Key Usage extension is present but does not contain the KeyCertSign flag. - - - The provided issuer certificate does not have an associated private key. - - - The requested notAfter value ({0}) is later than issuerCertificate.NotAfter ({1}). - - - The requested notBefore value ({0}) is earlier than issuerCertificate.NotBefore ({1}). - - - This method cannot be used since no signing key was provided via a constructor, use an overload accepting an X509SignatureGenerator instead. - - - The issuer certificate uses an RSA key but no RSASignaturePadding was provided to a constructor. If one cannot be provided, use the X509SignatureGenerator overload. - - - Object contains only the public half of a key pair. A private key must also be provided. - - - The specified curve '{0}' or its parameters are not valid for this platform. - - - Only named curves are supported on this platform. - - - The message exceeds the maximum allowable length for the chosen options ({0}). - - - ASN1 corrupted data. - - - The hash algorithm name cannot be null or empty. - - - The specified Characteristic2 curve parameters are not valid. Polynomial, A, B, G.X, G.Y, and Order are required. A, B, G.X, G.Y must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Seed, Cofactor and Hash are optional. Other parameters are not allowed. - - - The chain context handle is invalid. - - - {0} is an invalid handle. - - - Object identifier (OID) is unknown. - - - Specified padding mode is not valid for this algorithm. - - - The provided PublicKey object is invalid, valid Oid and EncodedKeyValue property values are required. - - - The specified RSA parameters are not valid. Exponent and Modulus are required. If D is present, it must have the same length as Modulus. If D is present, P, Q, DP, DQ, and InverseQ are required and must have half the length of Modulus, rounded up, otherwise they must be omitted. - - - The store handle is invalid. - - - Custom trust certificates were provided while in System trust mode. - - - A null or disposed certificate was present in CustomTrustStore. - - - The key is too small for the requested operation. - - - Error occurred while decoding OAEP padding. - - - Cannot open an invalid handle. - - - A certificate referenced a private key which was already referenced, or could not be loaded. - - - The certificate data cannot be read with the provided password, the password may be incorrect. - - - The provided PFX data contains no certificates. - - - The provided key does not match the public key for this certificate. - - - The provided key does not match the public key algorithm for this certificate. - - - The length of the data to decrypt is not valid for the size of this key. - - - The provided hash value is not the expected size for the specified hash algorithm. - - - The Disallowed store is not supported on this platform, but already has data. All files under '{0}' must be removed. - - - Unix LocalMachine X509Stores are read-only for all users. - - - Unix LocalMachine X509Store is limited to the Root and CertificateAuthority stores. - - - The Disallowed store is not supported on this platform. - - - The {0} value cannot be set on Unix. - - - '{0}' is not a known hash algorithm. - - - '{0}' is not a known key algorithm. - - - The signature format '{0}' is unknown. - - - X509ContentType.SerializedCert and X509ContentType.SerializedStore are not supported on Unix. - - - The system cryptographic library returned error '{0}' of type '{1}' - - - The certificate export operation failed. - - - The parameter should be an X509Extension. - - - Invalid content type. - - - Invalid find type. - - - Invalid find value. - - - The flags '{0}' may not be specified together. - - - Cannot find the original signer. - - - PKCS#7 certificate format is not supported on this platform. - - - The PKCS#12 PersistKeySet flag is not supported on this platform. - - - The PKCS#12 Exportable flag is not supported on this platform. - - - The X509 certificate could not be added to the store. - - - The X509 certificate could not be added to the store because all candidate file names were in use. - - - The specified X509 certificate store does not exist. - - - The X509 certificate store has not been opened. - - - The X509 certificate store is read-only. - - - The X509 certificate could not be removed from the store. - - - The platform does not have a definition for an X509 certificate store named '{0}' with a StoreLocation of '{1}', and does not support creating it. - - - Adding a DSA private key to the store is not supported on this platform. - - - Failed to enumerate certificates from the store. - - - Root certificate store is not supported on this platform. - - - The certificate contents do not contain a PEM with a CERTIFICATE label, or the content is malformed. - - - The key contents do not contain a PEM, the content is malformed, or the key does not match the certificate. - - - Certificate '{0}' is corrupted. - - - Enumeration has not started. Call MoveNext. - - - CryptoApi ECDsa keys are not supported. - - - CryptoApi ECDiffieHellman keys are not supported. - - - Only one certificate with a private key can be exported in a single PFX. - - - The certificate key algorithm is not supported. - - - The X509 Basic Constraints extension with OID 2.5.29.10 is not supported. - - - X509Certificate is immutable on this platform. Use the equivalent constructor instead. - - - The home directory of the current user could not be determined. - - - The {0} value was invalid. - - - Access is denied. - - - Unknown error. - - - Algorithm '{0}' is not supported on this platform. - - - Unable to get file status. - - - Invalid directory permissions. The directory '{0}' must be readable, writable and executable by the owner. - - - The owner of '{0}' is not the current user. - - - Invalid file permissions. The file '{0}' must readable and writable by the current owner and by no one else, and the permissions could not be changed to meet that criteria. - - - The string contains an invalid X500 name attribute key, oid, value or delimiter. - - - The string contains a character not in the 7 bit ASCII character set. - - - This platform does not support loading with EphemeralKeySet. Remove the flag to allow keys to be temporarily created on disk. - - - Removing the requested certificate would modify user trust settings, and has been denied. - - - Removing the requested certificate would modify admin trust settings, and has been denied. - - - Specified key is not a valid size for this algorithm. - - - DSA keys can be imported, but new key generation is not supported on this platform. - - - The specified DSA parameters are not valid; P, Q, G and Y are all required. - - - The specified DSA parameters are not valid; P, G and Y must be the same length (the key size). - - - The specified DSA parameters are not valid; Q and X (if present) must be the same length. - - - The specified DSA parameters are not valid; J (if present) must be shorter than P. - - - The specified DSA parameters are not valid; Seed, if present, must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q must be 20 bytes long for keys shorter than 1024 bits. - - - The specified DSA parameters are not valid; Q's length must be one of 20, 32 or 64 bytes. - - - The input to WriteEncodedValue must represent a single encoded value with no trailing data. - - - ASN.1 Enumerated values only apply to enum types without the [Flags] attribute. - - - Named bit list operations require an enum with the [Flags] attribute. - - - The encoded named bit list value is larger than the value size of the '{0}' enum. - - - Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written. - - - Unused bit count must be between 0 and 7, inclusive. - - - Encode cannot be called while a Sequence or SetOf is still open. - - - Cannot pop the requested tag as it is not currently in progress. - - - Key is not a valid public or private key. - - - The EncryptedPrivateKeyInfo structure was decoded but was not successfully interpreted, the password may be incorrect. - - - The algorithm identified by '{0}' is unknown, not valid for the requested usage, or was not handled. - - - Value was invalid. - - - The KDF for algorithm '{0}' requires a char-based password input. - - - The provided RSAPrivateKey value has version '{0}', but version '{1}' is the maximum supported. - - - Key is not a valid private key. - - - System.Security.Cryptography.X509Certificates is not supported on this platform. - - - The keys from both parties must be the same size to generate a secret agreement. - - - Keys used with the ECDiffieHellmanCng algorithm must have an algorithm group of ECDiffieHellman. - - - The TLS key derivation function requires a seed value of exactly 64 bytes. - - - The certificate content type could not be determined. - - diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj index 3ea6525c02b41..1fe031a388f59 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj @@ -1,993 +1,10 @@ - true - $(NoWarn);CA5384 - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent) - enable + $(NetCoreAppCurrent) + true - - $(NoWarn);CS8769;SYSLIB0026 - SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported - - - true - true - - - - - - - - - - - - - - - - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.manual.cs - Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs - Common\System\Security\Cryptography\Asn1\AttributeAsn.xml - - - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml - - - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml - - - Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml - - - Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml.cs - Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml - - - Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml.cs - Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml - - - Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.manual.cs - Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - System\Security\Cryptography\X509Certificates\Asn1\BasicConstraintsAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\CertificateAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\CertificationRequestAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\CertificationRequestInfoAsn.xml - - - - - System\Security\Cryptography\X509Certificates\Asn1\TbsCertificateAsn.xml - - - - - System\Security\Cryptography\X509Certificates\Asn1\TimeAsn.xml - - - - - System\Security\Cryptography\X509Certificates\Asn1\ValidityAsn.xml - - - - - System\Security\Cryptography\X509Certificates\Asn1\AccessDescriptionAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\CertificatePolicyMappingAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\CertificateTemplateAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\PolicyConstraintsAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\PolicyInformationAsn.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - System\Security\Cryptography\X509Certificates\Asn1\DistributionPointAsn.xml - - - - System\Security\Cryptography\X509Certificates\Asn1\DistributionPointNameAsn.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Common\System\Security\Cryptography\Asn1\CurveAsn.xml - - - Common\System\Security\Cryptography\Asn1\CurveAsn.xml.cs - Common\System\Security\Cryptography\Asn1\CurveAsn.xml - - - Common\System\Security\Cryptography\Asn1\DssParms.xml - - - Common\System\Security\Cryptography\Asn1\DssParms.xml.cs - Common\System\Security\Cryptography\Asn1\DssParms.xml - - - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml - - - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml.cs - Common\System\Security\Cryptography\Asn1\ECDomainParameters.xml - - - Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml - - - Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml.cs - Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml - - - Common\System\Security\Cryptography\Asn1\FieldID.xml - - - Common\System\Security\Cryptography\Asn1\FieldID.xml.cs - Common\System\Security\Cryptography\Asn1\FieldID.xml - - - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml.cs - Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml.cs - Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml - - - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml - - - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml.cs - Common\System\Security\Cryptography\Asn1\SpecifiedECDomain.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\PBEParameter.xml - - - Common\System\Security\Cryptography\Asn1\PBEParameter.xml.cs - Common\System\Security\Cryptography\Asn1\PBEParameter.xml - - - Common\System\Security\Cryptography\Asn1\PBES2Params.xml - - - Common\System\Security\Cryptography\Asn1\PBES2Params.xml.cs - Common\System\Security\Cryptography\Asn1\PBES2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml.cs - Common\System\Security\Cryptography\Asn1\Pbkdf2Params.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml - - - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml.cs - Common\System\Security\Cryptography\Asn1\Pbkdf2SaltChoice.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml.cs - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.manual.cs - Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs index 8a80d0e116cb7..1cf2e93872ed1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs @@ -91,25 +91,28 @@ public static void CtorValidation_ECDSA_string() { string subjectName = null; ECDsa key = null; - HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); subjectName = ""; AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); key = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters); using (key) { + AssertExtensions.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); + AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, new HashAlgorithmName(""))); } } @@ -118,25 +121,27 @@ public static void CtorValidation_ECDSA_X500DN() { X500DistinguishedName subjectName = null; ECDsa key = null; - HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); subjectName = new X500DistinguishedName(""); AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); key = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters); using (key) { + AssertExtensions.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName))); AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, hashAlgorithm)); + () => new CertificateRequest(subjectName, key, new HashAlgorithmName(""))); } } @@ -145,32 +150,29 @@ public static void CtorValidation_RSA_string() { string subjectName = null; RSA key = null; - HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); RSASignaturePadding padding = null; AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); subjectName = ""; AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); key = RSA.Create(TestData.RsaBigExponentParams); using (key) { - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); - - hashAlgorithm = HashAlgorithmName.SHA256; + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); AssertExtensions.Throws( "padding", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, HashAlgorithmName.SHA256, padding)); } } @@ -179,32 +181,33 @@ public static void CtorValidation_RSA_X500DN() { X500DistinguishedName subjectName = null; RSA key = null; - HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); RSASignaturePadding padding = null; AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); subjectName = new X500DistinguishedName(""); AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); key = RSA.Create(TestData.RsaBigExponentParams); using (key) { - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); - hashAlgorithm = HashAlgorithmName.SHA256; + AssertExtensions.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, new HashAlgorithmName(""), padding)); AssertExtensions.Throws( "padding", - () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + () => new CertificateRequest(subjectName, key, HashAlgorithmName.SHA256, padding)); } } @@ -213,17 +216,16 @@ public static void CtorValidation_PublicKey_X500DN() { X500DistinguishedName subjectName = null; PublicKey publicKey = null; - HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + () => new CertificateRequest(subjectName, publicKey, default(HashAlgorithmName))); subjectName = new X500DistinguishedName(""); AssertExtensions.Throws( "publicKey", - () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + () => new CertificateRequest(subjectName, publicKey, default(HashAlgorithmName))); using (ECDsa ecdsa = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters)) { @@ -231,9 +233,13 @@ public static void CtorValidation_PublicKey_X500DN() publicKey = generator.PublicKey; } + AssertExtensions.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, publicKey, default(HashAlgorithmName))); + AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + () => new CertificateRequest(subjectName, publicKey, new HashAlgorithmName(""))); } } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.X509Certificates/tests/Resources/Strings.resx index 00e896df64b5b..684a789df83a6 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/Resources/Strings.resx @@ -69,90 +69,12 @@ The OID value was invalid. - - ASN.1 Enumerated values only apply to enum types without the [Flags] attribute. - - - Named bit list operations require an enum with the [Flags] attribute. - - - The encoded named bit list value is larger than the value size of the '{0}' enum. - - - Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written. - - - Unused bit count must be between 0 and 7, inclusive. - - - Field '{0}' of type '{1}' has ambiguous type '{2}', an attribute derived from AsnTypeAttribute is required. - - - [Choice].AllowNull=true is not valid because type '{0}' cannot have a null value. - - - The tag ({0} {1}) for field '{2}' on type '{3}' already is associated in this context with field '{4}' on type '{5}'. - - - Field '{0}' on [Choice] type '{1}' has a default value, which is not permitted. - - - An instance of [Choice] type '{0}' has no non-null fields. - - - Field '{0}' on [Choice] type '{1}' can not be assigned a null value. - - - Fields '{0}' and '{1}' on type '{2}' are both non-null when only one value is permitted. - - - Field '{0}' on [Choice] type '{1}' has introduced a type chain cycle. - - - Field '{0}' on type '{1}' has multiple attributes deriving from '{2}' when at most one is permitted. - - - Type '{0}' cannot be serialized or deserialized because it is an array of arrays. - - - Type '{0}' cannot be serialized or deserialized because it is a multi-dimensional array. - - - Type '{0}' cannot be serialized or deserialized because it is not sealed or has unbound generic parameters. - - - Field '{0}' on type '{1}' is declared [OptionalValue], but it can not be assigned a null value. - - - Unable to set field {0} on type {1}. - - - Field '{0}' on type '{1}' has specified an implicit tag value via [ExpectedTag] for [Choice] type '{2}'. ExplicitTag must be true, or the [ExpectedTag] attribute removed. - - - Field '{0}' of type '{1}' has an effective type of '{2}' when one of ({3}) was expected. - - - Field '{0}' on type '{1}' has a [UtcTime] TwoDigitYearMax value ({2}) smaller than the minimum (99). - - - Could not determine how to serialize or deserialize type '{0}'. - - - Encode cannot be called while a Sequence or SetOf is still open. - - - Cannot pop the requested tag as it is not currently in progress. - ASN1 corrupted data. The string contains a character not in the 7 bit ASCII character set. - - The input to WriteEncodedValue must represent a single encoded value with no trailing data. - Removing the requested certificate would modify user trust settings, and has been denied. diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs index 7c32c3cd7dccf..0976cba08b743 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs @@ -15,7 +15,7 @@ namespace System.Security.Cryptography.X509Certificates.Tests.RevocationTests public static partial class DynamicRevocationTests { // The CI machines are doing an awful lot of things at once, be generous with the timeout; - internal static readonly TimeSpan s_urlRetrievalLimit = TimeSpan.FromSeconds(15); + internal static readonly TimeSpan s_urlRetrievalLimit = TimeSpan.FromSeconds(30); private static readonly Oid s_tlsServerOid = new Oid("1.3.6.1.5.5.7.3.1", null); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs index 14863aff90810..464895d338fef 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs @@ -108,16 +108,16 @@ public void LoadXml() dsaKeyValue.LoadXml(xmlDoc.DocumentElement); var parameters = dsaKeyValue.Key.ExportParameters(false); - Assert.Equal(Convert.ToBase64String(parameters.P), pValue); - Assert.Equal(Convert.ToBase64String(parameters.Q), qValue); - Assert.Equal(Convert.ToBase64String(parameters.G), gValue); - Assert.Equal(Convert.ToBase64String(parameters.Y), yValue); + Assert.Equal(pValue, Convert.ToBase64String(parameters.P)); + Assert.Equal(qValue, Convert.ToBase64String(parameters.Q)); + Assert.Equal(gValue, Convert.ToBase64String(parameters.G)); + Assert.Equal(yValue, Convert.ToBase64String(parameters.Y)); // Not all providers support round-tripping the seed value. // Seed and PGenCounter are round-tripped together. if (parameters.Seed != null) { - Assert.Equal(Convert.ToBase64String(parameters.Seed), seedValue); + Assert.Equal(seedValue, Convert.ToBase64String(parameters.Seed)); Assert.Equal(BitConverter.GetBytes(parameters.Counter)[0], Convert.FromBase64String(pgenCounterValue)[0]); } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/XmlLicenseEncryptedRef.cs b/src/libraries/System.Security.Cryptography.Xml/tests/XmlLicenseEncryptedRef.cs index a10050c652f7d..5da12f940d60f 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/XmlLicenseEncryptedRef.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/XmlLicenseEncryptedRef.cs @@ -49,7 +49,7 @@ public Stream Decrypt(EncryptionMethod encryptionMethod, KeyInfo keyInfo, Stream KeyInfoEncryptedKey encryptedKeyInfo = clause as KeyInfoEncryptedKey; EncryptedKey encryptedKey = encryptedKeyInfo.EncryptedKey; - Assert.Equal(encryptedKey.EncryptionMethod.KeyAlgorithm, EncryptedXml.XmlEncRSAOAEPUrl); + Assert.Equal(EncryptedXml.XmlEncRSAOAEPUrl, encryptedKey.EncryptionMethod.KeyAlgorithm); Assert.Equal(1, encryptedKey.KeyInfo.Count); Assert.NotEqual(0, _asymmetricKeys.Count); diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index be3a8b7bb3b0b..e07748b754ef9 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -4,6 +4,44 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +namespace Microsoft.Win32.SafeHandles +{ + public abstract partial class SafeNCryptHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + protected SafeNCryptHandle() : base (default(bool)) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + protected SafeNCryptHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) : base (default(bool)) { } + protected override bool ReleaseHandle() { throw null; } + protected abstract bool ReleaseNativeHandle(); + } + public sealed partial class SafeNCryptKeyHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public SafeNCryptKeyHandle() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public SafeNCryptKeyHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) { } + protected override bool ReleaseNativeHandle() { throw null; } + } + public sealed partial class SafeNCryptProviderHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public SafeNCryptProviderHandle() { } + protected override bool ReleaseNativeHandle() { throw null; } + } + public sealed partial class SafeNCryptSecretHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public SafeNCryptSecretHandle() { } + protected override bool ReleaseNativeHandle() { throw null; } + } + public sealed partial class SafeX509ChainHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + public SafeX509ChainHandle() : base (default(bool)) { } + protected override void Dispose(bool disposing) { } + protected override bool ReleaseHandle() { throw null; } + } +} namespace System.Security.Cryptography { public abstract partial class Aes : System.Security.Cryptography.SymmetricAlgorithm @@ -30,6 +68,55 @@ public void Dispose() { } public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] tag, byte[]? associatedData = null) { } public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) { } } + public sealed partial class AesCng : System.Security.Cryptography.Aes + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public AesCng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public AesCng(string keyName) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public AesCng(string keyName, System.Security.Cryptography.CngProvider provider) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public AesCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { } + public override byte[] Key { get { throw null; } set { } } + public override int KeySize { get { throw null; } set { } } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + protected override void Dispose(bool disposing) { } + public override void GenerateIV() { } + public override void GenerateKey() { } + protected override bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) { throw null; } + protected override bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) { throw null; } + protected override bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class AesCryptoServiceProvider : System.Security.Cryptography.Aes + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public AesCryptoServiceProvider() { } + public override int BlockSize { get { throw null; } set { } } + public override int FeedbackSize { get { throw null; } set { } } + public override byte[] IV { get { throw null; } set { } } + public override byte[] Key { get { throw null; } set { } } + public override int KeySize { get { throw null; } set { } } + public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public override System.Security.Cryptography.CipherMode Mode { get { throw null; } set { } } + public override System.Security.Cryptography.PaddingMode Padding { get { throw null; } set { } } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + protected override void Dispose(bool disposing) { } + public override void GenerateIV() { } + public override void GenerateKey() { } + } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] @@ -202,6 +289,223 @@ public enum CipherMode CFB = 4, CTS = 5, } + public sealed partial class CngAlgorithm : System.IEquatable + { + public CngAlgorithm(string algorithm) { } + public string Algorithm { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellman { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP256 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP384 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP521 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDsa { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDsaP256 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDsaP384 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm ECDsaP521 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm MD5 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm Rsa { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm Sha1 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm Sha256 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm Sha384 { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithm Sha512 { get { throw null; } } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngAlgorithm? other) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(System.Security.Cryptography.CngAlgorithm? left, System.Security.Cryptography.CngAlgorithm? right) { throw null; } + public static bool operator !=(System.Security.Cryptography.CngAlgorithm? left, System.Security.Cryptography.CngAlgorithm? right) { throw null; } + public override string ToString() { throw null; } + } + public sealed partial class CngAlgorithmGroup : System.IEquatable + { + public CngAlgorithmGroup(string algorithmGroup) { } + public string AlgorithmGroup { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithmGroup DiffieHellman { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithmGroup Dsa { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithmGroup ECDiffieHellman { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithmGroup ECDsa { get { throw null; } } + public static System.Security.Cryptography.CngAlgorithmGroup Rsa { get { throw null; } } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngAlgorithmGroup? other) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(System.Security.Cryptography.CngAlgorithmGroup? left, System.Security.Cryptography.CngAlgorithmGroup? right) { throw null; } + public static bool operator !=(System.Security.Cryptography.CngAlgorithmGroup? left, System.Security.Cryptography.CngAlgorithmGroup? right) { throw null; } + public override string ToString() { throw null; } + } + [System.FlagsAttribute] + public enum CngExportPolicies + { + None = 0, + AllowExport = 1, + AllowPlaintextExport = 2, + AllowArchiving = 4, + AllowPlaintextArchiving = 8, + } + public sealed partial class CngKey : System.IDisposable + { + internal CngKey() { } + public System.Security.Cryptography.CngAlgorithm Algorithm { get { throw null; } } + public System.Security.Cryptography.CngAlgorithmGroup? AlgorithmGroup { get { throw null; } } + public System.Security.Cryptography.CngExportPolicies ExportPolicy { get { throw null; } } + public Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle Handle { get { throw null; } } + public bool IsEphemeral { get { throw null; } } + public bool IsMachineKey { get { throw null; } } + public string? KeyName { get { throw null; } } + public int KeySize { get { throw null; } } + public System.Security.Cryptography.CngKeyUsages KeyUsage { get { throw null; } } + public System.IntPtr ParentWindowHandle { get { throw null; } set { } } + public System.Security.Cryptography.CngProvider? Provider { get { throw null; } } + public Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle ProviderHandle { get { throw null; } } + public System.Security.Cryptography.CngUIPolicy UIPolicy { get { throw null; } } + public string? UniqueName { get { throw null; } } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string? keyName) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string? keyName, System.Security.Cryptography.CngKeyCreationParameters? creationParameters) { throw null; } + public void Delete() { } + public void Dispose() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static bool Exists(string keyName) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions options) { throw null; } + public byte[] Export(System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } + public System.Security.Cryptography.CngProperty GetProperty(string name, System.Security.Cryptography.CngPropertyOptions options) { throw null; } + public bool HasProperty(string name, System.Security.Cryptography.CngPropertyOptions options) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Import(byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Import(byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format, System.Security.Cryptography.CngProvider provider) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, System.Security.Cryptography.CngKeyHandleOpenOptions keyHandleOpenOptions) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Open(string keyName) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { throw null; } + public void SetProperty(System.Security.Cryptography.CngProperty property) { } + } + public sealed partial class CngKeyBlobFormat : System.IEquatable + { + public CngKeyBlobFormat(string format) { } + public static System.Security.Cryptography.CngKeyBlobFormat EccFullPrivateBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat EccFullPublicBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat EccPrivateBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat EccPublicBlob { get { throw null; } } + public string Format { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat GenericPrivateBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat GenericPublicBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat OpaqueTransportBlob { get { throw null; } } + public static System.Security.Cryptography.CngKeyBlobFormat Pkcs8PrivateBlob { get { throw null; } } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngKeyBlobFormat? other) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(System.Security.Cryptography.CngKeyBlobFormat? left, System.Security.Cryptography.CngKeyBlobFormat? right) { throw null; } + public static bool operator !=(System.Security.Cryptography.CngKeyBlobFormat? left, System.Security.Cryptography.CngKeyBlobFormat? right) { throw null; } + public override string ToString() { throw null; } + } + [System.FlagsAttribute] + public enum CngKeyCreationOptions + { + None = 0, + MachineKey = 32, + OverwriteExistingKey = 128, + } + public sealed partial class CngKeyCreationParameters + { + public CngKeyCreationParameters() { } + public System.Security.Cryptography.CngExportPolicies? ExportPolicy { get { throw null; } set { } } + public System.Security.Cryptography.CngKeyCreationOptions KeyCreationOptions { get { throw null; } set { } } + public System.Security.Cryptography.CngKeyUsages? KeyUsage { get { throw null; } set { } } + public System.Security.Cryptography.CngPropertyCollection Parameters { get { throw null; } } + public System.IntPtr ParentWindowHandle { get { throw null; } set { } } + public System.Security.Cryptography.CngProvider Provider { get { throw null; } set { } } + public System.Security.Cryptography.CngUIPolicy? UIPolicy { get { throw null; } set { } } + } + [System.FlagsAttribute] + public enum CngKeyHandleOpenOptions + { + None = 0, + EphemeralKey = 1, + } + [System.FlagsAttribute] + public enum CngKeyOpenOptions + { + None = 0, + UserKey = 0, + MachineKey = 32, + Silent = 64, + } + [System.FlagsAttribute] + public enum CngKeyUsages + { + None = 0, + Decryption = 1, + Signing = 2, + KeyAgreement = 4, + AllUsages = 16777215, + } + public partial struct CngProperty : System.IEquatable + { + private object _dummy; + private int _dummyPrimitive; + public CngProperty(string name, byte[]? value, System.Security.Cryptography.CngPropertyOptions options) { throw null; } + public readonly string Name { get { throw null; } } + public readonly System.Security.Cryptography.CngPropertyOptions Options { get { throw null; } } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Security.Cryptography.CngProperty other) { throw null; } + public override int GetHashCode() { throw null; } + public byte[]? GetValue() { throw null; } + public static bool operator ==(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) { throw null; } + public static bool operator !=(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) { throw null; } + } + public sealed partial class CngPropertyCollection : System.Collections.ObjectModel.Collection + { + public CngPropertyCollection() { } + } + [System.FlagsAttribute] + public enum CngPropertyOptions + { + Persist = -2147483648, + None = 0, + CustomProperty = 1073741824, + } + public sealed partial class CngProvider : System.IEquatable + { + public CngProvider(string provider) { } + public static System.Security.Cryptography.CngProvider MicrosoftPlatformCryptoProvider { get { throw null; } } + public static System.Security.Cryptography.CngProvider MicrosoftSmartCardKeyStorageProvider { get { throw null; } } + public static System.Security.Cryptography.CngProvider MicrosoftSoftwareKeyStorageProvider { get { throw null; } } + public string Provider { get { throw null; } } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.CngProvider? other) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(System.Security.Cryptography.CngProvider? left, System.Security.Cryptography.CngProvider? right) { throw null; } + public static bool operator !=(System.Security.Cryptography.CngProvider? left, System.Security.Cryptography.CngProvider? right) { throw null; } + public override string ToString() { throw null; } + } + public sealed partial class CngUIPolicy + { + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel) { } + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName) { } + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description) { } + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description, string? useContext) { } + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string? friendlyName, string? description, string? useContext, string? creationTitle) { } + public string? CreationTitle { get { throw null; } } + public string? Description { get { throw null; } } + public string? FriendlyName { get { throw null; } } + public System.Security.Cryptography.CngUIProtectionLevels ProtectionLevel { get { throw null; } } + public string? UseContext { get { throw null; } } + } + [System.FlagsAttribute] + public enum CngUIProtectionLevels + { + None = 0, + ProtectKey = 1, + ForceHighProtection = 2, + } public partial class CryptoConfig { public CryptoConfig() { } @@ -272,6 +576,52 @@ public enum CryptoStreamMode Read = 0, Write = 1, } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public sealed partial class CspKeyContainerInfo + { + public CspKeyContainerInfo(System.Security.Cryptography.CspParameters parameters) { } + public bool Accessible { get { throw null; } } + public bool Exportable { get { throw null; } } + public bool HardwareDevice { get { throw null; } } + public string? KeyContainerName { get { throw null; } } + public System.Security.Cryptography.KeyNumber KeyNumber { get { throw null; } } + public bool MachineKeyStore { get { throw null; } } + public bool Protected { get { throw null; } } + public string? ProviderName { get { throw null; } } + public int ProviderType { get { throw null; } } + public bool RandomlyGenerated { get { throw null; } } + public bool Removable { get { throw null; } } + public string UniqueKeyContainerName { get { throw null; } } + } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public sealed partial class CspParameters + { + public string? KeyContainerName; + public int KeyNumber; + public string? ProviderName; + public int ProviderType; + public CspParameters() { } + public CspParameters(int dwTypeIn) { } + public CspParameters(int dwTypeIn, string? strProviderNameIn) { } + public CspParameters(int dwTypeIn, string? strProviderNameIn, string? strContainerNameIn) { } + public System.Security.Cryptography.CspProviderFlags Flags { get { throw null; } set { } } + [System.CLSCompliantAttribute(false)] + public System.Security.SecureString? KeyPassword { get { throw null; } set { } } + public System.IntPtr ParentWindowHandle { get { throw null; } set { } } + } + [System.FlagsAttribute] + public enum CspProviderFlags + { + NoFlags = 0, + UseMachineKeyStore = 1, + UseDefaultKeyContainer = 2, + UseNonExportableKey = 4, + UseExistingKey = 8, + UseArchivableKey = 16, + UseUserProtectedKey = 32, + NoPrompt = 64, + CreateEphemeralKey = 128, + } public abstract partial class DeriveBytes : System.IDisposable { protected DeriveBytes() { } @@ -292,6 +642,18 @@ protected DES() { } public static bool IsSemiWeakKey(byte[] rgbKey) { throw null; } public static bool IsWeakKey(byte[] rgbKey) { throw null; } } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class DESCryptoServiceProvider : System.Security.Cryptography.DES + { + public DESCryptoServiceProvider() { } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override void GenerateIV() { } + public override void GenerateKey() { } + } public abstract partial class DSA : System.Security.Cryptography.AsymmetricAlgorithm { protected DSA() { } @@ -361,6 +723,113 @@ public override void ImportFromPem(System.ReadOnlySpan input) { } public bool VerifySignature(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } protected virtual bool VerifySignatureCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } } + public sealed partial class DSACng : System.Security.Cryptography.DSA + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public DSACng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public DSACng(int keySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public DSACng(System.Security.Cryptography.CngKey key) { } + public System.Security.Cryptography.CngKey Key { get { throw null; } } + public override string? KeyExchangeAlgorithm { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public override string SignatureAlgorithm { get { throw null; } } + public override byte[] CreateSignature(byte[] rgbHash) { throw null; } + protected override void Dispose(bool disposing) { } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } + protected override bool TryCreateSignatureCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashData(System.ReadOnlySpan source, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) { throw null; } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } + protected override bool VerifySignatureCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } + } + public sealed partial class DSACryptoServiceProvider : System.Security.Cryptography.DSA, System.Security.Cryptography.ICspAsymmetricAlgorithm + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public DSACryptoServiceProvider() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public DSACryptoServiceProvider(int dwKeySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public DSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters? parameters) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public DSACryptoServiceProvider(System.Security.Cryptography.CspParameters? parameters) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get { throw null; } } + public override string? KeyExchangeAlgorithm { get { throw null; } } + public override int KeySize { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public bool PersistKeyInCsp { get { throw null; } set { } } + public bool PublicOnly { get { throw null; } } + public override string SignatureAlgorithm { get { throw null; } } + public static bool UseMachineKeyStore { get { throw null; } set { } } + public override byte[] CreateSignature(byte[] rgbHash) { throw null; } + protected override void Dispose(bool disposing) { } + public byte[] ExportCspBlob(bool includePrivateParameters) { throw null; } + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public void ImportCspBlob(byte[] keyBlob) { } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } + public byte[] SignData(byte[] buffer) { throw null; } + public byte[] SignData(byte[] buffer, int offset, int count) { throw null; } + public byte[] SignData(System.IO.Stream inputStream) { throw null; } + public byte[] SignHash(byte[] rgbHash, string? str) { throw null; } + public bool VerifyData(byte[] rgbData, byte[] rgbSignature) { throw null; } + public bool VerifyHash(byte[] rgbHash, string? str, byte[] rgbSignature) { throw null; } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } + } + public sealed partial class DSAOpenSsl : System.Security.Cryptography.DSA + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public DSAOpenSsl() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public DSAOpenSsl(int keySize) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public DSAOpenSsl(System.IntPtr handle) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public DSAOpenSsl(System.Security.Cryptography.DSAParameters parameters) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public DSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } + public override byte[] CreateSignature(byte[] rgbHash) { throw null; } + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) { } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { throw null; } + } public partial struct DSAParameters { public int Counter; @@ -493,6 +962,107 @@ protected ECDiffieHellman() { } public override void FromXmlString(string xmlString) { } public override string ToXmlString(bool includePrivateParameters) { throw null; } } + public sealed partial class ECDiffieHellmanCng : System.Security.Cryptography.ECDiffieHellman + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanCng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanCng(int keySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanCng(System.Security.Cryptography.CngKey key) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanCng(System.Security.Cryptography.ECCurve curve) { } + public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get { throw null; } set { } } + public byte[]? HmacKey { get { throw null; } set { } } + public System.Security.Cryptography.CngKey Key { get { throw null; } } + public System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get { throw null; } set { } } + public override int KeySize { get { throw null; } set { } } + public byte[]? Label { get { throw null; } set { } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get { throw null; } } + public byte[]? SecretAppend { get { throw null; } set { } } + public byte[]? SecretPrepend { get { throw null; } set { } } + public byte[]? Seed { get { throw null; } set { } } + public bool UseSecretAgreementAsHmacKey { get { throw null; } } + public override byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } + public override byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, byte[]? hmacKey, byte[]? secretPrepend, byte[]? secretAppend) { throw null; } + public byte[] DeriveKeyMaterial(System.Security.Cryptography.CngKey otherPartyPublicKey) { throw null; } + public override byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) { throw null; } + public override byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) { throw null; } + public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.CngKey otherPartyPublicKey) { throw null; } + public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) { throw null; } + protected override void Dispose(bool disposing) { } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } + public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) { } + public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } + public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) { throw null; } + } + public sealed partial class ECDiffieHellmanCngPublicKey : System.Security.Cryptography.ECDiffieHellmanPublicKey + { + internal ECDiffieHellmanCngPublicKey() { } + public System.Security.Cryptography.CngKeyBlobFormat BlobFormat { get { throw null; } } + protected override void Dispose(bool disposing) { } + public override System.Security.Cryptography.ECParameters ExportExplicitParameters() { throw null; } + public override System.Security.Cryptography.ECParameters ExportParameters() { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Security.Cryptography.ECDiffieHellmanPublicKey FromByteArray(byte[] publicKeyBlob, System.Security.Cryptography.CngKeyBlobFormat format) { throw null; } + public static System.Security.Cryptography.ECDiffieHellmanCngPublicKey FromXmlString(string xml) { throw null; } + public System.Security.Cryptography.CngKey Import() { throw null; } + public override string ToXmlString() { throw null; } + } + public enum ECDiffieHellmanKeyDerivationFunction + { + Hash = 0, + Hmac = 1, + Tls = 2, + } + public sealed partial class ECDiffieHellmanOpenSsl : System.Security.Cryptography.ECDiffieHellman + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanOpenSsl() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanOpenSsl(int keySize) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanOpenSsl(System.IntPtr handle) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanOpenSsl(System.Security.Cryptography.ECCurve curve) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDiffieHellmanOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } + public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get { throw null; } } + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } + } public abstract partial class ECDiffieHellmanPublicKey : System.IDisposable { protected ECDiffieHellmanPublicKey() { } @@ -558,6 +1128,91 @@ public override void FromXmlString(string xmlString) { } public bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } protected virtual bool VerifyHashCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } } + public sealed partial class ECDsaCng : System.Security.Cryptography.ECDsa + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDsaCng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDsaCng(int keySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDsaCng(System.Security.Cryptography.CngKey key) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public ECDsaCng(System.Security.Cryptography.ECCurve curve) { } + public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get { throw null; } set { } } + public System.Security.Cryptography.CngKey Key { get { throw null; } } + public override int KeySize { get { throw null; } set { } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + protected override void Dispose(bool disposing) { } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) { throw null; } + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) { throw null; } + public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) { } + public override void GenerateKey(System.Security.Cryptography.ECCurve curve) { } + protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } + public byte[] SignData(byte[] data) { throw null; } + public byte[] SignData(byte[] data, int offset, int count) { throw null; } + public byte[] SignData(System.IO.Stream data) { throw null; } + public override byte[] SignHash(byte[] hash) { throw null; } + public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashData(System.ReadOnlySpan source, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) { throw null; } + public override bool TrySignHash(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + protected override bool TrySignHashCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) { throw null; } + public bool VerifyData(byte[] data, byte[] signature) { throw null; } + public bool VerifyData(byte[] data, int offset, int count, byte[] signature) { throw null; } + public bool VerifyData(System.IO.Stream data, byte[] signature) { throw null; } + public override bool VerifyHash(byte[] hash, byte[] signature) { throw null; } + public override bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature) { throw null; } + protected override bool VerifyHashCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) { throw null; } + } + public sealed partial class ECDsaOpenSsl : System.Security.Cryptography.ECDsa + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDsaOpenSsl() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDsaOpenSsl(int keySize) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDsaOpenSsl(System.IntPtr handle) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDsaOpenSsl(System.Security.Cryptography.ECCurve curve) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public ECDsaOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } + public override byte[] SignHash(byte[] hash) { throw null; } + public override bool VerifyHash(byte[] hash, byte[] signature) { throw null; } + } + public enum ECKeyXmlFormat + { + Rfc4050 = 0, + } public partial struct ECParameters { public System.Security.Cryptography.ECCurve Curve; @@ -681,8 +1336,14 @@ protected override void Dispose(bool disposing) { } protected override void HashCore(byte[] rgb, int ib, int cb) { } protected override void HashCore(System.ReadOnlySpan source) { } public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } protected override byte[] HashFinal() { throw null; } public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } @@ -703,8 +1364,14 @@ protected override void Dispose(bool disposing) { } protected override void HashCore(byte[] rgb, int ib, int cb) { } protected override void HashCore(System.ReadOnlySpan source) { } public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } protected override byte[] HashFinal() { throw null; } public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } @@ -722,8 +1389,14 @@ protected override void Dispose(bool disposing) { } protected override void HashCore(byte[] rgb, int ib, int cb) { } protected override void HashCore(System.ReadOnlySpan source) { } public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } protected override byte[] HashFinal() { throw null; } public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } @@ -743,8 +1416,14 @@ protected override void Dispose(bool disposing) { } protected override void HashCore(byte[] rgb, int ib, int cb) { } protected override void HashCore(System.ReadOnlySpan source) { } public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } protected override byte[] HashFinal() { throw null; } public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } @@ -764,8 +1443,14 @@ protected override void Dispose(bool disposing) { } protected override void HashCore(byte[] rgb, int ib, int cb) { } protected override void HashCore(System.ReadOnlySpan source) { } public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } protected override byte[] HashFinal() { throw null; } public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } @@ -780,6 +1465,12 @@ public partial interface ICryptoTransform : System.IDisposable int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset); byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount); } + public partial interface ICspAsymmetricAlgorithm + { + System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get; } + byte[] ExportCspBlob(bool includePrivateParameters); + void ImportCspBlob(byte[] rawData); + } public sealed partial class IncrementalHash : System.IDisposable { internal IncrementalHash() { } @@ -812,6 +1503,11 @@ protected KeyedHashAlgorithm() { } public static new System.Security.Cryptography.KeyedHashAlgorithm? Create(string algName) { throw null; } protected override void Dispose(bool disposing) { } } + public enum KeyNumber + { + Exchange = 1, + Signature = 2, + } public sealed partial class KeySizes { public KeySizes(int minSize, int maxSize, int skipSize) { } @@ -834,10 +1530,26 @@ protected MD5() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.MD5? Create(string algName) { throw null; } public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class MD5CryptoServiceProvider : System.Security.Cryptography.MD5 + { + public MD5CryptoServiceProvider() { } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] array, int ibStart, int cbSize) { } + protected override void HashCore(System.ReadOnlySpan source) { } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } public sealed partial class Oid { public Oid() { } @@ -893,6 +1605,30 @@ public enum PaddingMode ANSIX923 = 4, ISO10126 = 5, } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public partial class PasswordDeriveBytes : System.Security.Cryptography.DeriveBytes + { + public PasswordDeriveBytes(byte[] password, byte[]? salt) { } + public PasswordDeriveBytes(byte[] password, byte[]? salt, System.Security.Cryptography.CspParameters? cspParams) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] + public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] + public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } + public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt) { } + public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, System.Security.Cryptography.CspParameters? cspParams) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] + public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] + public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } + public string HashName { get { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] set { } } + public int IterationCount { get { throw null; } set { } } + public byte[]? Salt { get { throw null; } set { } } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public byte[] CryptDeriveKey(string? algname, string? alghashname, int keySize, byte[] rgbIV) { throw null; } + protected override void Dispose(bool disposing) { } + public override byte[] GetBytes(int cb) { throw null; } + public override void Reset() { } + } public enum PbeEncryptionAlgorithm { Unknown = 0, @@ -962,6 +1698,20 @@ protected RC2() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.RC2? Create(string AlgName) { throw null; } } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class RC2CryptoServiceProvider : System.Security.Cryptography.RC2 + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public RC2CryptoServiceProvider() { } + public override int EffectiveKeySize { get { throw null; } set { } } + public bool UseSalt { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override void GenerateIV() { } + public override void GenerateKey() { } + } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public partial class Rfc2898DeriveBytes : System.Security.Cryptography.DeriveBytes { @@ -1020,6 +1770,21 @@ protected override void Dispose(bool disposing) { } public override void GenerateIV() { } public override void GenerateKey() { } } + [System.ObsoleteAttribute("RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.", DiagnosticId = "SYSLIB0023", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class RNGCryptoServiceProvider : System.Security.Cryptography.RandomNumberGenerator + { + public RNGCryptoServiceProvider() { } + public RNGCryptoServiceProvider(byte[] rgb) { } + public RNGCryptoServiceProvider(System.Security.Cryptography.CspParameters? cspParams) { } + public RNGCryptoServiceProvider(string str) { } + protected override void Dispose(bool disposing) { } + public override void GetBytes(byte[] data) { } + public override void GetBytes(byte[] data, int offset, int count) { } + public override void GetBytes(System.Span data) { } + public override void GetNonZeroBytes(byte[] data) { } + public override void GetNonZeroBytes(System.Span data) { } + } public abstract partial class RSA : System.Security.Cryptography.AsymmetricAlgorithm { protected RSA() { } @@ -1080,6 +1845,82 @@ public override void ImportFromPem(System.ReadOnlySpan input) { } public virtual bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } public virtual bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } } + public sealed partial class RSACng : System.Security.Cryptography.RSA + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public RSACng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public RSACng(int keySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public RSACng(System.Security.Cryptography.CngKey key) { } + public System.Security.Cryptography.CngKey Key { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public override byte[] Decrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } + protected override void Dispose(bool disposing) { } + public override byte[] Encrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) { throw null; } + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override byte[] SignHash(byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } + public override bool TryDecrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) { throw null; } + public override bool TryEncrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) { throw null; } + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) { throw null; } + public override bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) { throw null; } + public override bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } + public override bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } + } + public sealed partial class RSACryptoServiceProvider : System.Security.Cryptography.RSA, System.Security.Cryptography.ICspAsymmetricAlgorithm + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public RSACryptoServiceProvider() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public RSACryptoServiceProvider(int dwKeySize) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public RSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters? parameters) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public RSACryptoServiceProvider(System.Security.Cryptography.CspParameters? parameters) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get { throw null; } } + public override string? KeyExchangeAlgorithm { get { throw null; } } + public override int KeySize { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public bool PersistKeyInCsp { get { throw null; } set { } } + public bool PublicOnly { get { throw null; } } + public override string SignatureAlgorithm { get { throw null; } } + public static bool UseMachineKeyStore { get { throw null; } set { } } + public byte[] Decrypt(byte[] rgb, bool fOAEP) { throw null; } + public override byte[] Decrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } + public override byte[] DecryptValue(byte[] rgb) { throw null; } + protected override void Dispose(bool disposing) { } + public byte[] Encrypt(byte[] rgb, bool fOAEP) { throw null; } + public override byte[] Encrypt(byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) { throw null; } + public override byte[] EncryptValue(byte[] rgb) { throw null; } + public byte[] ExportCspBlob(bool includePrivateParameters) { throw null; } + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + protected override byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public void ImportCspBlob(byte[] keyBlob) { } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } + public byte[] SignData(byte[] buffer, int offset, int count, object halg) { throw null; } + public byte[] SignData(byte[] buffer, object halg) { throw null; } + public byte[] SignData(System.IO.Stream inputStream, object halg) { throw null; } + public override byte[] SignHash(byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } + public byte[] SignHash(byte[] rgbHash, string? str) { throw null; } + public bool VerifyData(byte[] buffer, object halg, byte[] signature) { throw null; } + public override bool VerifyHash(byte[] hash, byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { throw null; } + public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) { throw null; } + } public sealed partial class RSAEncryptionPadding : System.IEquatable { internal RSAEncryptionPadding() { } @@ -1122,6 +1963,42 @@ public RSAOAEPKeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgori public override byte[] CreateKeyExchange(byte[] rgbData, System.Type? symAlgType) { throw null; } public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } } + public sealed partial class RSAOpenSsl : System.Security.Cryptography.RSA + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public RSAOpenSsl() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public RSAOpenSsl(int keySize) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public RSAOpenSsl(System.IntPtr handle) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public RSAOpenSsl(System.Security.Cryptography.RSAParameters parameters) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public RSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) { } + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() { throw null; } + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) { throw null; } + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) { } + } public partial struct RSAParameters { public byte[]? D; @@ -1188,6 +2065,30 @@ public enum RSASignaturePaddingMode Pkcs1 = 0, Pss = 1, } + public sealed partial class SafeEvpPKeyHandle : System.Runtime.InteropServices.SafeHandle + { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public SafeEvpPKeyHandle() : base (default(System.IntPtr), default(bool)) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public SafeEvpPKeyHandle(System.IntPtr handle, bool ownsHandle) : base (default(System.IntPtr), default(bool)) { } + public override bool IsInvalid { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")] + public static long OpenSslVersion { get { throw null; } } + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateHandle() { throw null; } + protected override bool ReleaseHandle() { throw null; } + } public abstract partial class SHA1 : System.Security.Cryptography.HashAlgorithm { public const int HashSizeInBits = 160; @@ -1197,12 +2098,28 @@ protected SHA1() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.SHA1? Create(string hashName) { throw null; } public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } } [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class SHA1CryptoServiceProvider : System.Security.Cryptography.SHA1 + { + public SHA1CryptoServiceProvider() { } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] array, int ibStart, int cbSize) { } + protected override void HashCore(System.ReadOnlySpan source) { } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class SHA1Managed : System.Security.Cryptography.SHA1 { public SHA1Managed() { } @@ -1222,12 +2139,28 @@ protected SHA256() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.SHA256? Create(string hashName) { throw null; } public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } } [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class SHA256CryptoServiceProvider : System.Security.Cryptography.SHA256 + { + public SHA256CryptoServiceProvider() { } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] array, int ibStart, int cbSize) { } + protected override void HashCore(System.ReadOnlySpan source) { } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class SHA256Managed : System.Security.Cryptography.SHA256 { public SHA256Managed() { } @@ -1247,12 +2180,28 @@ protected SHA384() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.SHA384? Create(string hashName) { throw null; } public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } } [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class SHA384CryptoServiceProvider : System.Security.Cryptography.SHA384 + { + public SHA384CryptoServiceProvider() { } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] array, int ibStart, int cbSize) { } + protected override void HashCore(System.ReadOnlySpan source) { } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class SHA384Managed : System.Security.Cryptography.SHA384 { public SHA384Managed() { } @@ -1272,12 +2221,28 @@ protected SHA512() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.SHA512? Create(string hashName) { throw null; } public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } public static byte[] HashData(System.ReadOnlySpan source) { throw null; } public static int HashData(System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } } [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class SHA512CryptoServiceProvider : System.Security.Cryptography.SHA512 + { + public SHA512CryptoServiceProvider() { } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] array, int ibStart, int cbSize) { } + protected override void HashCore(System.ReadOnlySpan source) { } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class SHA512Managed : System.Security.Cryptography.SHA512 { public SHA512Managed() { } @@ -1398,4 +2363,766 @@ protected TripleDES() { } public static new System.Security.Cryptography.TripleDES? Create(string str) { throw null; } public static bool IsWeakKey(byte[] rgbKey) { throw null; } } + public sealed partial class TripleDESCng : System.Security.Cryptography.TripleDES + { + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public TripleDESCng() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public TripleDESCng(string keyName) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) { } + public override byte[] Key { get { throw null; } set { } } + public override int KeySize { get { throw null; } set { } } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + protected override void Dispose(bool disposing) { } + public override void GenerateIV() { } + public override void GenerateKey() { } + protected override bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) { throw null; } + protected override bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + protected override bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) { throw null; } + protected override bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) { throw null; } + } + [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId = "SYSLIB0021", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class TripleDESCryptoServiceProvider : System.Security.Cryptography.TripleDES + { + public TripleDESCryptoServiceProvider() { } + public override int BlockSize { get { throw null; } set { } } + public override int FeedbackSize { get { throw null; } set { } } + public override byte[] IV { get { throw null; } set { } } + public override byte[] Key { get { throw null; } set { } } + public override int KeySize { get { throw null; } set { } } + public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get { throw null; } } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { throw null; } } + public override System.Security.Cryptography.CipherMode Mode { get { throw null; } set { } } + public override System.Security.Cryptography.PaddingMode Padding { get { throw null; } set { } } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() { throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { throw null; } + protected override void Dispose(bool disposing) { } + public override void GenerateIV() { } + public override void GenerateKey() { } + } +} +namespace System.Security.Cryptography.X509Certificates +{ + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public sealed partial class CertificateRequest + { + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } + public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } + public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } + public System.Collections.ObjectModel.Collection CertificateExtensions { get { throw null; } } + public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get { throw null; } } + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) { throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) { throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSigned(System.DateTimeOffset notBefore, System.DateTimeOffset notAfter) { throw null; } + public byte[] CreateSigningRequest() { throw null; } + public byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) { throw null; } + } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public static partial class DSACertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) { throw null; } + public static System.Security.Cryptography.DSA? GetDSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public static System.Security.Cryptography.DSA? GetDSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + } + public static partial class ECDsaCertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.ECDsa privateKey) { throw null; } + public static System.Security.Cryptography.ECDsa? GetECDsaPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public static System.Security.Cryptography.ECDsa? GetECDsaPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + } + [System.FlagsAttribute] + public enum OpenFlags + { + ReadOnly = 0, + ReadWrite = 1, + MaxAllowed = 2, + OpenExistingOnly = 4, + IncludeArchived = 8, + } + public sealed partial class PublicKey + { + public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData parameters, System.Security.Cryptography.AsnEncodedData keyValue) { } + public System.Security.Cryptography.AsnEncodedData EncodedKeyValue { get { throw null; } } + public System.Security.Cryptography.AsnEncodedData EncodedParameters { get { throw null; } } + [System.ObsoleteAttribute("PublicKey.Key is obsolete. Use the appropriate method to get the public key, such as GetRSAPublicKey.", DiagnosticId = "SYSLIB0027", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public System.Security.Cryptography.AsymmetricAlgorithm Key { get { throw null; } } + public System.Security.Cryptography.Oid Oid { get { throw null; } } + public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } + public byte[] ExportSubjectPublicKeyInfo() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public System.Security.Cryptography.DSA? GetDSAPublicKey() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPublicKey() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public System.Security.Cryptography.ECDsa? GetECDsaPublicKey() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public System.Security.Cryptography.RSA? GetRSAPublicKey() { throw null; } + public bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) { throw null; } + } + public static partial class RSACertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.RSA privateKey) { throw null; } + public static System.Security.Cryptography.RSA? GetRSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public static System.Security.Cryptography.RSA? GetRSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + } + public enum StoreLocation + { + CurrentUser = 1, + LocalMachine = 2, + } + public enum StoreName + { + AddressBook = 1, + AuthRoot = 2, + CertificateAuthority = 3, + Disallowed = 4, + My = 5, + Root = 6, + TrustedPeople = 7, + TrustedPublisher = 8, + } + public sealed partial class SubjectAlternativeNameBuilder + { + public SubjectAlternativeNameBuilder() { } + public void AddDnsName(string dnsName) { } + public void AddEmailAddress(string emailAddress) { } + public void AddIpAddress(System.Net.IPAddress ipAddress) { } + public void AddUri(System.Uri uri) { } + public void AddUserPrincipalName(string upn) { } + public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical = false) { throw null; } + } + public sealed partial class X500DistinguishedName : System.Security.Cryptography.AsnEncodedData + { + public X500DistinguishedName(byte[] encodedDistinguishedName) { } + public X500DistinguishedName(System.ReadOnlySpan encodedDistinguishedName) { } + public X500DistinguishedName(System.Security.Cryptography.AsnEncodedData encodedDistinguishedName) { } + public X500DistinguishedName(System.Security.Cryptography.X509Certificates.X500DistinguishedName distinguishedName) { } + public X500DistinguishedName(string distinguishedName) { } + public X500DistinguishedName(string distinguishedName, System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) { } + public string Name { get { throw null; } } + public string Decode(System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) { throw null; } + public override string Format(bool multiLine) { throw null; } + } + [System.FlagsAttribute] + public enum X500DistinguishedNameFlags + { + None = 0, + Reversed = 1, + UseSemicolons = 16, + DoNotUsePlusSign = 32, + DoNotUseQuotes = 64, + UseCommas = 128, + UseNewLines = 256, + UseUTF8Encoding = 4096, + UseT61Encoding = 8192, + ForceUTF8Encoding = 16384, + } + public sealed partial class X509BasicConstraintsExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public X509BasicConstraintsExtension() { } + public X509BasicConstraintsExtension(bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical) { } + public X509BasicConstraintsExtension(System.Security.Cryptography.AsnEncodedData encodedBasicConstraints, bool critical) { } + public bool CertificateAuthority { get { throw null; } } + public bool HasPathLengthConstraint { get { throw null; } } + public int PathLengthConstraint { get { throw null; } } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + } + public partial class X509Certificate : System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable + { + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(byte[] data) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(byte[] rawData, System.Security.SecureString? password) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(byte[] rawData, string? password) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(System.IntPtr handle) { } + public X509Certificate(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(System.Security.Cryptography.X509Certificates.X509Certificate cert) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(string fileName) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(string fileName, System.Security.SecureString? password) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(string fileName, string? password) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + public System.IntPtr Handle { get { throw null; } } + public string Issuer { get { throw null; } } + public string Subject { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromCertFile(string filename) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromSignedFile(string filename) { throw null; } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public virtual bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.Cryptography.X509Certificates.X509Certificate? other) { throw null; } + public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) { throw null; } + [System.CLSCompliantAttribute(false)] + public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, System.Security.SecureString? password) { throw null; } + public virtual byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string? password) { throw null; } + protected static string FormatDate(System.DateTime date) { throw null; } + public virtual byte[] GetCertHash() { throw null; } + public virtual byte[] GetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public virtual string GetCertHashString() { throw null; } + public virtual string GetCertHashString(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } + public virtual string GetEffectiveDateString() { throw null; } + public virtual string GetExpirationDateString() { throw null; } + public virtual string GetFormat() { throw null; } + public override int GetHashCode() { throw null; } + [System.ObsoleteAttribute("X509Certificate.GetIssuerName has been deprecated. Use the Issuer property instead.")] + public virtual string GetIssuerName() { throw null; } + public virtual string GetKeyAlgorithm() { throw null; } + public virtual byte[] GetKeyAlgorithmParameters() { throw null; } + public virtual string GetKeyAlgorithmParametersString() { throw null; } + [System.ObsoleteAttribute("X509Certificate.GetName has been deprecated. Use the Subject property instead.")] + public virtual string GetName() { throw null; } + public virtual byte[] GetPublicKey() { throw null; } + public virtual string GetPublicKeyString() { throw null; } + public virtual byte[] GetRawCertData() { throw null; } + public virtual string GetRawCertDataString() { throw null; } + public virtual byte[] GetSerialNumber() { throw null; } + public virtual string GetSerialNumberString() { throw null; } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(byte[] rawData) { } + [System.CLSCompliantAttribute(false)] + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(string fileName) { } + [System.CLSCompliantAttribute(false)] + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public virtual void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + public virtual void Reset() { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } + void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public override string ToString() { throw null; } + public virtual string ToString(bool fVerbose) { throw null; } + public virtual bool TryGetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Span destination, out int bytesWritten) { throw null; } + } + public partial class X509Certificate2 : System.Security.Cryptography.X509Certificates.X509Certificate + { + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(byte[] rawData) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(byte[] rawData, System.Security.SecureString? password) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(byte[] rawData, string? password) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(System.IntPtr handle) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(System.ReadOnlySpan rawData) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + protected X509Certificate2(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(System.Security.Cryptography.X509Certificates.X509Certificate certificate) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName, System.Security.SecureString? password) { } + [System.CLSCompliantAttribute(false)] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName, string? password) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public X509Certificate2(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + public bool Archived { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public System.Security.Cryptography.X509Certificates.X509ExtensionCollection Extensions { get { throw null; } } + public string FriendlyName { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public bool HasPrivateKey { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName IssuerName { get { throw null; } } + public System.DateTime NotAfter { get { throw null; } } + public System.DateTime NotBefore { get { throw null; } } + [System.ObsoleteAttribute("X509Certificate2.PrivateKey is obsolete. Use the appropriate method to get the private key, such as GetRSAPrivateKey, or use the CopyWithPrivateKey method to create a new instance with a private key.", DiagnosticId = "SYSLIB0028", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public System.Security.Cryptography.AsymmetricAlgorithm? PrivateKey { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } + public byte[] RawData { get { throw null; } } + public System.ReadOnlyMemory RawDataMemory { get { throw null; } } + public string SerialNumber { get { throw null; } } + public System.Security.Cryptography.Oid SignatureAlgorithm { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } } + public string Thumbprint { get { throw null; } } + public int Version { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.ECDiffieHellman privateKey) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem, System.ReadOnlySpan password) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath, System.ReadOnlySpan password, string? keyPemFilePath = null) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPemFile(string certPemFilePath, string? keyPemFilePath = null) { throw null; } + public string ExportCertificatePem() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(byte[] rawData) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.ReadOnlySpan rawData) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(string fileName) { throw null; } + public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPrivateKey() { throw null; } + public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPublicKey() { throw null; } + public string GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType nameType, bool forIssuer) { throw null; } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(byte[] rawData) { } + [System.CLSCompliantAttribute(false)] + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(byte[] rawData, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(string fileName) { } + [System.CLSCompliantAttribute(false)] + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(string fileName, System.Security.SecureString? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + [System.ObsoleteAttribute("X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.", DiagnosticId = "SYSLIB0026", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + public override void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) { } + public override void Reset() { } + public override string ToString() { throw null; } + public override string ToString(bool verbose) { throw null; } + public bool TryExportCertificatePem(System.Span destination, out int charsWritten) { throw null; } + public bool Verify() { throw null; } + } + public partial class X509Certificate2Collection : System.Security.Cryptography.X509Certificates.X509CertificateCollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable + { + public X509Certificate2Collection() { } + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } + public new System.Security.Cryptography.X509Certificates.X509Certificate2 this[int index] { get { throw null; } set { } } + public int Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } + public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public byte[]? Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) { throw null; } + public byte[]? Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string? password) { throw null; } + public string ExportCertificatePems() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public string ExportPkcs7Pem() { throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Find(System.Security.Cryptography.X509Certificates.X509FindType findType, object findValue, bool validOnly) { throw null; } + public new System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator GetEnumerator() { throw null; } + public void Import(byte[] rawData) { } + public void Import(byte[] rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + public void Import(System.ReadOnlySpan rawData) { } + public void Import(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + public void Import(System.ReadOnlySpan rawData, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + public void Import(string fileName) { } + public void Import(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + public void Import(string fileName, string? password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet) { } + public void ImportFromPem(System.ReadOnlySpan certPem) { } + public void ImportFromPemFile(string certPemFilePath) { } + public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) { } + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } + public bool TryExportCertificatePems(System.Span destination, out int charsWritten) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public bool TryExportPkcs7Pem(System.Span destination, out int charsWritten) { throw null; } + } + public sealed partial class X509Certificate2Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + internal X509Certificate2Enumerator() { } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Current { get { throw null; } } + object System.Collections.IEnumerator.Current { get { throw null; } } + public bool MoveNext() { throw null; } + public void Reset() { } + bool System.Collections.IEnumerator.MoveNext() { throw null; } + void System.Collections.IEnumerator.Reset() { } + void System.IDisposable.Dispose() { } + } + public partial class X509CertificateCollection : System.Collections.CollectionBase + { + public X509CertificateCollection() { } + public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) { } + public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509Certificate[] value) { } + public System.Security.Cryptography.X509Certificates.X509Certificate this[int index] { get { throw null; } set { } } + public int Add(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } + public void AddRange(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) { } + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate[] value) { } + public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } + public void CopyTo(System.Security.Cryptography.X509Certificates.X509Certificate[] array, int index) { } + public new System.Security.Cryptography.X509Certificates.X509CertificateCollection.X509CertificateEnumerator GetEnumerator() { throw null; } + public override int GetHashCode() { throw null; } + public int IndexOf(System.Security.Cryptography.X509Certificates.X509Certificate value) { throw null; } + public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate value) { } + protected override void OnValidate(object value) { } + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate value) { } + public partial class X509CertificateEnumerator : System.Collections.IEnumerator + { + public X509CertificateEnumerator(System.Security.Cryptography.X509Certificates.X509CertificateCollection mappings) { } + public System.Security.Cryptography.X509Certificates.X509Certificate Current { get { throw null; } } + object System.Collections.IEnumerator.Current { get { throw null; } } + public bool MoveNext() { throw null; } + public void Reset() { } + bool System.Collections.IEnumerator.MoveNext() { throw null; } + void System.Collections.IEnumerator.Reset() { } + } + } + public partial class X509Chain : System.IDisposable + { + public X509Chain() { } + public X509Chain(bool useMachineContext) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public X509Chain(System.IntPtr chainContext) { } + public System.IntPtr ChainContext { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509ChainElementCollection ChainElements { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509ChainPolicy ChainPolicy { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainStatus { get { throw null; } } + public Microsoft.Win32.SafeHandles.SafeX509ChainHandle? SafeHandle { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public bool Build(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; } + public static System.Security.Cryptography.X509Certificates.X509Chain Create() { throw null; } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + public void Reset() { } + } + public partial class X509ChainElement + { + internal X509ChainElement() { } + public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainElementStatus { get { throw null; } } + public string Information { get { throw null; } } + } + public sealed partial class X509ChainElementCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable + { + internal X509ChainElementCollection() { } + public int Count { get { throw null; } } + public bool IsSynchronized { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509ChainElement this[int index] { get { throw null; } } + public object SyncRoot { get { throw null; } } + public void CopyTo(System.Security.Cryptography.X509Certificates.X509ChainElement[] array, int index) { } + public System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } + void System.Collections.ICollection.CopyTo(System.Array array, int index) { } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + } + public sealed partial class X509ChainElementEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + internal X509ChainElementEnumerator() { } + public System.Security.Cryptography.X509Certificates.X509ChainElement Current { get { throw null; } } + object System.Collections.IEnumerator.Current { get { throw null; } } + public bool MoveNext() { throw null; } + public void Reset() { } + void System.IDisposable.Dispose() { } + } + public sealed partial class X509ChainPolicy + { + public X509ChainPolicy() { } + public System.Security.Cryptography.OidCollection ApplicationPolicy { get { throw null; } } + public System.Security.Cryptography.OidCollection CertificatePolicy { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection CustomTrustStore { get { throw null; } } + public bool DisableCertificateDownloads { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection ExtraStore { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509RevocationFlag RevocationFlag { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.X509ChainTrustMode TrustMode { get { throw null; } set { } } + public System.TimeSpan UrlRetrievalTimeout { get { throw null; } set { } } + public System.Security.Cryptography.X509Certificates.X509VerificationFlags VerificationFlags { get { throw null; } set { } } + public System.DateTime VerificationTime { get { throw null; } set { } } + public void Reset() { } + } + public partial struct X509ChainStatus + { + private object _dummy; + private int _dummyPrimitive; + public System.Security.Cryptography.X509Certificates.X509ChainStatusFlags Status { readonly get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] + public string StatusInformation { get { throw null; } set { } } + } + [System.FlagsAttribute] + public enum X509ChainStatusFlags + { + NoError = 0, + NotTimeValid = 1, + NotTimeNested = 2, + Revoked = 4, + NotSignatureValid = 8, + NotValidForUsage = 16, + UntrustedRoot = 32, + RevocationStatusUnknown = 64, + Cyclic = 128, + InvalidExtension = 256, + InvalidPolicyConstraints = 512, + InvalidBasicConstraints = 1024, + InvalidNameConstraints = 2048, + HasNotSupportedNameConstraint = 4096, + HasNotDefinedNameConstraint = 8192, + HasNotPermittedNameConstraint = 16384, + HasExcludedNameConstraint = 32768, + PartialChain = 65536, + CtlNotTimeValid = 131072, + CtlNotSignatureValid = 262144, + CtlNotValidForUsage = 524288, + HasWeakSignature = 1048576, + OfflineRevocation = 16777216, + NoIssuanceChainPolicy = 33554432, + ExplicitDistrust = 67108864, + HasNotSupportedCriticalExtension = 134217728, + } + public enum X509ChainTrustMode + { + System = 0, + CustomRootTrust = 1, + } + public enum X509ContentType + { + Unknown = 0, + Cert = 1, + SerializedCert = 2, + Pfx = 3, + Pkcs12 = 3, + SerializedStore = 4, + Pkcs7 = 5, + Authenticode = 6, + } + public sealed partial class X509EnhancedKeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public X509EnhancedKeyUsageExtension() { } + public X509EnhancedKeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedEnhancedKeyUsages, bool critical) { } + public X509EnhancedKeyUsageExtension(System.Security.Cryptography.OidCollection enhancedKeyUsages, bool critical) { } + public System.Security.Cryptography.OidCollection EnhancedKeyUsages { get { throw null; } } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + } + public partial class X509Extension : System.Security.Cryptography.AsnEncodedData + { + protected X509Extension() { } + public X509Extension(System.Security.Cryptography.AsnEncodedData encodedExtension, bool critical) { } + public X509Extension(System.Security.Cryptography.Oid oid, byte[] rawData, bool critical) { } + public X509Extension(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData, bool critical) { } + public X509Extension(string oid, byte[] rawData, bool critical) { } + public X509Extension(string oid, System.ReadOnlySpan rawData, bool critical) { } + public bool Critical { get { throw null; } set { } } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + } + public sealed partial class X509ExtensionCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable + { + public X509ExtensionCollection() { } + public int Count { get { throw null; } } + public bool IsSynchronized { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509Extension this[int index] { get { throw null; } } + public System.Security.Cryptography.X509Certificates.X509Extension? this[string oid] { get { throw null; } } + public object SyncRoot { get { throw null; } } + public int Add(System.Security.Cryptography.X509Certificates.X509Extension extension) { throw null; } + public void CopyTo(System.Security.Cryptography.X509Certificates.X509Extension[] array, int index) { } + public System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } + void System.Collections.ICollection.CopyTo(System.Array array, int index) { } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + } + public sealed partial class X509ExtensionEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + internal X509ExtensionEnumerator() { } + public System.Security.Cryptography.X509Certificates.X509Extension Current { get { throw null; } } + object System.Collections.IEnumerator.Current { get { throw null; } } + public bool MoveNext() { throw null; } + public void Reset() { } + void System.IDisposable.Dispose() { } + } + public enum X509FindType + { + FindByThumbprint = 0, + FindBySubjectName = 1, + FindBySubjectDistinguishedName = 2, + FindByIssuerName = 3, + FindByIssuerDistinguishedName = 4, + FindBySerialNumber = 5, + FindByTimeValid = 6, + FindByTimeNotYetValid = 7, + FindByTimeExpired = 8, + FindByTemplateName = 9, + FindByApplicationPolicy = 10, + FindByCertificatePolicy = 11, + FindByExtension = 12, + FindByKeyUsage = 13, + FindBySubjectKeyIdentifier = 14, + } + public enum X509IncludeOption + { + None = 0, + ExcludeRoot = 1, + EndCertOnly = 2, + WholeChain = 3, + } + [System.FlagsAttribute] + public enum X509KeyStorageFlags + { + DefaultKeySet = 0, + UserKeySet = 1, + MachineKeySet = 2, + Exportable = 4, + UserProtected = 8, + PersistKeySet = 16, + EphemeralKeySet = 32, + } + public sealed partial class X509KeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public X509KeyUsageExtension() { } + public X509KeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedKeyUsage, bool critical) { } + public X509KeyUsageExtension(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags keyUsages, bool critical) { } + public System.Security.Cryptography.X509Certificates.X509KeyUsageFlags KeyUsages { get { throw null; } } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + } + [System.FlagsAttribute] + public enum X509KeyUsageFlags + { + None = 0, + EncipherOnly = 1, + CrlSign = 2, + KeyCertSign = 4, + KeyAgreement = 8, + DataEncipherment = 16, + KeyEncipherment = 32, + NonRepudiation = 64, + DigitalSignature = 128, + DecipherOnly = 32768, + } + public enum X509NameType + { + SimpleName = 0, + EmailName = 1, + UpnName = 2, + DnsName = 3, + DnsFromAlternativeName = 4, + UrlName = 5, + } + public enum X509RevocationFlag + { + EndCertificateOnly = 0, + EntireChain = 1, + ExcludeRoot = 2, + } + public enum X509RevocationMode + { + NoCheck = 0, + Online = 1, + Offline = 2, + } + public abstract partial class X509SignatureGenerator + { + protected X509SignatureGenerator() { } + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } + protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey(); + public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) { throw null; } + public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForRSA(System.Security.Cryptography.RSA key, System.Security.Cryptography.RSASignaturePadding signaturePadding) { throw null; } + public abstract byte[] GetSignatureAlgorithmIdentifier(System.Security.Cryptography.HashAlgorithmName hashAlgorithm); + public abstract byte[] SignData(byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm); + } + public sealed partial class X509Store : System.IDisposable + { + public X509Store() { } + public X509Store(System.IntPtr storeHandle) { } + public X509Store(System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName) { } + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { } + public X509Store(string storeName) { } + public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { } + public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get { throw null; } } + public bool IsOpen { get { throw null; } } + public System.Security.Cryptography.X509Certificates.StoreLocation Location { get { throw null; } } + public string? Name { get { throw null; } } + public System.IntPtr StoreHandle { get { throw null; } } + public void Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } + public void Close() { } + public void Dispose() { } + public void Open(System.Security.Cryptography.X509Certificates.OpenFlags flags) { } + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { } + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { } + } + public sealed partial class X509SubjectKeyIdentifierExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public X509SubjectKeyIdentifierExtension() { } + public X509SubjectKeyIdentifierExtension(byte[] subjectKeyIdentifier, bool critical) { } + public X509SubjectKeyIdentifierExtension(System.ReadOnlySpan subjectKeyIdentifier, bool critical) { } + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.AsnEncodedData encodedSubjectKeyIdentifier, bool critical) { } + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, bool critical) { } + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { } + public X509SubjectKeyIdentifierExtension(string subjectKeyIdentifier, bool critical) { } + public string? SubjectKeyIdentifier { get { throw null; } } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + } + public enum X509SubjectKeyIdentifierHashAlgorithm + { + Sha1 = 0, + ShortSha1 = 1, + CapiSha1 = 2, + } + [System.FlagsAttribute] + public enum X509VerificationFlags + { + NoFlag = 0, + IgnoreNotTimeValid = 1, + IgnoreCtlNotTimeValid = 2, + IgnoreNotTimeNested = 4, + IgnoreInvalidBasicConstraints = 8, + AllowUnknownCertificateAuthority = 16, + IgnoreWrongUsage = 32, + IgnoreInvalidName = 64, + IgnoreInvalidPolicy = 128, + IgnoreEndRevocationUnknown = 256, + IgnoreCtlSignerRevocationUnknown = 512, + IgnoreCertificateAuthorityRevocationUnknown = 1024, + IgnoreRootRevocationUnknown = 2048, + AllFlags = 4095, + } } diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.csproj index 3baaa77d1f515..0b9ddef821dad 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.csproj @@ -2,11 +2,15 @@ $(NetCoreAppCurrent) enable + $(NoWarn);SYSLIB0026 + + + diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs rename to src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs index 28508857bc2b8..9808e723e2a0b 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs +++ b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/NCryptSafeHandles.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using ErrorCode = Interop.NCrypt.ErrorCode; @@ -65,11 +66,12 @@ private enum OwnershipState private SafeHandle? _parentHandle; + [SupportedOSPlatform("windows")] protected SafeNCryptHandle() : base(true) { - return; } + [SupportedOSPlatform("windows")] protected SafeNCryptHandle(IntPtr handle, SafeHandle parentHandle) : base(true) { @@ -346,10 +348,12 @@ internal bool ReleaseNativeWithNCryptFreeObject() /// public sealed class SafeNCryptKeyHandle : SafeNCryptHandle { + [SupportedOSPlatform("windows")] public SafeNCryptKeyHandle() { } + [SupportedOSPlatform("windows")] public SafeNCryptKeyHandle(IntPtr handle, SafeHandle parentHandle) : base(handle, parentHandle) { @@ -371,6 +375,9 @@ protected override bool ReleaseNativeHandle() /// public sealed class SafeNCryptProviderHandle : SafeNCryptHandle { + [SupportedOSPlatform("windows")] + public SafeNCryptProviderHandle() { } + internal SafeNCryptProviderHandle Duplicate() { return Duplicate(); @@ -396,6 +403,9 @@ protected override bool ReleaseNativeHandle() /// public sealed class SafeNCryptSecretHandle : SafeNCryptHandle { + [SupportedOSPlatform("windows")] + public SafeNCryptSecretHandle() { } + protected override bool ReleaseNativeHandle() { return ReleaseNativeWithNCryptFreeObject(); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs rename to src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index 84a24a8fc9ef4..02431e49a9bd4 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -60,15 +60,45 @@ Error occurred during a cryptographic operation. + + Array may not be empty or null. + + + String cannot be empty or null. + + + The '{0}' string cannot be empty or null. + + + Illegal enum value: {0}. + + + Invalid handle. + + + Invalid type. + Only single dimensional arrays are supported for the requested action. Destination is too short. + + The method cannot be called with an invalid or closed SafeHandle. + + + Value of flags is invalid. + + + The value of 'nameType' is invalid. + Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. + + The OID value was invalid. + Range of random number does not contain at least one possibility. @@ -111,6 +141,18 @@ Positive number required. + + An empty custom trust store is not supported on this platform. + + + The certificate has invalid policy. + + + The certificate chain is incomplete. + + + The certificate's revocation status could not be determined. + Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.) @@ -126,24 +168,75 @@ Algorithms added to CryptoConfig must be accessible from outside their assembly. + + Keys used with the DSACng algorithm must have an algorithm group of DSA. + The keys from both parties must be the same size to generate a secret agreement. Keys used with the ECDiffieHellmanCng algorithm must have an algorithm group of ECDiffieHellman. + + Keys used with the ECDsaCng algorithm must have an algorithm group of ECDsa. + + + Keys used with the RSACng algorithm must have an algorithm group of RSA. + The computed authentication tag did not match the input authentication tag. The provided value of {0} bytes does not match the expected size of {1} bytes for the algorithm ({2}). + + '{0}' requires Windows Cryptographic API (CAPI), which is not available on this platform. + + + The certificate already has an associated private key. + + + The issuer certificate public key algorithm ({0}) does not match the value for this certificate request ({1}), use the X509SignatureGenerator overload. + + + The issuer certificate does not have a Basic Constraints extension. + + + The provided notBefore value is later than the notAfter value. + + + An X509Extension with OID '{0}' has already been specified. + + + The issuer certificate does not have an appropriate value for the Basic Constraints extension. + + + The issuer certificate's Key Usage extension is present but does not contain the KeyCertSign flag. + + + The provided issuer certificate does not have an associated private key. + + + This method cannot be used since no signing key was provided via a constructor, use an overload accepting an X509SignatureGenerator instead. + + + The requested notAfter value ({0}) is later than issuerCertificate.NotAfter ({1}). + + + The requested notBefore value ({0}) is earlier than issuerCertificate.NotBefore ({1}). + + + The issuer certificate uses an RSA key but no RSASignaturePadding was provided to a constructor. If one cannot be provided, use the X509SignatureGenerator overload. + The specified feedback size '{0}' for CipherMode '{1}' is not supported. The specified CipherMode '{0}' is not supported. + + This key is for algorithm '{0}'. Expected '{1}'. + Encoded OID length is too large (greater than 0x7f bytes). @@ -153,9 +246,18 @@ Object contains only the public half of a key pair. A private key must also be provided. + + The requested key container was not found. + + + The specified cryptographic service provider (CSP) does not support this key algorithm: {0}. + The specified curve '{0}' or its parameters are not valid for this platform. + + Custom trust certificates were provided while in System trust mode. + This platform does not allow the automatic selection of an algorithm. @@ -180,6 +282,9 @@ The current platform does not support the specified feedback size. + + Unable to get file status. + No hash algorithm has been associated with this formatter object, assign one via the SetHashAlgorithm method. @@ -201,11 +306,17 @@ Specified cipher mode is not valid for this algorithm. + + The chain context handle is invalid. + The specified key parameters are not valid. Q.X and Q.Y, or D, must be specified. Q.X, Q.Y must be the same length. If D is specified it must be the same length as Q.X and Q.Y if also specified for named curves or the same length as Order for explicit curves. - The specified Oid is not valid. The Oid.FriendlyName or Oid.Value property must be set. + The specified Oid ({0}) is not valid. The Oid.FriendlyName or Oid.Value property must be set. + + + Invalid directory permissions. The directory '{0}' must be readable, writable and executable by the owner. The specified DSA parameters are not valid; P, G and Y must be the same length (the key size). @@ -228,6 +339,9 @@ The specified DSA parameters are not valid; Seed, if present, must be 20 bytes long for keys shorter than 1024 bits. + + Length of the DSA signature was not 40 bytes. + The specified Characteristic2 curve parameters are not valid. Polynomial, A, B, G.X, G.Y, and Order are required. A, B, G.X, G.Y must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Cofactor is required. Seed and Hash are optional. Other parameters are not allowed. @@ -240,12 +354,21 @@ Specified feedback size is not valid for this algorithm. + + Invalid file permissions. The file '{0}' must readable and writable by the current owner and by no one else, and the permissions could not be changed to meet that criteria. + Input string does not contain a valid encoding of the '{0}' '{1}' parameter. + + {0} is an invalid handle. + The specified OID ({0}) does not represent a known hash algorithm. + + {0} algorithm hash size is {1} bytes. + Specified initialization vector (IV) does not match the block size for this algorithm. @@ -264,18 +387,33 @@ Object identifier (OID) is unknown. + + This operation is not supported for this class. + Padding is invalid and cannot be removed. Specified padding mode is not valid for this algorithm. - - This operation is not supported for this class. + + The store handle is invalid. The specified tag is not a valid size for this algorithm. + + A null or disposed certificate was present in CustomTrustStore. + + + The string contains a character not in the 7 bit ASCII character set. + + + The string contains an invalid X500 name attribute key, oid, value or delimiter. + + + Key Blob not in expected format. + The key is too small for the requested operation. @@ -321,12 +459,39 @@ Output keying material length can be at most {0} bytes (255 * hash length). + + The CNG key handle being opened was detected to be ephemeral, but the EphemeralKey open option was not specified. + Cannot open an invalid handle. + + The owner of '{0}' is not the current user. + The input data is not a complete block. + + Algorithm is unavailable or is not supported for this operation. + + + The Initialization vector should have the same length as the algorithm block size in bytes. + + + Requested number of bytes exceeds the maximum. + + + Value of '{0}' cannot be changed after the bytes have been retrieved. + + + A certificate referenced a private key which was already referenced, or could not be loaded. + + + The certificate data cannot be read with the provided password, the password may be incorrect. + + + The provided PFX data contains no certificates. + The EncryptedPrivateKeyInfo structure was decoded but was not successfully interpreted, the password may be incorrect. @@ -336,6 +501,12 @@ The specified plaintext size is too large. + + The provided key does not match the public key for this certificate. + + + The provided key does not match the public key algorithm for this certificate. + The pseudo-random key length must be at least {0} bytes. @@ -363,15 +534,42 @@ The TLS key derivation function requires a seed value of exactly 64 bytes. + + The TLS key derivation function requires both the label and seed properties to be set. + CNG provider unexpectedly terminated encryption or decryption prematurely. + + The Disallowed store is not supported on this platform, but already has data. All files under '{0}' must be removed. + + + Unix LocalMachine X509Stores are read-only for all users. + + + Unix LocalMachine X509Store is limited to the Root and CertificateAuthority stores. + + + The Disallowed store is not supported on this platform. + + + The {0} value cannot be set on Unix. + + + X509ContentType.SerializedCert and X509ContentType.SerializedStore are not supported on Unix. + The algorithm identified by '{0}' is unknown, not valid for the requested usage, or was not handled. + + The certificate content type could not be determined. + '{0}' is not a known hash algorithm. + + '{0}' is not a known key algorithm. + Unknown padding mode used. @@ -384,15 +582,117 @@ The specified PaddingMode is not supported. + + Certificate '{0}' is corrupted. + + + The certificate export operation failed. + + + The parameter should be an X509Extension. + + + Invalid content type. + + + Invalid find type. + + + Invalid find value. + + + The flags '{0}' may not be specified together. + + + This platform does not support loading with EphemeralKeySet. Remove the flag to allow keys to be temporarily created on disk. + + + The key contents do not contain a PEM, the content is malformed, or the key does not match the certificate. + + + The certificate contents do not contain a PEM with a CERTIFICATE label, or the content is malformed. + + + Cannot find the original signer. + + + PKCS#7 certificate format is not supported on this platform. + + + The PKCS#12 Exportable flag is not supported on this platform. + + + The PKCS#12 PersistKeySet flag is not supported on this platform. + + + Root certificate store is not supported on this platform. + + + The X509 certificate could not be added to the store. + + + The platform does not have a definition for an X509 certificate store named '{0}' with a StoreLocation of '{1}', and does not support creating it. + + + Adding a DSA private key to the store is not supported on this platform. + + + Failed to enumerate certificates from the store. + + + The X509 certificate could not be added to the store because all candidate file names were in use. + + + The specified X509 certificate store does not exist. + + + The X509 certificate store has not been opened. + + + The X509 certificate store is read-only. + + + The X509 certificate could not be removed from the store. + + + Removing the requested certificate would modify admin trust settings, and has been denied. + + + Removing the requested certificate would modify user trust settings, and has been denied. + + + CryptSetKeyParam failed with error code {0}. + + + CSPParameters cannot be null + Setting the hashname after it's already been set is not supported on this platform. + + Enumeration has not started. Call MoveNext. + The algorithm's implementation is incorrect. The algorithm's block size is not supported. + + CryptoApi ECDsa keys are not supported. + + + CryptoApi ECDiffieHellman keys are not supported. + + + X509Certificate is immutable on this platform. Use the equivalent constructor instead. + + + The certificate key algorithm is not supported. + + + The X509 Basic Constraints extension with OID 2.5.29.10 is not supported. + Method not supported. @@ -408,7 +708,28 @@ Stream does not support writing. + + The home directory of the current user could not be determined. + + + Windows Cryptography Next Generation (CNG) is not supported on this platform. + + + OpenSSL is not supported on this platform. + + + Access is denied. + + + The {0} value was invalid. + System.Security.Cryptography is not supported on this platform. + + System.Security.Cryptography.X509Certificates is not supported on this platform. + + + Unknown error. + diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index 9a268d9a83d9a..073513a0de966 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -8,6 +8,7 @@ SR.SystemSecurityCryptography_PlatformNotSupported + $(NoWarn);SYSLIB0026 true @@ -27,6 +28,8 @@ Link="Common\Internal\Cryptography\HashProvider.cs" /> + + + Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs Common\System\Security\Cryptography\Asn1\AttributeAsn.xml + + Common\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs + Common\System\Security\Cryptography\Asn1\AttributeAsn.xml + Common\System\Security\Cryptography\Asn1\CurveAsn.xml @@ -72,6 +83,13 @@ Common\System\Security\Cryptography\Asn1\CurveAsn.xml.cs Common\System\Security\Cryptography\Asn1\CurveAsn.xml + + Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml + + + Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml + Common\System\Security\Cryptography\Asn1\DssParms.xml @@ -93,6 +111,13 @@ Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml.cs Common\System\Security\Cryptography\Asn1\ECPrivateKey.xml + + Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml + + + Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml.cs + Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml + Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml @@ -107,6 +132,20 @@ Common\System\Security\Cryptography\Asn1\FieldID.xml.cs Common\System\Security\Cryptography\Asn1\FieldID.xml + + Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml + + + Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml.cs + Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml + + + Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml + + + Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml.cs + Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml + Common\System\Security\Cryptography\Asn1\PBEParameter.xml @@ -142,6 +181,13 @@ Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml.cs Common\System\Security\Cryptography\Asn1\PrivateKeyInfoAsn.xml + + Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml + + + Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml.cs + Common\System\Security\Cryptography\Asn1\PssParamsAsn.xml + Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml @@ -181,6 +227,17 @@ Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml.cs Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml + + Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml + + + Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml.cs + Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml + + + Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.manual.cs + Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml + + + @@ -234,6 +293,21 @@ + + + + + + + + + + + + + + + @@ -241,6 +315,8 @@ + + @@ -256,10 +332,12 @@ + + @@ -275,17 +353,22 @@ + + + + + @@ -300,6 +383,7 @@ + @@ -314,47 +398,139 @@ + + + + - - - - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml - - - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + System\Security\Cryptography\X509Certificates\Asn1\BasicConstraintsAsn.xml - - Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\EdiPartyNameAsn.xml + + + System\Security\Cryptography\X509Certificates\Asn1\CertificateAsn.xml - - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\GeneralNameAsn.xml + + + System\Security\Cryptography\X509Certificates\Asn1\CertificationRequestAsn.xml - - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml - - - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml.cs - Common\System\Security\Cryptography\Asn1\OtherNameAsn.xml + + + System\Security\Cryptography\X509Certificates\Asn1\CertificationRequestInfoAsn.xml + + + + + System\Security\Cryptography\X509Certificates\Asn1\TbsCertificateAsn.xml + + + + + System\Security\Cryptography\X509Certificates\Asn1\TimeAsn.xml + + + + + System\Security\Cryptography\X509Certificates\Asn1\ValidityAsn.xml + + + + + System\Security\Cryptography\X509Certificates\Asn1\AccessDescriptionAsn.xml + + + + System\Security\Cryptography\X509Certificates\Asn1\CertificatePolicyMappingAsn.xml + + + + System\Security\Cryptography\X509Certificates\Asn1\CertificateTemplateAsn.xml + + + + System\Security\Cryptography\X509Certificates\Asn1\PolicyConstraintsAsn.xml + + + + System\Security\Cryptography\X509Certificates\Asn1\PolicyInformationAsn.xml - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + System\Security\Cryptography\X509Certificates\Asn1\DistributionPointAsn.xml + + + + System\Security\Cryptography\X509Certificates\Asn1\DistributionPointNameAsn.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + @@ -555,22 +922,120 @@ Link="Common\System\Security\Cryptography\ECDsaAndroid.cs" /> + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Link="Common\System\Security\Cryptography\ECDiffieHellmanCng.cs" /> + Link="Common\System\Security\Cryptography\ECDiffieHellmanCng.ImportExport.cs" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -854,6 +1823,10 @@ + + + + diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/AesCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCng.Windows.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/AesCng.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCng.Windows.cs index 297cd51168888..19046e7bdf328 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/AesCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCng.Windows.cs @@ -8,6 +8,7 @@ // that each of these derive from a different class, it can't be helped. // +using System.Runtime.Versioning; using Internal.Cryptography; using Internal.NativeCrypto; @@ -15,21 +16,25 @@ namespace System.Security.Cryptography { public sealed class AesCng : Aes, ICngSymmetricAlgorithm { + [SupportedOSPlatform("windows")] public AesCng() { _core = new CngSymmetricAlgorithmCore(this); } + [SupportedOSPlatform("windows")] public AesCng(string keyName) : this(keyName, CngProvider.MicrosoftSoftwareKeyStorageProvider) { } + [SupportedOSPlatform("windows")] public AesCng(string keyName, CngProvider provider) : this(keyName, provider, CngKeyOpenOptions.None) { } + [SupportedOSPlatform("windows")] public AesCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) { _core = new CngSymmetricAlgorithmCore(this, keyName, provider, openOptions); @@ -244,7 +249,7 @@ SafeAlgorithmHandle ICngSymmetricAlgorithm.GetEphemeralModeHandle(CipherMode mod string ICngSymmetricAlgorithm.GetNCryptAlgorithmIdentifier() { - return Interop.NCrypt.NCRYPT_AES_ALGORITHM; + return Cng.BCRYPT_AES_ALGORITHM; } byte[] ICngSymmetricAlgorithm.PreprocessKey(byte[] key) diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/AesCryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/AesCryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs index c879a4f546087..2e081e8a06493 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/AesCryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.Versioning; namespace System.Security.Cryptography { @@ -11,6 +12,7 @@ public sealed class AesCryptoServiceProvider : Aes { private readonly Aes _impl; + [UnsupportedOSPlatform("browser")] public AesCryptoServiceProvider() { // This class wraps Aes diff --git a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherCsp.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherCsp.cs index 5d97658ab644c..0ecad1312e15f 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherCsp.cs @@ -1,20 +1,17 @@ // 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.Diagnostics; -using System.Security.Cryptography; -using Internal.NativeCrypto; -using Microsoft.Win32.SafeHandles; -using static Internal.NativeCrypto.CapiHelper; +using Internal.Cryptography; +using static System.Security.Cryptography.CapiHelper; -namespace Internal.Cryptography +namespace System.Security.Cryptography { internal sealed class BasicSymmetricCipherCsp : BasicSymmetricCipher { private readonly bool _encrypting; private SafeProvHandle _hProvider; - private SafeKeyHandle _hKey; + private SafeCapiKeyHandle _hKey; public BasicSymmetricCipherCsp(int algId, CipherMode cipherMode, int blockSizeInBytes, byte[] key, bool addNoSaltFlag, byte[]? iv, bool encrypting, int feedbackSize, int paddingSizeInBytes) : base(cipherMode.GetCipherIv(iv), blockSizeInBytes, paddingSizeInBytes) @@ -46,7 +43,7 @@ protected override void Dispose(bool disposing) { if (disposing) { - SafeKeyHandle hKey = _hKey; + SafeCapiKeyHandle hKey = _hKey; _hKey = null!; if (hKey != null) { @@ -110,9 +107,9 @@ private int Transform(ReadOnlySpan input, Span output, bool isFinal) return numBytesWritten; } - private static SafeKeyHandle ImportCspBlob(SafeProvHandle safeProvHandle, int algId, byte[] rawKey, bool addNoSaltFlag) + private static SafeCapiKeyHandle ImportCspBlob(SafeProvHandle safeProvHandle, int algId, byte[] rawKey, bool addNoSaltFlag) { - SafeKeyHandle safeKeyHandle; + SafeCapiKeyHandle safeKeyHandle; byte[] keyBlob = ToPlainTextKeyBlob(algId, rawKey); ImportKeyBlob(safeProvHandle, (CspProviderFlags)0, addNoSaltFlag, keyBlob, out safeKeyHandle); // Note if plain text import fails, .NET Framework falls back to "ExponentOfOneImport" which is not handled here diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherNCrypt.cs similarity index 85% rename from src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherNCrypt.cs index 1e38c44fef8fb..ffe1c8fa13e67 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipherNCrypt.cs @@ -1,17 +1,16 @@ // 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.Security.Cryptography; using System.Text; +using Internal.Cryptography; +using Internal.NativeCrypto; using Microsoft.Win32.SafeHandles; using ErrorCode = Interop.NCrypt.ErrorCode; using AsymmetricPaddingMode = Interop.NCrypt.AsymmetricPaddingMode; -namespace Internal.Cryptography +namespace System.Security.Cryptography { internal sealed class BasicSymmetricCipherNCrypt : BasicSymmetricCipher { @@ -104,7 +103,7 @@ private void Reset() { if (IV != null) { - CngProperty prop = new CngProperty(Interop.NCrypt.NCRYPT_INITIALIZATION_VECTOR, IV, CngPropertyOptions.None); + CngProperty prop = new CngProperty(KeyPropertyName.InitializationVector, IV, CngPropertyOptions.None); _cngKey!.SetProperty(prop); } } @@ -113,10 +112,10 @@ private void Reset() private readonly bool _encrypting; private static readonly CngProperty s_ECBMode = - new CngProperty(Interop.NCrypt.NCRYPT_CHAINING_MODE_PROPERTY, Encoding.Unicode.GetBytes(Interop.BCrypt.BCRYPT_CHAIN_MODE_ECB + "\0"), CngPropertyOptions.None); + new CngProperty(KeyPropertyName.ChainingMode, Encoding.Unicode.GetBytes(Cng.BCRYPT_CHAIN_MODE_ECB + "\0"), CngPropertyOptions.None); private static readonly CngProperty s_CBCMode = - new CngProperty(Interop.NCrypt.NCRYPT_CHAINING_MODE_PROPERTY, Encoding.Unicode.GetBytes(Interop.BCrypt.BCRYPT_CHAIN_MODE_CBC + "\0"), CngPropertyOptions.None); + new CngProperty(KeyPropertyName.ChainingMode, Encoding.Unicode.GetBytes(Cng.BCRYPT_CHAIN_MODE_CBC + "\0"), CngPropertyOptions.None); private static readonly CngProperty s_CFBMode = - new CngProperty(Interop.NCrypt.NCRYPT_CHAINING_MODE_PROPERTY, Encoding.Unicode.GetBytes(Interop.BCrypt.BCRYPT_CHAIN_MODE_CFB + "\0"), CngPropertyOptions.None); + new CngProperty(KeyPropertyName.ChainingMode, Encoding.Unicode.GetBytes(Cng.BCRYPT_CHAIN_MODE_CFB + "\0"), CngPropertyOptions.None); } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Browser.cs new file mode 100644 index 0000000000000..43c983085e1bd --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Browser.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + internal static partial class CapiHelper + { + // Return PROV_RSA_AES, in case any compat case pops up. + internal const int DefaultRsaProviderType = 24; + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs index 67a22cd75d116..2a4b6f1480836 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Shared.cs @@ -1,12 +1,10 @@ // 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.Diagnostics; using System.IO; -using System.Security.Cryptography; -namespace Internal.NativeCrypto +namespace System.Security.Cryptography { internal static partial class CapiHelper { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs index 09c9f4c6988e2..9cef8555e573a 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.DSA.Windows.cs @@ -1,11 +1,7 @@ // 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.Security.Cryptography; -using Microsoft.Win32.SafeHandles; - -namespace Internal.NativeCrypto +namespace System.Security.Cryptography { internal static partial class CapiHelper { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Shared.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Shared.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Shared.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Shared.cs index a75758092ef17..f6f9648f35aba 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Shared.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Shared.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using System; using System.IO; -using System.Security.Cryptography; -namespace Internal.NativeCrypto +namespace System.Security.Cryptography { internal static partial class CapiHelper { @@ -262,5 +260,19 @@ private static byte[] ReadReversed(this BinaryReader br, int count) Array.Reverse(data); return data; } + + internal static byte[]? TrimLargeIV(byte[]? currentIV, int blockSizeInBits) + { + int blockSizeBytes = checked((blockSizeInBits + 7) / 8); + + if (currentIV?.Length > blockSizeBytes) + { + byte[] tmp = new byte[blockSizeBytes]; + Buffer.BlockCopy(currentIV, 0, tmp, 0, tmp.Length); + return tmp; + } + + return currentIV; + } } } diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs index 6da826133d20d..27cbf46b8f2a1 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.SymmetricKey.cs @@ -3,7 +3,7 @@ using System.IO; -namespace Internal.NativeCrypto +namespace System.Security.Cryptography { internal static partial class CapiHelper { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Unix/HashAlgorithmNames.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs similarity index 76% rename from src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Unix/HashAlgorithmNames.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs index 9645cee8c6120..8fcf4603e9578 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/Unix/HashAlgorithmNames.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs @@ -1,18 +1,15 @@ // 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.Security.Cryptography; - -namespace Internal.Cryptography +namespace System.Security.Cryptography { - internal static class HashAlgorithmNames + internal static partial class CapiHelper { - public const string MD5 = "MD5"; - public const string SHA1 = "SHA1"; - public const string SHA256 = "SHA256"; - public const string SHA384 = "SHA384"; - public const string SHA512 = "SHA512"; + internal const string MD5 = "MD5"; + internal const string SHA1 = "SHA1"; + internal const string SHA256 = "SHA256"; + internal const string SHA384 = "SHA384"; + internal const string SHA512 = "SHA512"; private const string OID_MD5 = "1.2.840.113549.2.5"; private const string OID_SHA1 = "1.3.14.3.2.26"; @@ -21,7 +18,7 @@ internal static class HashAlgorithmNames private const string OID_SHA512 = "2.16.840.1.101.3.4.2.3"; // For backwards compat with CapiHelper.ObjToHashAlgorithm, use "hashAlg" as name - public static HashAlgorithmName ObjToHashAlgorithmName(object hashAlg) + internal static HashAlgorithmName ObjToHashAlgorithmName(object hashAlg) { if (hashAlg == null) throw new ArgumentNullException(nameof(hashAlg)); @@ -49,7 +46,7 @@ public static HashAlgorithmName ObjToHashAlgorithmName(object hashAlg) throw new ArgumentException(SR.Argument_InvalidValue); } - public static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) + internal static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) { HashAlgorithmName? name; @@ -78,7 +75,7 @@ public static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) /// /// Map HashAlgorithm type to HashAlgorithmName without using CryptoConfig. Returns null if not found. /// - public static HashAlgorithmName? ToHashAlgorithmName(this HashAlgorithm hashAlgorithm) + internal static HashAlgorithmName? ToHashAlgorithmName(this HashAlgorithm hashAlgorithm) { if (hashAlgorithm is SHA1) return HashAlgorithmName.SHA1; @@ -94,7 +91,7 @@ public static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) return null; } - public static HashAlgorithmName? OidToHashAlgorithmName(string oid) + internal static HashAlgorithmName? OidToHashAlgorithmName(string oid) { switch (oid) { @@ -113,7 +110,7 @@ public static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) } } - public static HashAlgorithmName? HashAlgorithmTypeToHashAlgorithmName(Type hashAlgType) + internal static HashAlgorithmName? HashAlgorithmTypeToHashAlgorithmName(Type hashAlgType) { if (typeof(SHA1).IsAssignableFrom(hashAlgType)) return HashAlgorithmName.SHA1; @@ -128,5 +125,16 @@ public static HashAlgorithmName NameOrOidToHashAlgorithmName(string nameOrOid) return null; } + + internal static CryptographicException GetBadDataException() + { + const int NTE_BAD_DATA = unchecked((int)CryptKeyError.NTE_BAD_DATA); + return new CryptographicException(NTE_BAD_DATA); + } + + internal static CryptographicException GetEFailException() + { + return new CryptographicException(E_FAIL); + } } } diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Windows.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Windows.cs index 48c6a78764fa6..2511c29992799 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Windows.cs @@ -1,19 +1,17 @@ // 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.Buffers.Binary; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Text; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; using static Interop.Crypt32; using CryptProvParam = Interop.Advapi32.CryptProvParam; -namespace Internal.NativeCrypto +namespace System.Security.Cryptography { /// /// Following part of CAPIHelper keeps the wrappers for all the PInvoke calls @@ -349,7 +347,7 @@ internal static int GetProviderParameterWorker(SafeProvHandle safeProvHandle, by { throw GetErrorCode().ToCryptographicException(); } - if (null != impType && cb == Constants.SIZE_OF_DWORD) + if (null != impType && cb == sizeof(uint)) { impTypeReturn = BitConverter.ToInt32(impType, 0); } @@ -360,12 +358,12 @@ internal static int GetProviderParameterWorker(SafeProvHandle safeProvHandle, by /// This method queries the key container and get some of it's properties. /// Those properties should never cause UI to display. /// - public static object GetProviderParameter(SafeProvHandle safeProvHandle, int keyNumber, int keyParam) + public static object GetProviderParameter(SafeProvHandle safeProvHandle, int keyNumber, ClrPropertyId keyParam) { VerifyValidHandle(safeProvHandle); - byte[] impType = new byte[Constants.SIZE_OF_DWORD]; - int cb = sizeof(byte) * Constants.SIZE_OF_DWORD; - SafeKeyHandle safeKeyHandle = SafeKeyHandle.InvalidHandle; + byte[] impType = new byte[sizeof(uint)]; + int cb = sizeof(byte) * sizeof(uint); + SafeCapiKeyHandle safeKeyHandle = SafeCapiKeyHandle.InvalidHandle; int impTypeReturn; int returnType = 0; //using 0 for bool and 1 for string return types bool retVal = false; @@ -375,7 +373,7 @@ public static object GetProviderParameter(SafeProvHandle safeProvHandle, int key { switch (keyParam) { - case Constants.CLR_EXPORTABLE: + case ClrPropertyId.CLR_EXPORTABLE: { impTypeReturn = GetProviderParameterWorker(safeProvHandle, impType, ref cb, CryptProvParam.PP_IMPTYPE); //If implementation type is not HW @@ -387,8 +385,8 @@ public static object GetProviderParameter(SafeProvHandle safeProvHandle, int key } byte[]? permissions = null; int permissionsReturn = 0; - permissions = new byte[Constants.SIZE_OF_DWORD]; - cb = sizeof(byte) * Constants.SIZE_OF_DWORD; + permissions = new byte[sizeof(uint)]; + cb = sizeof(byte) * sizeof(uint); if (!Interop.Advapi32.CryptGetKeyParam(safeKeyHandle, Interop.Advapi32.CryptGetKeyParamFlags.KP_PERMISSIONS, permissions, ref cb, 0)) { throw GetErrorCode().ToCryptographicException(); @@ -404,25 +402,25 @@ public static object GetProviderParameter(SafeProvHandle safeProvHandle, int key break; } - case Constants.CLR_REMOVABLE: + case ClrPropertyId.CLR_REMOVABLE: { impTypeReturn = GetProviderParameterWorker(safeProvHandle, impType, ref cb, CryptProvParam.PP_IMPTYPE); retVal = IsFlagBitSet((uint)impTypeReturn, (uint)CryptGetProvParamPPImpTypeFlags.CRYPT_IMPL_REMOVABLE); break; } - case Constants.CLR_HARDWARE: - case Constants.CLR_PROTECTED: + case ClrPropertyId.CLR_HARDWARE: + case ClrPropertyId.CLR_PROTECTED: { impTypeReturn = GetProviderParameterWorker(safeProvHandle, impType, ref cb, CryptProvParam.PP_IMPTYPE); retVal = IsFlagBitSet((uint)impTypeReturn, (uint)CryptGetProvParamPPImpTypeFlags.CRYPT_IMPL_HARDWARE); break; } - case Constants.CLR_ACCESSIBLE: + case ClrPropertyId.CLR_ACCESSIBLE: { retVal = CryptGetUserKey(safeProvHandle, keyNumber, out safeKeyHandle) ? true : false; break; } - case Constants.CLR_UNIQUE_CONTAINER: + case ClrPropertyId.CLR_UNIQUE_CONTAINER: { returnType = 1; byte[]? pb = null; @@ -454,7 +452,7 @@ public static object GetProviderParameter(SafeProvHandle safeProvHandle, int key /// /// Retrieves the handle for user public / private key pair. /// - internal static int GetUserKey(SafeProvHandle safeProvHandle, int keySpec, out SafeKeyHandle safeKeyHandle) + internal static int GetUserKey(SafeProvHandle safeProvHandle, int keySpec, out SafeCapiKeyHandle safeKeyHandle) { int hr = S_OK; VerifyValidHandle(safeProvHandle); @@ -472,7 +470,7 @@ internal static int GetUserKey(SafeProvHandle safeProvHandle, int keySpec, out S /// /// Generates the key if provided CSP handle is valid /// - internal static int GenerateKey(SafeProvHandle safeProvHandle, int algID, int flags, uint keySize, out SafeKeyHandle safeKeyHandle) + internal static int GenerateKey(SafeProvHandle safeProvHandle, int algID, int flags, uint keySize, out SafeCapiKeyHandle safeKeyHandle) { int hr = S_OK; VerifyValidHandle(safeProvHandle); @@ -551,7 +549,7 @@ internal static void VerifyValidHandle(SafeHandleZeroOrMinusOneIsInvalid handle) /// Key handle /// Key property you want to get /// Returns the key property - internal static byte[] GetKeyParameter(SafeKeyHandle safeKeyHandle, int keyParam) + internal static byte[] GetKeyParameter(SafeCapiKeyHandle safeKeyHandle, ClrPropertyId keyParam) { byte[]? pb = null; int cb = 0; @@ -559,7 +557,7 @@ internal static byte[] GetKeyParameter(SafeKeyHandle safeKeyHandle, int keyParam switch (keyParam) { - case Constants.CLR_KEYLEN: + case ClrPropertyId.CLR_KEYLEN: { if (!Interop.Advapi32.CryptGetKeyParam(safeKeyHandle, Interop.Advapi32.CryptGetKeyParamFlags.KP_KEYLEN, null, ref cb, 0)) { @@ -572,13 +570,13 @@ internal static byte[] GetKeyParameter(SafeKeyHandle safeKeyHandle, int keyParam } break; } - case Constants.CLR_PUBLICKEYONLY: + case ClrPropertyId.CLR_PUBLICKEYONLY: { pb = new byte[1]; pb[0] = safeKeyHandle.PublicOnly ? (byte)1 : (byte)0; break; } - case Constants.CLR_ALGID: + case ClrPropertyId.CLR_ALGID: { // returns the algorithm ID for the key if (!Interop.Advapi32.CryptGetKeyParam(safeKeyHandle, Interop.Advapi32.CryptGetKeyParamFlags.KP_ALGID, null, ref cb, 0)) @@ -607,7 +605,7 @@ internal static byte[] GetKeyParameter(SafeKeyHandle safeKeyHandle, int keyParam /// Key handle /// Key property you want to set /// Key property value you want to set - internal static void SetKeyParameter(SafeKeyHandle safeKeyHandle, CryptGetKeyParamQueryType keyParam, byte[] value) + internal static void SetKeyParameter(SafeCapiKeyHandle safeKeyHandle, CryptGetKeyParamQueryType keyParam, byte[] value) { VerifyValidHandle(safeKeyHandle); //This will throw if handle is invalid @@ -630,7 +628,7 @@ internal static void SetKeyParameter(SafeKeyHandle safeKeyHandle, CryptGetKeyPar /// Key handle /// Key property you want to set /// Key property value you want to set - internal static void SetKeyParameter(SafeKeyHandle safeKeyHandle, CryptGetKeyParamQueryType keyParam, int value) + internal static void SetKeyParameter(SafeCapiKeyHandle safeKeyHandle, CryptGetKeyParamQueryType keyParam, int value) { VerifyValidHandle(safeKeyHandle); //This will throw if handle is invalid @@ -724,14 +722,14 @@ private static void ValidateCspFlags(CspProviderFlags flags) /// /// Helper function to get the key pair /// - internal static SafeKeyHandle GetKeyPairHelper( + internal static SafeCapiKeyHandle GetKeyPairHelper( CspAlgorithmType keyType, CspParameters parameters, int keySize, SafeProvHandle safeProvHandle) { // If the key already exists, use it, else generate a new one - SafeKeyHandle hKey; + SafeCapiKeyHandle hKey; int hr = CapiHelper.GetUserKey(safeProvHandle, parameters.KeyNumber, out hKey); if (hr != S_OK) { @@ -748,7 +746,7 @@ internal static SafeKeyHandle GetKeyPairHelper( } // check that this is indeed an RSA/DSS key. - byte[] algid = CapiHelper.GetKeyParameter(hKey, Constants.CLR_ALGID); + byte[] algid = CapiHelper.GetKeyParameter(hKey, ClrPropertyId.CLR_ALGID); int dwAlgId = BinaryPrimitives.ReadInt32LittleEndian(algid); @@ -812,7 +810,7 @@ internal static void SetPersistKeyInCsp(SafeProvHandle safeProvHandle, bool fPer // // static - internal static void DecryptKey(SafeKeyHandle safeKeyHandle, byte[] encryptedData, int encryptedDataLength, bool fOAEP, out byte[] decryptedData) + internal static void DecryptKey(SafeCapiKeyHandle safeKeyHandle, byte[] encryptedData, int encryptedDataLength, bool fOAEP, out byte[] decryptedData) { VerifyValidHandle(safeKeyHandle); Debug.Assert(encryptedData != null, "Encrypted Data is null"); @@ -872,7 +870,7 @@ internal static void DecryptKey(SafeKeyHandle safeKeyHandle, byte[] encryptedDat // The returned value in ohRetEncryptedKey is byte-reversed from the version CAPI gives us. This is for // compatibility with previous releases of the CLR and other RSA implementations. // - internal static void EncryptKey(SafeKeyHandle safeKeyHandle, byte[] pbKey, int cbKey, bool foep, [NotNull] ref byte[]? pbEncryptedKey) + internal static void EncryptKey(SafeCapiKeyHandle safeKeyHandle, byte[] pbKey, int cbKey, bool foep, [NotNull] ref byte[]? pbEncryptedKey) { VerifyValidHandle(safeKeyHandle); Debug.Assert(pbKey != null, "pbKey is null"); @@ -904,7 +902,7 @@ internal static void EncryptKey(SafeKeyHandle safeKeyHandle, byte[] pbKey, int c } internal static int EncryptData( - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, ReadOnlySpan input, Span output, bool isFinal) @@ -943,7 +941,7 @@ internal static int EncryptData( } internal static int DecryptData( - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, ReadOnlySpan input, Span output) { @@ -967,7 +965,7 @@ internal static int DecryptData( /// /// Helper for Import CSP /// - internal static void ImportKeyBlob(SafeProvHandle saveProvHandle, CspProviderFlags flags, bool addNoSaltFlag, byte[] keyBlob, out SafeKeyHandle safeKeyHandle) + internal static void ImportKeyBlob(SafeProvHandle saveProvHandle, CspProviderFlags flags, bool addNoSaltFlag, byte[] keyBlob, out SafeCapiKeyHandle safeKeyHandle) { // Compat note: This isn't the same check as the one done by the CLR _ImportCspBlob QCall, // but this does match the .NET Framework CLR behavior and the only scenarios it @@ -987,8 +985,8 @@ internal static void ImportKeyBlob(SafeProvHandle saveProvHandle, CspProviderFla dwCapiFlags |= (int)CryptGenKeyFlags.CRYPT_NO_SALT; } - SafeKeyHandle hKey; - if (!CryptImportKey(saveProvHandle, keyBlob, SafeKeyHandle.InvalidHandle, dwCapiFlags, out hKey)) + SafeCapiKeyHandle hKey; + if (!CryptImportKey(saveProvHandle, keyBlob, SafeCapiKeyHandle.InvalidHandle, dwCapiFlags, out hKey)) { int hr = Marshal.GetHRForLastWin32Error(); @@ -1006,7 +1004,7 @@ internal static void ImportKeyBlob(SafeProvHandle saveProvHandle, CspProviderFla /// /// Helper for Export CSP /// - internal static byte[] ExportKeyBlob(bool includePrivateParameters, SafeKeyHandle safeKeyHandle) + internal static byte[] ExportKeyBlob(bool includePrivateParameters, SafeCapiKeyHandle safeKeyHandle) { VerifyValidHandle(safeKeyHandle); @@ -1014,13 +1012,13 @@ internal static byte[] ExportKeyBlob(bool includePrivateParameters, SafeKeyHandl int cbRawData = 0; int dwBlobType = includePrivateParameters ? PRIVATEKEYBLOB : PUBLICKEYBLOB; - if (!Interop.Advapi32.CryptExportKey(safeKeyHandle, SafeKeyHandle.InvalidHandle, dwBlobType, 0, null, ref cbRawData)) + if (!Interop.Advapi32.CryptExportKey(safeKeyHandle, SafeCapiKeyHandle.InvalidHandle, dwBlobType, 0, null, ref cbRawData)) { throw GetErrorCode().ToCryptographicException(); } pbRawData = new byte[cbRawData]; - if (!Interop.Advapi32.CryptExportKey(safeKeyHandle, SafeKeyHandle.InvalidHandle, dwBlobType, 0, pbRawData, ref cbRawData)) + if (!Interop.Advapi32.CryptExportKey(safeKeyHandle, SafeCapiKeyHandle.InvalidHandle, dwBlobType, 0, pbRawData, ref cbRawData)) { throw GetErrorCode().ToCryptographicException(); } @@ -1149,7 +1147,7 @@ private static int GetAlgIdFromOid(string oid, OidGroup oidGroup) /// /// Helper for RSACryptoServiceProvider.SignData/SignHash apis. /// - public static byte[] SignValue(SafeProvHandle hProv, SafeKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash) + public static byte[] SignValue(SafeProvHandle hProv, SafeCapiKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash) { using (SafeHashHandle hHash = hProv.CreateHashHandle(hash, calgHash)) { @@ -1186,7 +1184,7 @@ public static byte[] SignValue(SafeProvHandle hProv, SafeKeyHandle hKey, int key /// /// Helper for RSACryptoServiceProvider.VerifyData/VerifyHash apis. /// - public static bool VerifySign(SafeProvHandle hProv, SafeKeyHandle hKey, int calgKey, int calgHash, byte[] hash, byte[] signature) + public static bool VerifySign(SafeProvHandle hProv, SafeCapiKeyHandle hKey, int calgKey, int calgHash, byte[] hash, byte[] signature) { switch (calgKey) { @@ -1231,10 +1229,10 @@ public static void DeriveKey( VerifyValidHandle(hProv); SafeHashHandle? hHash = null; - SafeKeyHandle? hKey = null; + SafeCapiKeyHandle? hKey = null; try { - if (!CryptCreateHash(hProv, algidHash, SafeKeyHandle.InvalidHandle, Interop.Advapi32.CryptCreateHashFlags.None, out hHash)) + if (!CryptCreateHash(hProv, algidHash, SafeCapiKeyHandle.InvalidHandle, Interop.Advapi32.CryptCreateHashFlags.None, out hHash)) { int hr = Marshal.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); @@ -1295,13 +1293,13 @@ public static void DeriveKey( // Helper method used by DeriveKey (above) to return the key contents. // WARNING: This function side-effects its first argument (hProv) - private static void UnloadKey(SafeProvHandle hProv, SafeKeyHandle hKey, [NotNull] ref byte[]? key_out, ref int cb_out) + private static void UnloadKey(SafeProvHandle hProv, SafeCapiKeyHandle hKey, [NotNull] ref byte[]? key_out, ref int cb_out) { - SafeKeyHandle? hPubKey = null; + SafeCapiKeyHandle? hPubKey = null; try { // Import the public key - if (!CryptImportKey(hProv, RgbPubKey, SafeKeyHandle.InvalidHandle, 0, out hPubKey)) + if (!CryptImportKey(hProv, RgbPubKey, SafeCapiKeyHandle.InvalidHandle, 0, out hPubKey)) { int hr = Marshal.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); @@ -1369,7 +1367,7 @@ private static SafeHashHandle CreateHashHandle(this SafeProvHandle hProv, byte[] private static SafeHashHandle? CreateHashHandle(this SafeProvHandle hProv, byte[] hash, int calgHash, bool throwOnSizeError) { SafeHashHandle? hHash; - if (!CryptCreateHash(hProv, calgHash, SafeKeyHandle.InvalidHandle, Interop.Advapi32.CryptCreateHashFlags.None, out hHash)) + if (!CryptCreateHash(hProv, calgHash, SafeCapiKeyHandle.InvalidHandle, Interop.Advapi32.CryptCreateHashFlags.None, out hHash)) { int hr = Marshal.GetHRForLastWin32Error(); @@ -1431,7 +1429,7 @@ public static CryptographicException GetEFailException() public static bool CryptGetUserKey( SafeProvHandle safeProvHandle, int dwKeySpec, - out SafeKeyHandle safeKeyHandle) + out SafeCapiKeyHandle safeKeyHandle) { bool response = Interop.Advapi32.CryptGetUserKey(safeProvHandle, dwKeySpec, out safeKeyHandle); @@ -1444,7 +1442,7 @@ public static bool CryptGenKey( SafeProvHandle safeProvHandle, int algId, int dwFlags, - out SafeKeyHandle safeKeyHandle) + out SafeCapiKeyHandle safeKeyHandle) { bool response = Interop.Advapi32.CryptGenKey(safeProvHandle, algId, dwFlags, out safeKeyHandle); @@ -1456,9 +1454,9 @@ public static bool CryptGenKey( public static unsafe bool CryptImportKey( SafeProvHandle hProv, ReadOnlySpan pbData, - SafeKeyHandle hPubKey, + SafeCapiKeyHandle hPubKey, int dwFlags, - out SafeKeyHandle phKey) + out SafeCapiKeyHandle phKey) { fixed (byte* pbDataPtr = pbData) { @@ -1473,7 +1471,7 @@ public static unsafe bool CryptImportKey( public static bool CryptCreateHash( SafeProvHandle hProv, int algId, - SafeKeyHandle hKey, + SafeCapiKeyHandle hKey, Interop.Advapi32.CryptCreateHashFlags dwFlags, out SafeHashHandle phHash) { @@ -1489,7 +1487,7 @@ public static bool CryptDeriveKey( int algId, SafeHashHandle phHash, int dwFlags, - out SafeKeyHandle phKey) + out SafeCapiKeyHandle phKey) { bool response = Interop.Advapi32.CryptDeriveKey(hProv, algId, phHash, dwFlags, out phKey); @@ -1497,7 +1495,7 @@ public static bool CryptDeriveKey( return response; } - }//End of class CapiHelper : Wrappers + } /// /// All the Crypto flags are capture in following @@ -1549,6 +1547,7 @@ internal enum CryptGetKeyParamQueryType : int KP_KEYLEN = 9, // Length of key in bits KP_ALGID = 7 // Key algorithm } + internal enum CryptGenKeyFlags : int { // dwFlag definitions for CryptGenKey @@ -1575,5 +1574,20 @@ internal enum CspAlgorithmType Rsa = 0, Dss = 1 } - } //End CapiHelper:Flags -} //End Namespace Internal.NativeCrypto + + internal enum ClrPropertyId + { + CLR_KEYLEN = 1, + CLR_PUBLICKEYONLY = 2, + CLR_EXPORTABLE = 3, + CLR_REMOVABLE = 4, + CLR_HARDWARE = 5, + CLR_ACCESSIBLE = 6, + CLR_PROTECTED = 7, + CLR_UNIQUE_CONTAINER = 8, + CLR_ALGID = 9, + CLR_PP_CLIENT_HWND = 10, + CLR_PP_PIN = 11, + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Cng.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Cng.NotSupported.cs new file mode 100644 index 0000000000000..7495ae1d20260 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Cng.NotSupported.cs @@ -0,0 +1,378 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Text; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.Win32.SafeHandles +{ + public abstract partial class SafeNCryptHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [SupportedOSPlatform("windows")] + protected SafeNCryptHandle() : base(default(bool)) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + protected SafeNCryptHandle(IntPtr handle, SafeHandle parentHandle) : base(default(bool)) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + protected override bool ReleaseHandle() => false; + + protected abstract bool ReleaseNativeHandle(); + } + public sealed partial class SafeNCryptKeyHandle : SafeNCryptHandle + { + [SupportedOSPlatform("windows")] + public SafeNCryptKeyHandle() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public SafeNCryptKeyHandle(IntPtr handle, SafeHandle parentHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + protected override bool ReleaseNativeHandle() => false; + } + public sealed partial class SafeNCryptProviderHandle : SafeNCryptHandle + { + [SupportedOSPlatform("windows")] + public SafeNCryptProviderHandle() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + protected override bool ReleaseNativeHandle() => false; + } + public sealed partial class SafeNCryptSecretHandle : SafeNCryptHandle + { + [SupportedOSPlatform("windows")] + public SafeNCryptSecretHandle() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + protected override bool ReleaseNativeHandle() => false; + } +} + +namespace System.Security.Cryptography +{ + public sealed partial class AesCng : Aes + { + [SupportedOSPlatform("windows")] + public AesCng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public AesCng(string keyName) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public AesCng(string keyName, CngProvider provider) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public AesCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public override void GenerateKey() { } + public override void GenerateIV() { } + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => null!; + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => null!; + } + public sealed partial class CngKey : System.IDisposable + { + internal CngKey() { } + public CngAlgorithm Algorithm => null!; + public CngAlgorithmGroup? AlgorithmGroup => null; + public CngExportPolicies ExportPolicy => default; + public SafeNCryptKeyHandle Handle => null!; + public bool IsEphemeral => false; + public bool IsMachineKey => false; + public string? KeyName => null; + public int KeySize => default; + public CngKeyUsages KeyUsage => default; + public IntPtr ParentWindowHandle { get => default; set { } } + public CngProvider? Provider => null; + public SafeNCryptProviderHandle ProviderHandle => null!; + public CngUIPolicy UIPolicy => null!; + public string? UniqueName => null; + public void Delete() { } + public void Dispose() { } + public byte[] Export(CngKeyBlobFormat format) => null!; + public CngProperty GetProperty(string name, CngPropertyOptions options) => default; + public bool HasProperty(string name, CngPropertyOptions options) => false; + public void SetProperty(CngProperty property) { } + + [SupportedOSPlatform("windows")] + public static CngKey Create(CngAlgorithm algorithm) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Create(CngAlgorithm algorithm, string? keyName) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Create(CngAlgorithm algorithm, string? keyName, CngKeyCreationParameters? creationParameters) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static bool Exists(string keyName) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static bool Exists(string keyName, CngProvider provider) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static bool Exists(string keyName, CngProvider provider, CngKeyOpenOptions options) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Open(string keyName) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Open(string keyName, CngProvider provider) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public static CngKey Open(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + } + public sealed partial class DSACng : DSA + { + [SupportedOSPlatform("windows")] + public DSACng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public DSACng(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public DSACng(CngKey key) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public CngKey Key => null!; + public override byte[] CreateSignature(byte[] rgbHash) => null!; + public override DSAParameters ExportParameters(bool includePrivateParameters) => default; + public override void ImportParameters(DSAParameters parameters) { } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) => false; + } + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + { + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(CngKey key) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(ECCurve curve) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public CngAlgorithm HashAlgorithm { get => null!; set { } } + public byte[]? HmacKey { get => null; set { } } + public CngKey Key => null!; + public ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get => default; set { } } + public byte[]? Label { get => null; set { } } + public byte[]? SecretAppend { get => null; set { } } + public byte[]? SecretPrepend { get => null; set { } } + public byte[]? Seed { get => null; set { } } + public bool UseSecretAgreementAsHmacKey => false; + public SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) => null!; + public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) => null!; + public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) => null!; + public void FromXmlString(string xml, ECKeyXmlFormat format) { } + public string ToXmlString(ECKeyXmlFormat format) => null!; + public override ECDiffieHellmanPublicKey PublicKey => null!; + } + public sealed partial class ECDiffieHellmanCngPublicKey : ECDiffieHellmanPublicKey + { + internal ECDiffieHellmanCngPublicKey() { } + public CngKeyBlobFormat BlobFormat => null!; + protected override void Dispose(bool disposing) { } + public CngKey Import() => null!; + + [SupportedOSPlatform("windows")] + public static ECDiffieHellmanPublicKey FromByteArray(byte[] publicKeyBlob, CngKeyBlobFormat format) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + // Also throws in Windows, no SupportedOSPlatform required. + public static ECDiffieHellmanCngPublicKey FromXmlString(string xml) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + } + public sealed partial class ECDsaCng : ECDsa + { + [SupportedOSPlatform("windows")] + public ECDsaCng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDsaCng(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDsaCng(CngKey key) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public ECDsaCng(ECCurve curve) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public CngAlgorithm HashAlgorithm { get => null!; set { } } + public CngKey Key => null!; + public void FromXmlString(string xml, ECKeyXmlFormat format) { } + public byte[] SignData(byte[] data) => null!; + public byte[] SignData(byte[] data, int offset, int count) => null!; + public byte[] SignData(System.IO.Stream data) => null!; + public string ToXmlString(ECKeyXmlFormat format) => null!; + public bool VerifyData(byte[] data, byte[] signature) => false; + public bool VerifyData(byte[] data, int offset, int count, byte[] signature) => false; + public bool VerifyData(System.IO.Stream data, byte[] signature) => false; + public override byte[] SignHash(byte[] hash) => null!; + public override bool VerifyHash(byte[] hash, byte[] signature) => false; + } + public sealed partial class RSACng : RSA + { + [SupportedOSPlatform("windows")] + public RSACng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public RSACng(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public RSACng(CngKey key) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public CngKey Key => null!; + public override RSAParameters ExportParameters(bool includePrivateParameters) => default; + public override void ImportParameters(RSAParameters parameters) { } + } + public sealed partial class TripleDESCng : TripleDES + { + [SupportedOSPlatform("windows")] + public TripleDESCng() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public TripleDESCng(string keyName) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public TripleDESCng(string keyName, CngProvider provider) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + [SupportedOSPlatform("windows")] + public TripleDESCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyCng); + } + + public override void GenerateKey() { } + public override void GenerateIV() { } + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => null!; + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => null!; + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithm.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithm.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithm.cs index 52ba6b6a7d5db..28de479aae4f6 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithm.cs @@ -17,11 +17,7 @@ public sealed class CngAlgorithm : IEquatable { public CngAlgorithm(string algorithm) { - if (algorithm == null) - throw new ArgumentNullException(nameof(algorithm)); - if (algorithm.Length == 0) - throw new ArgumentException(SR.Format(SR.Cryptography_InvalidAlgorithmName, algorithm), nameof(algorithm)); - + ArgumentException.ThrowIfNullOrEmpty(algorithm); _algorithm = algorithm; } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngAlgorithmCore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmCore.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngAlgorithmCore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmCore.cs index 7273ea9b6400d..d5bcfafaaa502 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngAlgorithmCore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmCore.cs @@ -1,13 +1,11 @@ // 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.Diagnostics; -using System.Security.Cryptography; using Microsoft.Win32.SafeHandles; using static Interop.NCrypt; -namespace Internal.Cryptography +namespace System.Security.Cryptography { // // Common infrastructure for crypto algorithms that accept CngKeys. @@ -15,7 +13,9 @@ namespace Internal.Cryptography internal struct CngAlgorithmCore { private readonly string _disposedName; +#pragma warning disable CS0649 public CngAlgorithm? DefaultKeyType; +#pragma warning restore CS0649 private CngKey? _lazyKey; private bool _disposed; diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithmGroup.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmGroup.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithmGroup.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmGroup.cs index 0c7ffe55998c0..b65eb4c3d78d4 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngAlgorithmGroup.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngAlgorithmGroup.cs @@ -18,11 +18,7 @@ public sealed class CngAlgorithmGroup : IEquatable { public CngAlgorithmGroup(string algorithmGroup) { - if (algorithmGroup == null) - throw new ArgumentNullException(nameof(algorithmGroup)); - if (algorithmGroup.Length == 0) - throw new ArgumentException(SR.Format(SR.Cryptography_InvalidAlgorithmGroup, algorithmGroup), nameof(algorithmGroup)); - + ArgumentException.ThrowIfNullOrEmpty(algorithmGroup); _algorithmGroup = algorithmGroup; } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngExportPolicies.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngExportPolicies.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngExportPolicies.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngExportPolicies.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngHelpers.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngHelpers.cs new file mode 100644 index 0000000000000..6e316bf652454 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngHelpers.cs @@ -0,0 +1,242 @@ +// 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 System.IO; +using System.Runtime.InteropServices; +using System.Text; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; + +using ErrorCode = Interop.NCrypt.ErrorCode; + +namespace System.Security.Cryptography +{ + internal static class CngHelpers + { + private static readonly CngKeyBlobFormat s_cipherKeyBlobFormat = new CngKeyBlobFormat(Interop.NCrypt.NCRYPT_CIPHER_KEY_BLOB); + + internal static SafeNCryptProviderHandle OpenStorageProvider(this CngProvider provider) + { + string providerName = provider.Provider; + SafeNCryptProviderHandle providerHandle; + ErrorCode errorCode = Interop.NCrypt.NCryptOpenStorageProvider(out providerHandle, providerName, 0); + + if (errorCode != ErrorCode.ERROR_SUCCESS) + { + throw errorCode.ToCryptographicException(); + } + + return providerHandle; + } + + public static void SetExportPolicy(this SafeNCryptKeyHandle keyHandle, CngExportPolicies exportPolicy) + { + unsafe + { + ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty( + keyHandle, + KeyPropertyName.ExportPolicy, + &exportPolicy, + sizeof(CngExportPolicies), + CngPropertyOptions.Persist); + + if (errorCode != ErrorCode.ERROR_SUCCESS) + { + throw errorCode.ToCryptographicException(); + } + } + } + + /// + /// Returns a CNG key property. + /// + /// + /// null - if property not defined on key. + /// throws - for any other type of error. + /// + internal static byte[]? GetProperty(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) + { + Debug.Assert(!ncryptHandle.IsInvalid); + unsafe + { + ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty( + ncryptHandle, + propertyName, + null, + 0, + out int numBytesNeeded, + options); + + if (errorCode == ErrorCode.NTE_NOT_FOUND) + { + return null; + } + + if (errorCode != ErrorCode.ERROR_SUCCESS) + { + throw errorCode.ToCryptographicException(); + } + + byte[] propertyValue = new byte[numBytesNeeded]; + + fixed (byte* pPropertyValue = propertyValue) + { + errorCode = Interop.NCrypt.NCryptGetProperty( + ncryptHandle, + propertyName, + pPropertyValue, + propertyValue.Length, + out numBytesNeeded, + options); + } + + if (errorCode == ErrorCode.NTE_NOT_FOUND) + { + return null; + } + + if (errorCode != ErrorCode.ERROR_SUCCESS) + { + throw errorCode.ToCryptographicException(); + } + + Array.Resize(ref propertyValue, numBytesNeeded); + return propertyValue; + } + } + + /// + /// Retrieve a well-known CNG string property. (Note: .NET Framework compat: this helper likes to return special + /// values rather than throw exceptions for missing or ill-formatted property values. Only use it for well-known + /// properties that are unlikely to be ill-formatted.) + /// + internal static string? GetPropertyAsString(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) + { + Debug.Assert(!ncryptHandle.IsInvalid); + byte[]? value = GetProperty(ncryptHandle, propertyName, options); + + if (value == null) + { + // .NET Framework compat: return null if key not present. + return null; + } + + if (value.Length == 0) + { + // .NET Framework compat: return empty if property value is 0-length. + return string.Empty; + } + + unsafe + { + fixed (byte* pValue = &value[0]) + { + string valueAsString = Marshal.PtrToStringUni((IntPtr)pValue)!; + return valueAsString; + } + } + } + + /// + /// Retrieve a well-known CNG dword property. (Note: .NET Framework compat: this helper likes to return special values + /// rather than throw exceptions for missing or ill-formatted property values. Only use it for well-known properties that + /// are unlikely to be ill-formatted.) + /// + public static int GetPropertyAsDword(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) + { + byte[]? value = ncryptHandle.GetProperty(propertyName, options); + + if (value == null) + { + // .NET Framework compat: return 0 if key not present. + return 0; + } + + return BitConverter.ToInt32(value, 0); + } + + /// + /// Retrieve a well-known CNG pointer property. (Note: .NET Framework compat: this helper likes to return special values + /// rather than throw exceptions for missing or ill-formatted property values. Only use it for well-known properties that + /// are unlikely to be ill-formatted.) + /// + internal static IntPtr GetPropertyAsIntPtr(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) + { + unsafe + { + IntPtr value; + + ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty( + ncryptHandle, + propertyName, + &value, + IntPtr.Size, + out _, + options); + + if (errorCode == ErrorCode.NTE_NOT_FOUND) + { + return IntPtr.Zero; + } + + if (errorCode != ErrorCode.ERROR_SUCCESS) + { + throw errorCode.ToCryptographicException(); + } + + return value; + } + } + + /// + /// Note! This can and likely will throw if the algorithm was given a hardware-based key. + /// + internal static byte[] GetSymmetricKeyDataIfExportable(this CngKey cngKey, string algorithm) + { + const int SizeOf_NCRYPT_KEY_BLOB_HEADER = + sizeof(int) + sizeof(int) + sizeof(int) + sizeof(int); + + byte[] keyBlob = cngKey.Export(s_cipherKeyBlobFormat); + using (MemoryStream ms = new MemoryStream(keyBlob)) + { + using (BinaryReader br = new BinaryReader(ms, Encoding.Unicode)) + { + // Read NCRYPT_KEY_BLOB_HEADER + int cbSize = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbSize + if (cbSize != SizeOf_NCRYPT_KEY_BLOB_HEADER) + throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); + + int ncryptMagic = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.dwMagic + if (ncryptMagic != Interop.NCrypt.NCRYPT_CIPHER_KEY_BLOB_MAGIC) + throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); + + int cbAlgName = br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbAlgName + + br.ReadInt32(); // NCRYPT_KEY_BLOB_HEADER.cbKey + + string algorithmName = new string(br.ReadChars((cbAlgName / 2) - 1)); + if (algorithmName != algorithm) + throw new CryptographicException(SR.Format(SR.Cryptography_CngKeyWrongAlgorithm, algorithmName, algorithm)); + + char nullTerminator = br.ReadChar(); + if (nullTerminator != 0) + throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); + + // Read BCRYPT_KEY_DATA_BLOB_HEADER + int bcryptMagic = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.dwMagic + if (bcryptMagic != Interop.BCrypt.BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_MAGIC) + throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); + + int dwVersion = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.dwVersion + if (dwVersion != Interop.BCrypt.BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_VERSION1) + throw new CryptographicException(SR.Cryptography_KeyBlobParsingError); + + int keyLength = br.ReadInt32(); // BCRYPT_KEY_DATA_BLOB_HEADER.cbKeyData + byte[] key = br.ReadBytes(keyLength); + return key; + } + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Create.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Create.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Create.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Create.cs index d56aaacb33598..a8ee97a859d69 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Create.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Create.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; @@ -18,16 +19,19 @@ public sealed partial class CngKey : IDisposable // Creation factory methods // + [SupportedOSPlatform("windows")] public static CngKey Create(CngAlgorithm algorithm) { return Create(algorithm, keyName: null); } + [SupportedOSPlatform("windows")] public static CngKey Create(CngAlgorithm algorithm, string? keyName) { return Create(algorithm, keyName, creationParameters: null); } + [SupportedOSPlatform("windows")] public static CngKey Create(CngAlgorithm algorithm, string? keyName, CngKeyCreationParameters? creationParameters) { if (algorithm == null) @@ -105,7 +109,7 @@ private static void InitializeKeyProperties(SafeNCryptKeyHandle keyHandle, CngKe { byte[]? value = property.GetValueWithoutCopying(); int valueLength = (value == null) ? 0 : value.Length; - fixed (byte* pValue = value.MapZeroLengthArrayToNonNullPointer()) + fixed (byte* pValue = MapZeroLengthArrayToNonNullPointer(value)) { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, property.Name, pValue, valueLength, property.Options); if (errorCode != ErrorCode.ERROR_SUCCESS) diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Delete.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Delete.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Delete.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Delete.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.EC.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.EC.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.EC.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.EC.cs index 32f7af604ea43..c47f427b4cf1d 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.EC.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.EC.cs @@ -1,10 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; using System.Diagnostics; -using BCRYPT_ECC_PARAMETER_HEADER = Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER; -using Internal.NativeCrypto; namespace System.Security.Cryptography { @@ -115,14 +112,17 @@ internal static CngAlgorithm EcdhCurveNameToAlgorithm(string name) { case "nistP256": case "ECDH_P256": + case "ECDSA_P256": return CngAlgorithm.ECDiffieHellmanP256; case "nistP384": case "ECDH_P384": + case "ECDSA_P384": return CngAlgorithm.ECDiffieHellmanP384; case "nistP521": case "ECDH_P521": + case "ECDSA_P521": return CngAlgorithm.ECDiffieHellmanP521; } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Exists.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Exists.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Exists.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Exists.cs index d4124aafc272b..ff1ba4a7c8338 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Exists.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Exists.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; using Internal.Cryptography; @@ -18,16 +19,19 @@ public sealed partial class CngKey : IDisposable // Check to see if a key already exists // + [SupportedOSPlatform("windows")] public static bool Exists(string keyName) { return Exists(keyName, provider: CngProvider.MicrosoftSoftwareKeyStorageProvider); } + [SupportedOSPlatform("windows")] public static bool Exists(string keyName, CngProvider provider) { return Exists(keyName, provider, options: CngKeyOpenOptions.None); } + [SupportedOSPlatform("windows")] public static bool Exists(string keyName, CngProvider provider, CngKeyOpenOptions options) { if (keyName == null) diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Export.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Export.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Export.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Export.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Import.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Import.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Import.cs index 6b4950fe4ce14..4a7e64000cbd9 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Import.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; using Internal.Cryptography; @@ -23,6 +24,7 @@ internal static CngKey Import(ReadOnlySpan keyBlob, CngKeyBlobFormat forma return Import(keyBlob, null, format, CngProvider.MicrosoftSoftwareKeyStorageProvider); } + [SupportedOSPlatform("windows")] public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format) { return Import(keyBlob, format, provider: CngProvider.MicrosoftSoftwareKeyStorageProvider); @@ -33,6 +35,7 @@ internal static CngKey Import(byte[] keyBlob, string? curveName, CngKeyBlobForma return Import(keyBlob, curveName, format, provider: CngProvider.MicrosoftSoftwareKeyStorageProvider); } + [SupportedOSPlatform("windows")] public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider) { return Import(keyBlob, null, format, provider); diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Open.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Open.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Open.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Open.cs index 838a934a2b10b..4f6344baf2a51 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Open.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Open.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; using Internal.Cryptography; @@ -18,16 +19,19 @@ public sealed partial class CngKey : IDisposable // Open factory methods // + [SupportedOSPlatform("windows")] public static CngKey Open(string keyName) { return Open(keyName, provider: CngProvider.MicrosoftSoftwareKeyStorageProvider); } + [SupportedOSPlatform("windows")] public static CngKey Open(string keyName, CngProvider provider) { return Open(keyName, provider, openOptions: CngKeyOpenOptions.None); } + [SupportedOSPlatform("windows")] public static CngKey Open(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) { if (keyName == null) diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.OpenHandle.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.OpenHandle.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.OpenHandle.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.OpenHandle.cs index a5b61dc82fd90..51a70f8d9468b 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.OpenHandle.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.OpenHandle.cs @@ -1,10 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; -using Internal.Cryptography; - namespace System.Security.Cryptography { /// @@ -15,6 +14,7 @@ public sealed partial class CngKey : IDisposable /// /// Wrap an existing key handle with a CngKey object /// + [SupportedOSPlatform("windows")] public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Properties.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Properties.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Properties.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Properties.cs index 998690be8ea3a..4507c0fccf48f 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.Properties.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.Properties.cs @@ -62,7 +62,7 @@ public void SetProperty(CngProperty property) if (propertyValue == null) throw ErrorCode.NTE_INVALID_PARAMETER.ToCryptographicException(); - fixed (byte* pinnedPropertyValue = propertyValue.MapZeroLengthArrayToNonNullPointer()) + fixed (byte* pinnedPropertyValue = MapZeroLengthArrayToNonNullPointer(propertyValue)) { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(_keyHandle, property.Name, pinnedPropertyValue, propertyValue.Length, property.Options); if (errorCode != ErrorCode.ERROR_SUCCESS) diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.StandardProperties.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.StandardProperties.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.cs similarity index 59% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.cs index 1b42de8ccb702..dd78630eecf6f 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.cs @@ -1,15 +1,9 @@ // 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.Diagnostics; - using Microsoft.Win32.SafeHandles; -using Internal.Cryptography; - -using ErrorCode = Interop.NCrypt.ErrorCode; - namespace System.Security.Cryptography { /// @@ -17,6 +11,9 @@ namespace System.Security.Cryptography /// public sealed partial class CngKey : IDisposable { + private readonly SafeNCryptKeyHandle _keyHandle; + private readonly SafeNCryptProviderHandle _providerHandle; + private CngKey(SafeNCryptProviderHandle providerHandle, SafeNCryptKeyHandle keyHandle) { Debug.Assert(keyHandle != null && !keyHandle.IsInvalid && !keyHandle.IsClosed); @@ -39,7 +36,29 @@ public void Dispose() } } - private readonly SafeNCryptKeyHandle _keyHandle; - private readonly SafeNCryptProviderHandle _providerHandle; + // + // The C# construct + // + // fixed (byte* p = new byte[0]) + // + // sets "p" to 0 rather than a valid address. Sometimes, we actually want a non-NULL pointer instead. + // (Some CNG apis actually care whether the buffer pointer is NULL or not, even if the accompanying + // size argument is 0.) + // + // This helper enables the syntax: + // + // fixed (byte* p = new byte[0].MapZeroLengthArrayToNonNullPointer()) + // + // which always sets "p" to a non-NULL pointer for a non-null byte array. + // + private static byte[]? MapZeroLengthArrayToNonNullPointer(byte[]? src) + { + if (src != null && src.Length == 0) + { + return new byte[1]; + } + + return src; + } } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyBlobFormat.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyBlobFormat.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyBlobFormat.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyBlobFormat.cs index 81d4b170dccb7..baf07295805da 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyBlobFormat.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyBlobFormat.cs @@ -18,11 +18,7 @@ public sealed class CngKeyBlobFormat : IEquatable { public CngKeyBlobFormat(string format) { - if (format == null) - throw new ArgumentNullException(nameof(format)); - if (format.Length == 0) - throw new ArgumentException(SR.Format(SR.Cryptography_InvalidKeyBlobFormat, format), nameof(format)); - + ArgumentException.ThrowIfNullOrEmpty(format); _format = format; } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyCreationOptions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationOptions.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyCreationOptions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationOptions.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyCreationParameters.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyCreationParameters.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyHandleOpenOptions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyHandleOpenOptions.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyHandleOpenOptions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyHandleOpenOptions.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyLite.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyLite.cs index 3670b98ffc049..efa152cc562c7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyLite.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyLite.cs @@ -1,10 +1,8 @@ // 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.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; @@ -13,19 +11,40 @@ namespace System.Security.Cryptography { - internal static class CngKeyLite + internal static class KeyPropertyName { - internal static class KeyPropertyName - { - internal const string Algorithm = "Algorithm Name"; // NCRYPT_ALGORITHM_PROPERTY - internal const string AlgorithmGroup = "Algorithm Group"; // NCRYPT_ALGORITHM_GROUP_PROPERTY - internal const string ECCCurveName = "ECCCurveName"; // NCRYPT_ECC_CURVE_NAME - internal const string ECCParameters = "ECCParameters"; // BCRYPT_ECC_PARAMETERS - internal const string ExportPolicy = "Export Policy"; // NCRYPT_EXPORT_POLICY_PROPERTY - internal const string Length = "Length"; // NCRYPT_LENGTH_PROPERTY - internal const string PublicKeyLength = "PublicKeyLength"; // NCRYPT_PUBLIC_KEY_LENGTH (Win10+) - } + internal const string Algorithm = "Algorithm Name"; // NCRYPT_ALGORITHM_PROPERTY + internal const string AlgorithmGroup = "Algorithm Group"; // NCRYPT_ALGORITHM_GROUP_PROPERTY + internal const string ChainingMode = "Chaining Mode"; // NCRYPT_CHAINING_MODE_PROPERTY + internal const string ECCCurveName = "ECCCurveName"; // NCRYPT_ECC_CURVE_NAME + internal const string ECCParameters = "ECCParameters"; // BCRYPT_ECC_PARAMETERS + internal const string ExportPolicy = "Export Policy"; // NCRYPT_EXPORT_POLICY_PROPERTY + internal const string InitializationVector = "IV"; // NCRYPT_INITIALIZATION_VECTOR + internal const string KeyType = "Key Type"; // NCRYPT_KEY_TYPE_PROPERTY + internal const string KeyUsage = "Key Usage"; // NCRYPT_KEY_USAGE_PROPERTY + internal const string Length = "Length"; // NCRYPT_LENGTH_PROPERTY + internal const string Name = "Name"; // NCRYPT_NAME_PROPERTY + internal const string ParentWindowHandle = "HWND Handle"; // NCRYPT_WINDOW_HANDLE_PROPERTY + internal const string PublicKeyLength = "PublicKeyLength"; // NCRYPT_PUBLIC_KEY_LENGTH (Win10+) + internal const string ProviderHandle = "Provider Handle"; // NCRYPT_PROVIDER_HANDLE_PROPERTY + internal const string UIPolicy = "UI Policy"; // NCRYPT_UI_POLICY_PROPERTY + internal const string UniqueName = "Unique Name"; // NCRYPT_UNIQUE_NAME_PROPERTY + internal const string UseContext = "Use Context"; // NCRYPT_USE_CONTEXT_PROPERTY + + + // + // Properties defined by the CLR + // + + /// + /// Is the key a CLR created ephemeral key, it will contain a single byte with value 1 if the + /// key was created by the CLR as an ephemeral key. + /// + internal const string ClrIsEphemeral = "CLR IsEphemeral"; + } + internal static class CngKeyLite + { private static readonly SafeNCryptProviderHandle s_microsoftSoftwareProviderHandle = OpenNCryptProvider("Microsoft Software Key Storage Provider"); // MS_KEY_STORAGE_PROVIDER @@ -569,58 +588,13 @@ private static SafeNCryptProviderHandle OpenNCryptProvider(string providerName) /// private static byte[]? GetProperty(SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) { - Debug.Assert(!ncryptHandle.IsInvalid); - unsafe - { - int numBytesNeeded; - ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, null, 0, out numBytesNeeded, options); - if (errorCode == ErrorCode.NTE_NOT_FOUND) - return null; - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - - byte[] propertyValue = new byte[numBytesNeeded]; - fixed (byte* pPropertyValue = propertyValue) - { - errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, pPropertyValue, propertyValue.Length, out numBytesNeeded, options); - } - if (errorCode == ErrorCode.NTE_NOT_FOUND) - return null; - if (errorCode != ErrorCode.ERROR_SUCCESS) - throw errorCode.ToCryptographicException(); - - Array.Resize(ref propertyValue, numBytesNeeded); - return propertyValue; - } - } - - /// - /// Retrieve a well-known CNG string property. (Note: .NET Framework compat: this helper likes to return special values rather than throw exceptions for missing - /// or ill-formatted property values. Only use it for well-known properties that are unlikely to be ill-formatted.) - /// - internal static string? GetPropertyAsString(SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) - { - Debug.Assert(!ncryptHandle.IsInvalid); - byte[]? value = GetProperty(ncryptHandle, propertyName, options); - if (value == null) - return null; // .NET Framework compat: return null if key not present. - if (value.Length == 0) - return string.Empty; // .NET Framework compat: return empty if property value is 0-length. - - unsafe - { - fixed (byte* pValue = &value[0]) - { - string valueAsString = Marshal.PtrToStringUni((IntPtr)pValue)!; - return valueAsString; - } - } + return CngHelpers.GetProperty(ncryptHandle, propertyName, options); } internal static string? GetCurveName(SafeNCryptHandle ncryptHandle) { Debug.Assert(!ncryptHandle.IsInvalid); - return GetPropertyAsString(ncryptHandle, KeyPropertyName.ECCCurveName, CngPropertyOptions.None); + return ncryptHandle.GetPropertyAsString(KeyPropertyName.ECCCurveName, CngPropertyOptions.None); } internal static void SetCurveName(SafeNCryptHandle keyHandle, string curveName) @@ -655,97 +629,4 @@ private static void SetProperty(SafeNCryptHandle ncryptHandle, string propertyNa } } } - - // Limited version of CngExportPolicies from the Cng contract. - [Flags] - internal enum CngPropertyOptions : int - { - None = 0, - Persist = unchecked((int)0x80000000), //NCRYPT_PERSIST_FLAG (The property should be persisted.) - } - - // Limited version of CngKeyCreationOptions from the Cng contract. - [Flags] - internal enum CngKeyCreationOptions : int - { - None = 0x00000000, - } - - // Limited version of CngKeyOpenOptions from the Cng contract. - [Flags] - internal enum CngKeyOpenOptions : int - { - None = 0x00000000, - } - - // Limited version of CngExportPolicies from the Cng contract. - [Flags] - internal enum CngExportPolicies : int - { - None = 0x00000000, - AllowPlaintextExport = 0x00000002, // NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG - } -} - -// Internal, lightweight versions of the SafeNCryptHandle types which are public in CNG. -namespace Microsoft.Win32.SafeHandles -{ - internal class SafeNCryptHandle : SafeHandle - { - public SafeNCryptHandle() - : base(IntPtr.Zero, ownsHandle: true) - { - } - - protected override bool ReleaseHandle() - { - ErrorCode errorCode = Interop.NCrypt.NCryptFreeObject(handle); - bool success = (errorCode == ErrorCode.ERROR_SUCCESS); - Debug.Assert(success); - handle = IntPtr.Zero; - return success; - } - - public override bool IsInvalid - { - get { return handle == IntPtr.Zero; } - } - } - - internal class SafeNCryptKeyHandle : SafeNCryptHandle - { - } - - internal sealed class SafeNCryptProviderHandle : SafeNCryptHandle - { - } - - internal sealed class SafeNCryptSecretHandle : SafeNCryptHandle - { - } - -#pragma warning disable CA1419 // TODO https://github.com/dotnet/roslyn-analyzers/issues/5232: not intended for use with P/Invoke - - internal sealed class DuplicateSafeNCryptKeyHandle : SafeNCryptKeyHandle - { - public DuplicateSafeNCryptKeyHandle(SafeNCryptKeyHandle original) - : base() - { - bool success = false; - original.DangerousAddRef(ref success); - if (!success) - throw new CryptographicException(); // DangerousAddRef() never actually sets success to false, so no need to expend a resource string here. - SetHandle(original.DangerousGetHandle()); - _original = original; - } - - protected override bool ReleaseHandle() - { - _original.DangerousRelease(); - SetHandle(IntPtr.Zero); - return true; - } - - private readonly SafeNCryptKeyHandle _original; - } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyOpenOptions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyOpenOptions.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyOpenOptions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyOpenOptions.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyUsages.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyUsages.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngKeyUsages.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyUsages.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPkcs8.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPkcs8.cs index ad9914066278a..7324a310746ba 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPkcs8.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPkcs8.cs @@ -1,39 +1,33 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; - namespace System.Security.Cryptography { internal static partial class CngPkcs8 { internal struct Pkcs8Response { - internal SafeNCryptKeyHandle KeyHandle; + internal CngKey Key; internal string? GetAlgorithmGroup() { - return CngKeyLite.GetPropertyAsString( - KeyHandle, - CngKeyLite.KeyPropertyName.AlgorithmGroup, - CngPropertyOptions.None); + return Key.AlgorithmGroup!.AlgorithmGroup; } internal void FreeKey() { - KeyHandle.Dispose(); + Key.Dispose(); } } private static Pkcs8Response ImportPkcs8(ReadOnlySpan keyBlob) { - SafeNCryptKeyHandle handle = CngKeyLite.ImportKeyBlob( - Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, - keyBlob); + CngKey key = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob); + key.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; return new Pkcs8Response { - KeyHandle = handle, + Key = key, }; } @@ -41,15 +35,12 @@ private static Pkcs8Response ImportPkcs8( ReadOnlySpan keyBlob, ReadOnlySpan password) { - SafeNCryptKeyHandle handle = CngKeyLite.ImportKeyBlob( - Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, - keyBlob, - encrypted: true, - password); + CngKey key = CngKey.ImportEncryptedPkcs8(keyBlob, password); + key.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; return new Pkcs8Response { - KeyHandle = handle, + Key = key, }; } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngProperty.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngProperty.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPropertyCollection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPropertyCollection.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPropertyCollection.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPropertyCollection.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPropertyOptions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPropertyOptions.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngPropertyOptions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngPropertyOptions.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProvider.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProvider.cs index aad1695cef02d..61d631c7be4cd 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProvider.cs @@ -17,11 +17,7 @@ public sealed class CngProvider : IEquatable { public CngProvider(string provider) { - if (provider == null) - throw new ArgumentNullException(nameof(provider)); - if (provider.Length == 0) - throw new ArgumentException(SR.Format(SR.Cryptography_InvalidProviderName, provider), nameof(provider)); - + ArgumentException.ThrowIfNullOrEmpty(provider); _provider = provider; } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngSymmetricAlgorithmCore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngSymmetricAlgorithmCore.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngSymmetricAlgorithmCore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngSymmetricAlgorithmCore.cs index 401a8c1a7d645..654a06a95e558 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/CngSymmetricAlgorithmCore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngSymmetricAlgorithmCore.cs @@ -1,12 +1,11 @@ // 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.Diagnostics; -using System.Security.Cryptography; +using Internal.Cryptography; using Internal.NativeCrypto; -namespace Internal.Cryptography +namespace System.Security.Cryptography { // // Common infrastructure for crypto symmetric algorithms that use Cng. @@ -89,13 +88,13 @@ public void SetKeySize(int keySize, ICngSymmetricAlgorithm outer) public void GenerateKey() { - byte[] key = Helpers.GenerateRandom(_outer.BaseKeySize.BitSizeToByteSize()); + byte[] key = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BaseKeySize)); SetKey(key); } public void GenerateIV() { - byte[] iv = Helpers.GenerateRandom(_outer.BlockSize.BitSizeToByteSize()); + byte[] iv = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)); _outer.IV = iv; } @@ -150,13 +149,22 @@ private UniversalCryptoTransform CreateCryptoTransform(byte[] rgbKey, byte[]? rg long keySize = key.Length * (long)BitsPerByte; if (keySize > int.MaxValue || !((int)keySize).IsLegalSize(_outer.LegalKeySizes)) + { throw new ArgumentException(SR.Cryptography_InvalidKeySize, nameof(rgbKey)); + } if (_outer.IsWeakKey(key)) - throw new CryptographicException(SR.Cryptography_WeakKey); + { + throw new CryptographicException( + SR.Format( + SR.Cryptography_InvalidKey_Weak, + _outer.GetNCryptAlgorithmIdentifier())); + } - if (rgbIV != null && rgbIV.Length != _outer.BlockSize.BitSizeToByteSize()) + if (rgbIV != null && rgbIV.Length != AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)) + { throw new ArgumentException(SR.Cryptography_InvalidIVSize, nameof(rgbIV)); + } // CloneByteArray is null-preserving. So even when GetCipherIv returns null the iv variable // is correct, and detached from the input parameter. @@ -169,7 +177,7 @@ private UniversalCryptoTransform CreateCryptoTransform(byte[] rgbKey, byte[]? rg private UniversalCryptoTransform CreateEphemeralCryptoTransformCore(byte[] key, byte[]? iv, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { - int blockSizeInBytes = _outer.BlockSize.BitSizeToByteSize(); + int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); SafeAlgorithmHandle algorithmModeHandle = _outer.GetEphemeralModeHandle(mode, feedbackSizeInBits); BasicSymmetricCipher cipher = new BasicSymmetricCipherBCrypt( @@ -192,7 +200,7 @@ private UniversalCryptoTransform CreatePersistedCryptoTransformCore(Func ValidateFeedbackSize(mode, feedbackSizeInBits); Debug.Assert(mode == CipherMode.CFB ? feedbackSizeInBits == 8 : true); - int blockSizeInBytes = _outer.BlockSize.BitSizeToByteSize(); + int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); BasicSymmetricCipher cipher = new BasicSymmetricCipherNCrypt( cngKeyFactory, mode, diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngUIPolicy.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngUIPolicy.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngUIProtectionLevels.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIProtectionLevels.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/CngUIProtectionLevels.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIProtectionLevels.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs index 886bfb290731e..e03c5e3756dc1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs @@ -14,10 +14,7 @@ namespace System.Security.Cryptography public partial class CryptoConfig { #if !BROWSER - private const string AssemblyName_Cng = "System.Security.Cryptography.Cng"; - private const string AssemblyName_Csp = "System.Security.Cryptography.Csp"; private const string AssemblyName_Pkcs = "System.Security.Cryptography.Pkcs"; - private const string AssemblyName_X509Certificates = "System.Security.Cryptography.X509Certificates"; private const BindingFlags ConstructorDefault = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance; @@ -128,19 +125,20 @@ private static Dictionary DefaultNameHT Type SHA256DefaultType = typeof(System.Security.Cryptography.SHA256Managed); Type SHA384DefaultType = typeof(System.Security.Cryptography.SHA384Managed); Type SHA512DefaultType = typeof(System.Security.Cryptography.SHA512Managed); + Type SHA1CryptoServiceProviderType = typeof(SHA1CryptoServiceProvider); + Type MD5CryptoServiceProviderType = typeof(MD5CryptoServiceProvider); + Type RSACryptoServiceProviderType = typeof(RSACryptoServiceProvider); + Type DSACryptoServiceProviderType = typeof(DSACryptoServiceProvider); + Type DESCryptoServiceProviderType = typeof(DESCryptoServiceProvider); + Type TripleDESCryptoServiceProviderType = typeof(TripleDESCryptoServiceProvider); + Type RC2CryptoServiceProviderType = typeof(RC2CryptoServiceProvider); + Type AesCryptoServiceProviderType = typeof(AesCryptoServiceProvider); #pragma warning restore SYSLIB0021 +#pragma warning disable SYSLIB0023 // RNGCryptoServiceProvider is obsolete + Type RNGCryptoServiceProviderType = typeof(RNGCryptoServiceProvider); +#pragma warning restore SYSLIB0023 - string SHA1CryptoServiceProviderType = "System.Security.Cryptography.SHA1CryptoServiceProvider, " + AssemblyName_Csp; - string MD5CryptoServiceProviderType = "System.Security.Cryptography.MD5CryptoServiceProvider," + AssemblyName_Csp; - string RSACryptoServiceProviderType = "System.Security.Cryptography.RSACryptoServiceProvider, " + AssemblyName_Csp; - string DSACryptoServiceProviderType = "System.Security.Cryptography.DSACryptoServiceProvider, " + AssemblyName_Csp; - string DESCryptoServiceProviderType = "System.Security.Cryptography.DESCryptoServiceProvider, " + AssemblyName_Csp; - string TripleDESCryptoServiceProviderType = "System.Security.Cryptography.TripleDESCryptoServiceProvider, " + AssemblyName_Csp; - string RC2CryptoServiceProviderType = "System.Security.Cryptography.RC2CryptoServiceProvider, " + AssemblyName_Csp; - string RNGCryptoServiceProviderType = "System.Security.Cryptography.RNGCryptoServiceProvider, " + AssemblyName_Csp; - string AesCryptoServiceProviderType = "System.Security.Cryptography.AesCryptoServiceProvider, " + AssemblyName_Csp; - - string ECDsaCngType = "System.Security.Cryptography.ECDsaCng, " + AssemblyName_Cng; + Type ECDsaCngType = typeof(ECDsaCng); // Random number generator ht.Add("RandomNumberGenerator", RNGCryptoServiceProviderType); @@ -255,17 +253,17 @@ private static Dictionary DefaultNameHT ht.Add("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", HMACSHA512Type); // X509 Extensions (custom decoders) // Basic Constraints OID value - ht.Add("2.5.29.10", "System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension, " + AssemblyName_X509Certificates); - ht.Add("2.5.29.19", "System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension, " + AssemblyName_X509Certificates); + ht.Add("2.5.29.10", typeof(X509Certificates.X509BasicConstraintsExtension)); + ht.Add("2.5.29.19", typeof(X509Certificates.X509BasicConstraintsExtension)); // Subject Key Identifier OID value - ht.Add("2.5.29.14", "System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension, " + AssemblyName_X509Certificates); + ht.Add("2.5.29.14", typeof(X509Certificates.X509SubjectKeyIdentifierExtension)); // Key Usage OID value - ht.Add("2.5.29.15", "System.Security.Cryptography.X509Certificates.X509KeyUsageExtension, " + AssemblyName_X509Certificates); + ht.Add("2.5.29.15", typeof(X509Certificates.X509KeyUsageExtension)); // Enhanced Key Usage OID value - ht.Add("2.5.29.37", "System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension, " + AssemblyName_X509Certificates); + ht.Add("2.5.29.37", typeof(X509Certificates.X509EnhancedKeyUsageExtension)); // X509Chain class can be overridden to use a different chain engine. - ht.Add("X509Chain", "System.Security.Cryptography.X509Certificates.X509Chain, " + AssemblyName_X509Certificates); + ht.Add("X509Chain", typeof(X509Certificates.X509Chain)); // PKCS9 attributes ht.Add("1.2.840.113549.1.9.3", "System.Security.Cryptography.Pkcs.Pkcs9ContentType, " + AssemblyName_Pkcs); diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.NotSupported.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.NotSupported.cs diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs similarity index 87% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs index ce73894fb36e0..4e1c7c22144a6 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspKeyContainerInfo.Windows.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.NativeCrypto; -using Microsoft.Win32.SafeHandles; using System.Runtime.Versioning; namespace System.Security.Cryptography @@ -49,7 +47,7 @@ public bool Accessible { get { - object? retVal = ReadKeyParameterSilent(Constants.CLR_ACCESSIBLE, throwOnNotFound: false); + object? retVal = ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_ACCESSIBLE, throwOnNotFound: false); if (retVal == null) { @@ -74,7 +72,7 @@ public bool Exportable return false; } - return (bool)ReadKeyParameterSilent(Constants.CLR_EXPORTABLE)!; + return (bool)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_EXPORTABLE)!; } } @@ -85,7 +83,7 @@ public bool HardwareDevice { get { - return (bool)ReadDeviceParameterVerifyContext(Constants.CLR_HARDWARE); + return (bool)ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId.CLR_HARDWARE); } } @@ -135,7 +133,7 @@ public bool Protected return true; } - return (bool)ReadKeyParameterSilent(Constants.CLR_PROTECTED)!; + return (bool)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_PROTECTED)!; } } @@ -179,7 +177,7 @@ public bool Removable { get { - return (bool)ReadDeviceParameterVerifyContext(Constants.CLR_REMOVABLE); + return (bool)ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId.CLR_REMOVABLE); } } @@ -190,14 +188,14 @@ public string UniqueKeyContainerName { get { - return (string)ReadKeyParameterSilent(Constants.CLR_UNIQUE_CONTAINER)!; + return (string)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_UNIQUE_CONTAINER)!; } } /// /// Read a parameter from the current key using CRYPT_SILENT, to avoid any potential UI prompts. /// - private object? ReadKeyParameterSilent(int keyParam, bool throwOnNotFound = true) + private object? ReadKeyParameterSilent(CapiHelper.ClrPropertyId keyParam, bool throwOnNotFound = true) { const uint SilentFlags = (uint)Interop.Advapi32.CryptAcquireContextFlags.CRYPT_SILENT; @@ -210,7 +208,7 @@ public string UniqueKeyContainerName { if (throwOnNotFound) { - throw new CryptographicException(SR.Format(SR.Cryptography_CSP_NotFound, "Error")); + throw new CryptographicException(SR.Cryptography_CSP_NotFound); } return null; @@ -224,7 +222,7 @@ public string UniqueKeyContainerName /// /// Read a parameter using VERIFY_CONTEXT to read from the device being targeted by _parameters /// - private object ReadDeviceParameterVerifyContext(int keyParam) + private object ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId keyParam) { CspParameters parameters = new CspParameters(_parameters); @@ -243,7 +241,7 @@ private object ReadDeviceParameterVerifyContext(int keyParam) { if (hr != CapiHelper.S_OK) { - throw new CryptographicException(SR.Format(SR.Cryptography_CSP_NotFound, "Error")); + throw new CryptographicException(SR.Cryptography_CSP_NotFound); } object retVal = CapiHelper.GetProviderParameter(safeProvHandle, parameters.KeyNumber, keyParam); diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspParameters.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspParameters.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspParameters.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspParameters.cs index 67cb9c55f8632..0053bb1225862 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspParameters.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspParameters.cs @@ -1,11 +1,8 @@ // 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.Diagnostics; -using System.Security.Cryptography; using System.Runtime.Versioning; -using Internal.NativeCrypto; namespace System.Security.Cryptography { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspProviderFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspProviderFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CspProviderFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CspProviderFlags.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.NotSupported.cs new file mode 100644 index 0000000000000..64ffcfa2fc85b --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.NotSupported.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + [Obsolete(Obsoletions.DerivedCryptographicTypesMessage, DiagnosticId = Obsoletions.DerivedCryptographicTypesDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class DESCryptoServiceProvider : DES + { + [SuppressMessage("Microsoft.Security", "CA5351", Justification = "This is the implementation of DESCryptoServiceProvider")] + public DESCryptoServiceProvider() + { + throw new PlatformNotSupportedException(); + } + + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + public override void GenerateIV() { } + public override void GenerateKey() { } + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs index 34f2b13647a87..59dfff8fa188b 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Unix.cs @@ -30,10 +30,10 @@ public override int BlockSize public override ICryptoTransform CreateEncryptor() => _impl.CreateEncryptor(); public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateEncryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateEncryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateDecryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateDecryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs index 5829aa05f0355..3dd55e352f74a 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs @@ -3,7 +3,6 @@ using System.ComponentModel; using Internal.Cryptography; -using Internal.NativeCrypto; namespace System.Security.Cryptography { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.OpenSsl.cs new file mode 100644 index 0000000000000..3b4c8b052ab8a --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.OpenSsl.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class DSA : AsymmetricAlgorithm + { + private static DSA CreateCore() + { + return new DSAWrapper(new DSAOpenSsl()); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.SecurityTransforms.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.SecurityTransforms.cs new file mode 100644 index 0000000000000..3ce3230b5368d --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.SecurityTransforms.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class DSA : AsymmetricAlgorithm + { + private static DSA CreateCore() + { + return new DSAImplementation.DSASecurityTransforms(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.Windows.cs new file mode 100644 index 0000000000000..fa667bb92ca33 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.Create.Windows.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class DSA : AsymmetricAlgorithm + { + private static DSA CreateCore() + { + return new DSAWrapper(new DSACng()); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.cs index c19b7103384cc..0990807ceed7a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSA.cs @@ -127,10 +127,8 @@ public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) /// public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -139,14 +137,12 @@ public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, DSASignatur public virtual byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, offset, count, hashAlgorithm); return CreateSignature(hash); @@ -195,14 +191,12 @@ public byte[] SignData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -242,10 +236,8 @@ protected virtual byte[] SignDataCore( public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, hashAlgorithm); return CreateSignature(hash); @@ -274,10 +266,8 @@ public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) /// public byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -314,16 +304,13 @@ public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgo public virtual bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, offset, count, hashAlgorithm); return VerifySignature(hash, signature); @@ -374,16 +361,13 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -392,12 +376,9 @@ public bool VerifyData( public virtual bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, hashAlgorithm); return VerifySignature(hash, signature); @@ -544,8 +525,7 @@ public virtual bool TrySignData( HashAlgorithmName hashAlgorithm, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (TryHashData(data, destination, hashAlgorithm, out int hashLength) && TryCreateSignature(destination.Slice(0, hashLength), destination, out bytesWritten)) @@ -589,8 +569,7 @@ public bool TrySignData( DSASignatureFormat signatureFormat, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -634,8 +613,7 @@ public virtual bool VerifyData( ReadOnlySpan signature, HashAlgorithmName hashAlgorithm) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); return VerifyDataCore(data, signature, hashAlgorithm, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); } @@ -668,12 +646,9 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -708,12 +683,9 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -765,8 +737,7 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -933,9 +904,6 @@ private byte[] HashSpanToArray(ReadOnlySpan data, HashAlgorithmName hashAl private static Exception DerivedClassMustOverride() => new NotImplementedException(SR.NotSupported_SubclassOverride); - internal static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); - public override bool TryExportEncryptedPkcs8PrivateKey( ReadOnlySpan passwordBytes, PbeParameters pbeParameters, diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.ImportExport.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.ImportExport.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.ImportExport.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.ImportExport.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.Key.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.Key.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/DSACng.Key.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.Key.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.cs index 8ede9bb6dcf5c..4bdd219dfb8f6 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACng.cs @@ -1,149 +1,44 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System.Diagnostics; +using System.Runtime.Versioning; +using Internal.Cryptography; namespace System.Security.Cryptography { - public partial class DSA : AsymmetricAlgorithm + public sealed partial class DSACng : DSA { - private static DSA CreateCore() + private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(DSACng)); + + /// + /// Creates a new DSACng object that will use the specified key. The key's + /// must be Dsa. This constructor + /// creates a copy of the key. Hence, the caller can safely dispose of the + /// passed in key and continue using the DSACng object. + /// + /// Key to use for DSA operations + /// if is not an DSA key + /// if is null. + [SupportedOSPlatform("windows")] + public DSACng(CngKey key) { - return new DSAImplementation.DSACng(); - } - } - - internal static partial class DSAImplementation - { - public sealed partial class DSACng : DSA - { - private SafeNCryptKeyHandle? _keyHandle; - private int _lastKeySize; - private bool _disposed; - - private void ThrowIfDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(RSA)); - } - } - - private SafeNCryptKeyHandle GetDuplicatedKeyHandle() - { - ThrowIfDisposed(); - - int keySize = KeySize; - - if (_lastKeySize != keySize) - { - if (_keyHandle != null) - { - _keyHandle.Dispose(); - } - - const string BCRYPT_DSA_ALGORITHM = "DSA"; - - _keyHandle = CngKeyLite.GenerateNewExportableKey(BCRYPT_DSA_ALGORITHM, keySize); - _lastKeySize = keySize; - } - - return new DuplicateSafeNCryptKeyHandle(_keyHandle!); - } - - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - // Use generic blob type for multiple version support - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_PRIVATE_KEY_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_PUBLIC_KEY_BLOB; - - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + if (key == null) + throw new ArgumentNullException(nameof(key)); - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportPkcs8KeyBlob(keyHandle, pkcs8Password, kdfCount); - } - } + if (key.AlgorithmGroup != CngAlgorithmGroup.Dsa) + throw new ArgumentException(SR.Cryptography_ArgDSARequiresDSAKey, nameof(key)); - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.TryExportPkcs8KeyBlob( - keyHandle, - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - } - - private void ImportKeyBlob(byte[] dsaBlob, bool includePrivate) - { - ThrowIfDisposed(); - - // Use generic blob type for multiple version support - string blobType = includePrivate ? - Interop.BCrypt.KeyBlobType.BCRYPT_PRIVATE_KEY_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_PUBLIC_KEY_BLOB; - - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, dsaBlob); - SetKeyHandle(keyHandle); - } - - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - ThrowIfDisposed(); - - SafeNCryptKeyHandle keyHandle = response.KeyHandle; - SetKeyHandle(keyHandle); - } - - private void SetKeyHandle(SafeNCryptKeyHandle keyHandle) - { - Debug.Assert(!keyHandle.IsInvalid); - - _keyHandle = keyHandle; - - int newKeySize = CngKeyLite.GetKeyLength(keyHandle); - - // Our LegalKeySizes value stores the values that we encoded as being the correct - // legal key size limitations for this algorithm, as documented on MSDN. - // - // But on a new OS version we might not question if our limit is accurate, or MSDN - // could have been inaccurate to start with. - // - // Since the key is already loaded, we know that Windows thought it to be valid; - // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance - // check. - ForceSetKeySize(newKeySize); - _lastKeySize = newKeySize; - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _keyHandle?.Dispose(); - _keyHandle = null; - _disposed = true; - } + Key = CngAlgorithmCore.Duplicate(key); + } + protected override void Dispose(bool disposing) + { + _core.Dispose(); + } - base.Dispose(disposing); - } + private void ThrowIfDisposed() + { + _core.ThrowIfDisposed(); } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.NotSupported.cs new file mode 100644 index 0000000000000..6a6c3f910d8eb --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.NotSupported.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.IO; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.Versioning; + +namespace System.Security.Cryptography +{ + public sealed class DSACryptoServiceProvider : DSA, ICspAsymmetricAlgorithm + { + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public DSACryptoServiceProvider() + { + throw new PlatformNotSupportedException(); + } + + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public DSACryptoServiceProvider(int dwKeySize) : base() + { + throw new PlatformNotSupportedException(); + } + + [SupportedOSPlatform("windows")] + public DSACryptoServiceProvider(int dwKeySize, CspParameters parameters) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspParameters))); + } + + [SupportedOSPlatform("windows")] + public DSACryptoServiceProvider(CspParameters parameters) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspParameters))); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "This is the implementation of DSACryptoServiceProvider")] + public override byte[] CreateSignature(byte[] rgbHash) => default!; + + [SupportedOSPlatform("windows")] + public CspKeyContainerInfo CspKeyContainerInfo + { + get { throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspKeyContainerInfo))); } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "This is the implementation of DSACryptoServiceProvider")] + public byte[] SignHash(byte[] rgbHash, string str) => default!; + + public byte[] ExportCspBlob(bool includePrivateParameters) => default!; + public override DSAParameters ExportParameters(bool includePrivateParameters) => default; + public void ImportCspBlob(byte[] keyBlob) { } + public override void ImportParameters(DSAParameters parameters) { } + public bool PersistKeyInCsp { get; set; } + public bool PublicOnly => default; + public byte[] SignData(byte[] buffer) => default!; + public byte[] SignData(byte[] buffer, int offset, int count) => default!; + public byte[] SignData(Stream inputStream) => default!; + public bool VerifyData(byte[] rgbData, byte[] rgbSignature) => default; + public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) => default; + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) => default; + + // UseMachineKeyStore has no effect in non-Windows + public static bool UseMachineKeyStore { get; set; } + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs index 8790cc96a79b6..252f93272e783 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.NativeCrypto; using System.IO; using System.Diagnostics; using System.Runtime.Versioning; @@ -37,11 +36,15 @@ public sealed class DSACryptoServiceProvider : DSA, ICspAsymmetricAlgorithm ? s_legalKeySizesAndroid : s_legalKeySizesWindowsCsp; + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] public DSACryptoServiceProvider() : this(DefaultKeySize) { } + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] public DSACryptoServiceProvider(int dwKeySize) : base() { if (dwKeySize < 0) diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs index 186f9c80100c5..0a53d8af55034 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.IO; using System.Runtime.Versioning; -using Internal.NativeCrypto; namespace System.Security.Cryptography { @@ -14,7 +13,7 @@ public sealed class DSACryptoServiceProvider : DSA, ICspAsymmetricAlgorithm private int _keySize; private readonly CspParameters _parameters; private readonly bool _randomKeyContainer; - private SafeKeyHandle? _safeKeyHandle; + private SafeCapiKeyHandle? _safeKeyHandle; private SafeProvHandle? _safeProvHandle; private readonly SHA1 _sha1; private static volatile CspProviderFlags s_useMachineKeyStore; @@ -23,6 +22,8 @@ public sealed class DSACryptoServiceProvider : DSA, ICspAsymmetricAlgorithm /// /// Initializes a new instance of the DSACryptoServiceProvider class. /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] public DSACryptoServiceProvider() : this( new CspParameters(CapiHelper.DefaultDssProviderType, @@ -36,6 +37,8 @@ public DSACryptoServiceProvider() /// Initializes a new instance of the DSACryptoServiceProvider class with the specified key size. /// /// The size of the key for the asymmetric algorithm in bits. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] public DSACryptoServiceProvider(int dwKeySize) : this(dwKeySize, new CspParameters(CapiHelper.DefaultDssProviderType, @@ -83,7 +86,7 @@ public DSACryptoServiceProvider(int dwKeySize, CspParameters? parameters) if (!_randomKeyContainer) { // Force-read the SafeKeyHandle property, which will summon it into existence. - SafeKeyHandle localHandle = SafeKeyHandle; + SafeCapiKeyHandle localHandle = SafeKeyHandle; Debug.Assert(localHandle != null); } } @@ -126,7 +129,7 @@ private SafeProvHandle SafeProvHandle if (current != null) { - SafeKeyHandle? keyHandle = _safeKeyHandle; + SafeCapiKeyHandle? keyHandle = _safeKeyHandle; _safeKeyHandle = null; keyHandle?.Dispose(); current.Dispose(); @@ -137,7 +140,7 @@ private SafeProvHandle SafeProvHandle } } - private SafeKeyHandle SafeKeyHandle + private SafeCapiKeyHandle SafeKeyHandle { get { @@ -147,7 +150,7 @@ private SafeKeyHandle SafeKeyHandle { if (_safeKeyHandle == null) { - SafeKeyHandle hKey = CapiHelper.GetKeyPairHelper( + SafeCapiKeyHandle hKey = CapiHelper.GetKeyPairHelper( CapiHelper.CspAlgorithmType.Dss, _parameters, _keySize, @@ -169,7 +172,7 @@ private SafeKeyHandle SafeKeyHandle { lock (_parameters) { - SafeKeyHandle? current = _safeKeyHandle; + SafeCapiKeyHandle? current = _safeKeyHandle; if (ReferenceEquals(value, current)) { @@ -192,7 +195,7 @@ public CspKeyContainerInfo CspKeyContainerInfo { // .NET Framework compat: Read the SafeKeyHandle property to force the key to load, // because it might throw here. - SafeKeyHandle localHandle = SafeKeyHandle; + SafeCapiKeyHandle localHandle = SafeKeyHandle; Debug.Assert(localHandle != null); return new CspKeyContainerInfo(_parameters, _randomKeyContainer); @@ -203,7 +206,7 @@ public override int KeySize { get { - byte[] keySize = CapiHelper.GetKeyParameter(SafeKeyHandle, Constants.CLR_KEYLEN); + byte[] keySize = CapiHelper.GetKeyParameter(SafeKeyHandle, CapiHelper.ClrPropertyId.CLR_KEYLEN); _keySize = BinaryPrimitives.ReadInt32LittleEndian(keySize); return _keySize; } @@ -246,7 +249,7 @@ public bool PublicOnly { get { - byte[] publicKey = CapiHelper.GetKeyParameter(SafeKeyHandle, Constants.CLR_PUBLICKEYONLY); + byte[] publicKey = CapiHelper.GetKeyParameter(SafeKeyHandle, CapiHelper.ClrPropertyId.CLR_PUBLICKEYONLY); return (publicKey[0] == 1); } } @@ -336,7 +339,7 @@ public void ImportCspBlob(byte[] keyBlob) { ThrowIfDisposed(); - SafeKeyHandle safeKeyHandle; + SafeCapiKeyHandle safeKeyHandle; if (IsPublic(keyBlob)) { diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/DSAOpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAOpenSsl.cs similarity index 86% rename from src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/DSAOpenSsl.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAOpenSsl.cs index 3a2adb68ebb6e..6847a0a1f56a7 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/DSAOpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAOpenSsl.cs @@ -1,12 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { public sealed partial class DSAOpenSsl : DSA { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public DSAOpenSsl(DSAParameters parameters) { ThrowIfNotSupported(); @@ -25,6 +31,11 @@ public DSAOpenSsl(DSAParameters parameters) /// /// /// is not a valid enveloped DSA* + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public DSAOpenSsl(SafeEvpPKeyHandle pkeyHandle) { if (pkeyHandle == null) @@ -54,6 +65,11 @@ public DSAOpenSsl(SafeEvpPKeyHandle pkeyHandle) /// /// A pointer to an OpenSSL DSA* /// is invalid + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public DSAOpenSsl(IntPtr handle) { if (handle == IntPtr.Zero) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAWrapper.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAWrapper.cs new file mode 100644 index 0000000000000..904ed56bfb6b8 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/DSAWrapper.cs @@ -0,0 +1,165 @@ +// 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 System.IO; +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + internal sealed class DSAWrapper : DSA + { + private readonly DSA _wrapped; + + internal DSAWrapper(DSA wrapped) + { + Debug.Assert(wrapped != null); + _wrapped = wrapped; + } + + public override DSAParameters ExportParameters(bool includePrivateParameters) => + _wrapped.ExportParameters(includePrivateParameters); + + public override void ImportParameters(DSAParameters parameters) => + _wrapped.ImportParameters(parameters); + + public override byte[] CreateSignature(byte[] rgbHash) => + _wrapped.CreateSignature(rgbHash); + + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) => + _wrapped.VerifySignature(rgbHash, rgbSignature); + + public override byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + _wrapped.SignData(data, offset, count, hashAlgorithm); + + public override byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) => + _wrapped.SignData(data, hashAlgorithm); + + public override bool VerifyData( + byte[] data, + int offset, + int count, + byte[] signature, + HashAlgorithmName hashAlgorithm) => + _wrapped.VerifyData(data, offset, count, signature, hashAlgorithm); + + public override bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm) => + _wrapped.VerifyData(data, signature, hashAlgorithm); + + public override bool TryCreateSignature(ReadOnlySpan hash, Span destination, out int bytesWritten) => + _wrapped.TryCreateSignature(hash, destination, out bytesWritten); + + public override bool TrySignData( + ReadOnlySpan data, + Span destination, + HashAlgorithmName hashAlgorithm, + out int bytesWritten) => + _wrapped.TrySignData(data, destination, hashAlgorithm, out bytesWritten); + + public override bool VerifyData( + ReadOnlySpan data, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm) => + _wrapped.VerifyData(data, signature, hashAlgorithm); + + public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) => + _wrapped.VerifySignature(hash, signature); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters, destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(password, pbeParameters, destination, out bytesWritten); + + public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) => + _wrapped.TryExportPkcs8PrivateKey(destination, out bytesWritten); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _wrapped.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override unsafe void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + + public override unsafe void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + + public override unsafe void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportPkcs8PrivateKey(source, out bytesRead); + + public override void ImportSubjectPublicKeyInfo(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportSubjectPublicKeyInfo(source, out bytesRead); + + public override void ImportFromPem(ReadOnlySpan input) => _wrapped.ImportFromPem(input); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => + _wrapped.ImportFromEncryptedPem(input, password); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => + _wrapped.ImportFromEncryptedPem(input, passwordBytes); + + public override void FromXmlString(string xmlString) => _wrapped.FromXmlString(xmlString); + + public override string ToXmlString(bool includePrivateParameters) => + _wrapped.ToXmlString(includePrivateParameters); + + public override int KeySize + { + get => _wrapped.KeySize; + set => _wrapped.KeySize = value; + } + + public override KeySizes[] LegalKeySizes => _wrapped.LegalKeySizes; + + public override string? SignatureAlgorithm => _wrapped.SignatureAlgorithm; + + public override string? KeyExchangeAlgorithm => _wrapped.KeyExchangeAlgorithm; + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _wrapped.Dispose(); + } + } + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(password, pbeParameters); + + public override byte[] ExportPkcs8PrivateKey() => _wrapped.ExportPkcs8PrivateKey(); + + public override byte[] ExportSubjectPublicKeyInfo() => _wrapped.ExportSubjectPublicKeyInfo(); + + public override bool Equals(object? obj) => _wrapped.Equals(obj); + + public override int GetHashCode() => _wrapped.GetHashCode(); + + public override string ToString() => _wrapped.ToString()!; + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECCng.ImportExport.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCng.ImportExport.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECCng.ImportExport.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCng.ImportExport.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCngKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCngKey.cs index 9da73eeb398a3..dc4c3c812399c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCngKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCngKey.cs @@ -53,7 +53,7 @@ internal SafeNCryptKeyHandle GetDuplicatedKeyHandle(int callerKeySizeProperty) if (ECCng.IsECNamedCurve(_lastAlgorithm)) { // Curve was previously created, so use that - return new DuplicateSafeNCryptKeyHandle(_keyHandle!); + return _keyHandle!.Duplicate(); } else { @@ -97,7 +97,7 @@ internal SafeNCryptKeyHandle GetDuplicatedKeyHandle(int callerKeySizeProperty) KeySize = callerKeySizeProperty; } - return new DuplicateSafeNCryptKeyHandle(_keyHandle!); + return _keyHandle!.Duplicate(); } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCurve.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCurve.cs index a14e816f799df..5876e483bcb6d 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCurve.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECCurve.cs @@ -79,7 +79,7 @@ private set throw new ArgumentNullException(nameof(Oid)); if (string.IsNullOrEmpty(value.Value) && string.IsNullOrEmpty(value.FriendlyName)) - throw new ArgumentException(SR.Cryptography_InvalidCurveOid); + throw new ArgumentException(SR.Format(SR.Cryptography_InvalidCurveOid, value.Value)); _oid = value; } @@ -197,7 +197,7 @@ public void Validate() if (Oid == null || (string.IsNullOrEmpty(Oid.FriendlyName) && string.IsNullOrEmpty(Oid.Value))) { - throw new CryptographicException(SR.Cryptography_InvalidCurveOid); + throw new CryptographicException(SR.Format(SR.Cryptography_InvalidCurveOid, Oid?.Value)); } } else if (IsExplicit) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.Cng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.Cng.cs index d8d4782ef63fb..48eb815bd5ee9 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.Cng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.Cng.cs @@ -7,22 +7,22 @@ public abstract partial class ECDiffieHellman : ECAlgorithm { public static new partial ECDiffieHellman Create() { - return new ECDiffieHellmanImplementation.ECDiffieHellmanCng(); + return new ECDiffieHellmanWrapper(new ECDiffieHellmanCng()); } public static partial ECDiffieHellman Create(ECCurve curve) { - return new ECDiffieHellmanImplementation.ECDiffieHellmanCng(curve); + return new ECDiffieHellmanWrapper(new ECDiffieHellmanCng(curve)); } public static partial ECDiffieHellman Create(ECParameters parameters) { - ECDiffieHellman ecdh = new ECDiffieHellmanImplementation.ECDiffieHellmanCng(); + ECDiffieHellman ecdh = new ECDiffieHellmanCng(); try { ecdh.ImportParameters(parameters); - return ecdh; + return new ECDiffieHellmanWrapper(ecdh); } catch { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.OpenSsl.cs index 1fa4161fa7f13..da2747f534277 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellman.Create.OpenSsl.cs @@ -7,22 +7,22 @@ public abstract partial class ECDiffieHellman : ECAlgorithm { public static new partial ECDiffieHellman Create() { - return new ECDiffieHellmanImplementation.ECDiffieHellmanOpenSsl(); + return new ECDiffieHellmanWrapper(new ECDiffieHellmanOpenSsl()); } public static partial ECDiffieHellman Create(ECCurve curve) { - return new ECDiffieHellmanImplementation.ECDiffieHellmanOpenSsl(curve); + return new ECDiffieHellmanWrapper(new ECDiffieHellmanOpenSsl(curve)); } public static partial ECDiffieHellman Create(ECParameters parameters) { - ECDiffieHellman ecdh = new ECDiffieHellmanImplementation.ECDiffieHellmanOpenSsl(); + ECDiffieHellman ecdh = new ECDiffieHellmanOpenSsl(); try { ecdh.ImportParameters(parameters); - return ecdh; + return new ECDiffieHellmanWrapper(ecdh); } catch { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs index d3e2c527169c3..deca9cfd932ee 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Derive.cs @@ -1,71 +1,146 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.NativeCrypto; +using System.Diagnostics; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman { - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) { - // For the public ECDiffieHellmanCng this is exposed as the HashAlgorithm property - // which is a CngAlgorithm type. We're not doing that, but we do need the default value - // for DeriveKeyMaterial. - public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); + + if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey) { - if (otherPartyPublicKey == null) + using (CngKey import = otherKey.Import()) { - throw new ArgumentNullException(nameof(otherPartyPublicKey)); + return DeriveKeyMaterial(import); } + } - // ECDiffieHellmanCng on .NET Framework will throw an ArgumentException in this method - // if otherPartyPublicKey is not an ECDiffieHellmanCngPublicKey. All of the other methods - // will use Import/Export to coerce the correct type for interop. + // This deviates from the .NET Framework behavior. .NET Framework can't handle unknown public + // key types, but on .NET Core there are automatically two: the public class produced by + // this class' PublicKey member, and the private class produced by ECDiffieHellman.Create().PublicKey + // + // So let's just work. + ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); - // None of the other Core types will match that behavior, so the ECDiffieHellman.Create() on - // Windows on .NET Core won't, either. + using (ECDiffieHellmanCng otherPartyCng = new ECDiffieHellmanCng()) + { + otherPartyCng.ImportParameters(otherPartyParameters); - // The default behavior for ECDiffieHellmanCng / ECDiffieHellman.Create() on .NET Framework was - // to derive from hash, no prepend, no append, SHA-2-256. - return DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256); + using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey) + using (CngKey importedKey = otherKey.Import()) + { + return DeriveKeyMaterial(importedKey); + } } + } + + public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) + { + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); + if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) + throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); + if (otherPartyPublicKey.KeySize != KeySize) + throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); + + // Setting the flag to UseSecretAsHmacKey even when the KDF isn't HMAC, because that's what .NET Framework does. + Interop.NCrypt.SecretAgreementFlags flags = + UseSecretAgreementAsHmacKey + ? Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey + : Interop.NCrypt.SecretAgreementFlags.None; - private SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) + using (SafeNCryptSecretHandle handle = DeriveSecretAgreementHandle(otherPartyPublicKey)) { - if (otherPartyPublicKey == null) + switch (KeyDerivationFunction) { - throw new ArgumentNullException(nameof(otherPartyPublicKey)); + case ECDiffieHellmanKeyDerivationFunction.Hash: + return Interop.NCrypt.DeriveKeyMaterialHash( + handle, + HashAlgorithm.Algorithm, + _secretPrepend, + _secretAppend, + flags); + case ECDiffieHellmanKeyDerivationFunction.Hmac: + return Interop.NCrypt.DeriveKeyMaterialHmac( + handle, + HashAlgorithm.Algorithm, + _hmacKey, + _secretPrepend, + _secretAppend, + flags); + case ECDiffieHellmanKeyDerivationFunction.Tls: + if (_label == null || _seed == null) + { + throw new InvalidOperationException(SR.Cryptography_TlsRequiresLabelAndSeed); + } + + return Interop.NCrypt.DeriveKeyMaterialTls( + handle, + _label, + _seed, + flags); + default: + Debug.Fail($"Unknown KDF ({KeyDerivationFunction})"); + // Match .NET Framework behavior + goto case ECDiffieHellmanKeyDerivationFunction.Tls; } + } + } - ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); + /// + /// Get a handle to the secret agreement generated between two parties + /// + public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) + { + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); - using (ECDiffieHellmanCng otherPartyCng = (ECDiffieHellmanCng)Create(otherPartyParameters)) - using (SafeNCryptKeyHandle otherPartyHandle = otherPartyCng.GetDuplicatedKeyHandle()) + if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey) + { + using (CngKey importedKey = otherKey.Import()) { - string? importedKeyAlgorithmGroup = - CngKeyLite.GetPropertyAsString( - otherPartyHandle, - CngKeyLite.KeyPropertyName.AlgorithmGroup, - CngPropertyOptions.None); - - if (importedKeyAlgorithmGroup != BCryptNative.AlgorithmName.ECDH) - { - throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); - } - - if (CngKeyLite.GetKeyLength(otherPartyHandle) != KeySize) - { - throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); - } - - using (SafeNCryptKeyHandle localHandle = GetDuplicatedKeyHandle()) - { - return Interop.NCrypt.DeriveSecretAgreement(localHandle, otherPartyHandle); - } + return DeriveSecretAgreementHandle(importedKey); } } + + ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); + + using (ECDiffieHellmanCng otherPartyCng = new ECDiffieHellmanCng()) + { + otherPartyCng.ImportParameters(otherPartyParameters); + + using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey) + using (CngKey importedKey = otherKey.Import()) + { + return DeriveSecretAgreementHandle(importedKey); + } + } + } + + /// + /// Get a handle to the secret agreement between two parties + /// + public SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) + { + if (otherPartyPublicKey == null) + throw new ArgumentNullException(nameof(otherPartyPublicKey)); + if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) + throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); + if (otherPartyPublicKey.KeySize != KeySize) + throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); + + // This looks strange, but the Handle property returns a duplicate so we need to dispose of it when we're done + using (SafeNCryptKeyHandle localHandle = Key.Handle) + using (SafeNCryptKeyHandle otherPartyHandle = otherPartyPublicKey.Handle) + { + return Interop.NCrypt.DeriveSecretAgreement(localHandle, otherPartyHandle); + } } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs index 5ccb8f4468213..baf5046f242e3 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Key.cs @@ -1,45 +1,135 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.NativeCrypto; +using System.Diagnostics; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { - internal static partial class ECDiffieHellmanImplementation + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman { - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + /// + /// Public key used to generate key material with the second party + /// + public override ECDiffieHellmanPublicKey PublicKey { - private readonly ECCngKey _key = new ECCngKey(BCryptNative.AlgorithmName.ECDH, nameof(ECDiffieHellman)); - - private string? GetCurveName(out string? oidValue) => _key.GetCurveName(KeySize, out oidValue); + get + { + return ECDiffieHellmanCngPublicKey.FromKey(Key); + } + } - public override void GenerateKey(ECCurve curve) + /// + /// Gets the key that will be used by the ECDH object for any cryptographic operation that it uses. + /// This key object will be disposed if the key is reset, for instance by changing the KeySize + /// property, using ImportParamers to create a new key, or by Disposing of the parent ECDH object. + /// Therefore, you should make sure that the key object is no longer used in these scenarios. This + /// object will not be the same object as the CngKey passed to the ECDHCng constructor if that + /// constructor was used, however it will point at the same CNG key. + /// + public CngKey Key + { + get { - _key.GenerateKey(curve); - ForceSetKeySize(_key.KeySize); + return GetKey(); } - private SafeNCryptKeyHandle GetDuplicatedKeyHandle() => _key.GetDuplicatedKeyHandle(KeySize); + private set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + if (value.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) + throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(value)); - private void DisposeKey() => _key.DisposeKey(); + _core.SetKey(value); - /// - /// Public key used to generate key material with the second party - /// - public override ECDiffieHellmanPublicKey PublicKey + // LegalKeySizes stores the values for either the current named curve or for the three + // curves that use size instead of name + ForceSetKeySize(value.KeySize); + } + } + + public override void GenerateKey(ECCurve curve) + { + curve.Validate(); + _core.DisposeKey(); + + if (curve.IsNamed) { - get + if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); + + // Map curve name to algorithm to support pre-Win10 curves + CngAlgorithm alg = CngKey.EcdhCurveNameToAlgorithm(curve.Oid.FriendlyName); + if (CngKey.IsECNamedCurve(alg.Algorithm)) { - string? curveName = GetCurveName(out _); + CngKey key = _core.GetOrGenerateKey(curve); + ForceSetKeySize(key.KeySize); + } + else + { + int keySize; + // Get the proper KeySize from algorithm name + if (alg == CngAlgorithm.ECDiffieHellmanP256) + keySize = 256; + else if (alg == CngAlgorithm.ECDiffieHellmanP384) + keySize = 384; + else if (alg == CngAlgorithm.ECDiffieHellmanP521) + keySize = 521; + else + { + Debug.Fail($"Unknown algorithm {alg}"); + throw new ArgumentException(SR.Cryptography_InvalidKeySize); + } + _core.GetOrGenerateKey(keySize, alg); + ForceSetKeySize(keySize); + } + } + else if (curve.IsExplicit) + { + CngKey key = _core.GetOrGenerateKey(curve); + ForceSetKeySize(key.KeySize); + } + else + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + } + } + + private CngKey GetKey() + { + CngKey key; - return new ECDiffieHellmanCngPublicKey( - curveName == null - ? ExportFullKeyBlob(includePrivateParameters: false) - : ExportKeyBlob(includePrivateParameters: false), - curveName); + if (_core.IsKeyGeneratedNamedCurve()) + { + // Curve was previously created, so use that + key = _core.GetOrGenerateKey(null); + } + else + { + CngAlgorithm algorithm; + + // Map the current key size to a CNG algorithm name + int keySize = KeySize; + switch (keySize) + { + case 256: + algorithm = CngAlgorithm.ECDiffieHellmanP256; + break; + case 384: + algorithm = CngAlgorithm.ECDiffieHellmanP384; + break; + case 521: + algorithm = CngAlgorithm.ECDiffieHellmanP521; + break; + default: + Debug.Fail("Should not have invalid key size"); + throw new ArgumentException(SR.Cryptography_InvalidKeySize); } + key = _core.GetOrGenerateKey(keySize, algorithm); } + + return key; } } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECDiffieHellmanCng.Xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.Xml.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.cs index be34cc620bd82..f4a574a67dcc3 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCng.cs @@ -1,121 +1,200 @@ // 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 Microsoft.Win32.SafeHandles; -using static Internal.NativeCrypto.BCryptNative; +using System.Runtime.Versioning; namespace System.Security.Cryptography { - internal static partial class ECDiffieHellmanImplementation + /// + /// Wrapper for CNG's implementation of elliptic curve Diffie-Hellman key exchange + /// + public sealed partial class ECDiffieHellmanCng : ECDiffieHellman { - public sealed partial class ECDiffieHellmanCng : ECDiffieHellman + private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(ECDiffieHellmanCng)) { DefaultKeyType = CngAlgorithm.ECDiffieHellman }; + private CngAlgorithm _hashAlgorithm = CngAlgorithm.Sha256; + private ECDiffieHellmanKeyDerivationFunction _kdf = ECDiffieHellmanKeyDerivationFunction.Hash; + private byte[]? _hmacKey; + private byte[]? _label; + private byte[]? _secretAppend; + private byte[]? _secretPrepend; + private byte[]? _seed; + + [SupportedOSPlatform("windows")] + public ECDiffieHellmanCng(CngKey key) { - protected override void Dispose(bool disposing) + if (key == null) + throw new ArgumentNullException(nameof(key)); + + if (key.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) + throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(key)); + + Key = CngAlgorithmCore.Duplicate(key); + } + + /// + /// Hash algorithm used with the Hash and HMAC KDFs + /// + public CngAlgorithm HashAlgorithm + { + get { - if (disposing) + return _hashAlgorithm; + } + + set + { + if (_hashAlgorithm == null) { - _key.FullDispose(); + throw new ArgumentNullException(nameof(value)); } - base.Dispose(disposing); + _hashAlgorithm = value; } + } - private void ThrowIfDisposed() + /// + /// KDF used to transform the secret agreement into key material + /// + public ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction + { + get { - _key.ThrowIfDisposed(); + return _kdf; } - private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) + set { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPUBLIC_BLOB; + if (value < ECDiffieHellmanKeyDerivationFunction.Hash || value > ECDiffieHellmanKeyDerivationFunction.Tls) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecfullKeyBlob); + _kdf = value; + } + } - Debug.Assert(!keyHandle.IsInvalid); + /// + /// Key used with the HMAC KDF + /// + public byte[]? HmacKey + { + get { return _hmacKey; } + set { _hmacKey = value; } + } - _key.SetHandle(keyHandle, AlgorithmName.ECDH); - ForceSetKeySize(_key.KeySize); - } + /// + /// Label bytes used for the TLS KDF + /// + public byte[]? Label + { + get { return _label; } + set { _label = value; } + } - private void ImportKeyBlob(byte[] ecKeyBlob, string curveName, bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; + /// + /// Bytes to append to the raw secret agreement before processing by the KDF + /// + public byte[]? SecretAppend + { + get { return _secretAppend; } + set { _secretAppend = value; } + } - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecKeyBlob, curveName); + /// + /// Bytes to prepend to the raw secret agreement before processing by the KDF + /// + public byte[]? SecretPrepend + { + get { return _secretPrepend; } + set { _secretPrepend = value; } + } - Debug.Assert(!keyHandle.IsInvalid); + /// + /// Seed bytes used for the TLS KDF + /// + public byte[]? Seed + { + get { return _seed; } + set { _seed = value; } + } - _key.SetHandle(keyHandle, ECCng.EcdhCurveNameToAlgorithm(curveName)); - ForceSetKeySize(_key.KeySize); - } + /// + /// Use the secret agreement as the HMAC key rather than supplying a seperate one + /// + public bool UseSecretAgreementAsHmacKey + { + get { return HmacKey == null; } + } - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; + protected override void Dispose(bool disposing) + { + _core.Dispose(); + } - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + private void ThrowIfDisposed() + { + _core.ThrowIfDisposed(); + } - private byte[] ExportFullKeyBlob(bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPUBLIC_BLOB; + private void DisposeKey() + { + _core.DisposeKey(); + } - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + internal string? GetCurveName(out string? oidValue) + { + return Key.GetCurveName(out oidValue); + } - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportPkcs8KeyBlob(keyHandle, pkcs8Password, kdfCount); - } - } + private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) + { + Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); + } - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.TryExportPkcs8KeyBlob( - keyHandle, - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - } + private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) + { + Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); + } - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - SafeNCryptKeyHandle keyHandle = response.KeyHandle; + private byte[] ExportKeyBlob(bool includePrivateParameters) + { + return ECCng.ExportKeyBlob(Key, includePrivateParameters); + } - _key.SetHandle( - keyHandle, - CngKeyLite.GetPropertyAsString( - keyHandle, - CngKeyLite.KeyPropertyName.Algorithm, - CngPropertyOptions.None)); + private byte[] ExportFullKeyBlob(bool includePrivateParameters) + { + return ECCng.ExportFullKeyBlob(Key, includePrivateParameters); + } - ForceSetKeySize(_key.KeySize); - } + private void AcceptImport(CngPkcs8.Pkcs8Response response) + { + Key = response.Key; + } + + public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) + { + return Key.TryExportKeyBlob( + Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, + destination, + out bytesWritten); + } + + private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) + { + return Key.ExportPkcs8KeyBlob(pkcs8Password, kdfCount); + } + + private bool TryExportEncryptedPkcs8( + ReadOnlySpan pkcs8Password, + int kdfCount, + Span destination, + out int bytesWritten) + { + return Key.TryExportPkcs8KeyBlob( + pkcs8Password, + kdfCount, + destination, + out bytesWritten); } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs index 99bdc7604bc06..886e5161f0af0 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanCngPublicKey.cs @@ -1,90 +1,155 @@ // 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 System.Runtime.Versioning; namespace System.Security.Cryptography { - internal static partial class ECDiffieHellmanImplementation + /// + /// Public key used to do key exchange with the ECDiffieHellmanCng algorithm + /// + public sealed partial class ECDiffieHellmanCngPublicKey : ECDiffieHellmanPublicKey { - public sealed partial class ECDiffieHellmanCngPublicKey : ECDiffieHellmanPublicKey + private readonly CngKeyBlobFormat _format; + private readonly string? _curveName; + private bool _disposed; + + /// + /// Wrap a CNG key + /// + internal ECDiffieHellmanCngPublicKey(byte[] keyBlob, string? curveName, CngKeyBlobFormat format) : base(keyBlob) { - private byte[] _keyBlob; - internal string? _curveName; + _format = format; + // Can be null for P256, P384, P521, or an explicit blob + _curveName = curveName; + } - protected override void Dispose(bool disposing) + protected override void Dispose(bool disposing) + { + if (disposing) { - _keyBlob = null!; - base.Dispose(disposing); + _disposed = true; } - public override string ToXmlString() - { - throw new PlatformNotSupportedException(); - } + base.Dispose(disposing); + } - public static ECDiffieHellmanCngPublicKey FromXmlString(string xml) + public override string ToXmlString() + { + throw new PlatformNotSupportedException(); + } + + public static ECDiffieHellmanCngPublicKey FromXmlString(string xml) + { + throw new PlatformNotSupportedException(); + } + + /// + /// Format the key blob is expressed in + /// + public CngKeyBlobFormat BlobFormat + { + get { - throw new PlatformNotSupportedException(); + return _format; } + } - internal ECDiffieHellmanCngPublicKey(byte[] keyBlob, string? curveName) : base(keyBlob) + /// + /// Hydrate a public key from a blob + /// + [SupportedOSPlatform("windows")] + public static ECDiffieHellmanPublicKey FromByteArray(byte[] publicKeyBlob, CngKeyBlobFormat format) + { + if (publicKeyBlob == null) + throw new ArgumentNullException(nameof(publicKeyBlob)); + if (format == null) + throw new ArgumentNullException(nameof(format)); + + // Verify that the key can import successfully, because we did in the past. + using (CngKey imported = CngKey.Import(publicKeyBlob, format)) { - Debug.Assert(keyBlob != null); + if (imported.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) + { + throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey); + } - _keyBlob = keyBlob; - _curveName = curveName; + return new ECDiffieHellmanCngPublicKey(publicKeyBlob, null, format); } + } - /// - /// Exports the key and explicit curve parameters used by the ECC object into an object. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// - /// if explicit export is not supported by this platform. Windows 10 or higher is required. - /// - /// The key and explicit curve parameters used by the ECC object. - public override ECParameters ExportExplicitParameters() + internal static ECDiffieHellmanCngPublicKey FromKey(CngKey key) + { + CngKeyBlobFormat format; + string? curveName; + byte[] blob = ECCng.ExportKeyBlob(key, false, out format, out curveName); + return new ECDiffieHellmanCngPublicKey(blob, curveName, format); + } + + /// + /// Import the public key into CNG + /// + /// + public CngKey Import() + { + if (_disposed) { - if (_keyBlob == null) - { - throw new ObjectDisposedException(nameof(ECDiffieHellmanPublicKey)); - } + throw new ObjectDisposedException(nameof(ECDiffieHellmanCngPublicKey)); + } + + return CngKey.Import(ToByteArray(), _curveName, BlobFormat); + } + /// + /// Exports the key and explicit curve parameters used by the ECC object into an object. + /// + /// + /// if there was an issue obtaining the curve values. + /// + /// + /// if explicit export is not supported by this platform. Windows 10 or higher is required. + /// + /// The key and explicit curve parameters used by the ECC object. + public override ECParameters ExportExplicitParameters() + { + using (CngKey key = Import()) + { ECParameters ecparams = default; - ECCng.ExportPrimeCurveParameters(ref ecparams, _keyBlob, includePrivateParameters: false); + byte[] blob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); + ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters: false); return ecparams; } + } - /// - /// Exports the key used by the ECC object into an object. - /// If the key was created as a named curve, the Curve property will contain named curve parameters - /// otherwise it will contain explicit parameters. - /// - /// - /// if there was an issue obtaining the curve values. - /// - /// The key and named curve parameters used by the ECC object. - public override ECParameters ExportParameters() + /// + /// Exports the key used by the ECC object into an object. + /// If the key was created as a named curve, the Curve property will contain named curve parameters + /// otherwise it will contain explicit parameters. + /// + /// + /// if there was an issue obtaining the curve values. + /// + /// The key and named curve parameters used by the ECC object. + public override ECParameters ExportParameters() + { + using (CngKey key = Import()) { - if (_keyBlob == null) - { - throw new ObjectDisposedException(nameof(ECDiffieHellmanPublicKey)); - } + ECParameters ecparams = default; + string? curveName = key.GetCurveName(out _); - if (string.IsNullOrEmpty(_curveName)) + if (string.IsNullOrEmpty(curveName)) { - return ExportExplicitParameters(); + byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); + ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters: false); } else { - ECParameters ecparams = default; - ECCng.ExportNamedCurveParameters(ref ecparams, _keyBlob, includePrivateParameters: false); - ecparams.Curve = ECCurve.CreateFromFriendlyName(_curveName); - return ecparams; + byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters: false); + ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters: false); + ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); } + + return ecparams; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanKeyDerivationFunction.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanKeyDerivationFunction.cs new file mode 100644 index 0000000000000..faa0ead6806b7 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanKeyDerivationFunction.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + /// + /// Key derivation functions used to transform the raw secret agreement into key material + /// + public enum ECDiffieHellmanKeyDerivationFunction + { + Hash, + Hmac, + Tls + } +} diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs index 86e29e6fa136c..870e7291563a6 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography @@ -16,6 +17,11 @@ public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman /// is null /// /// is not a valid enveloped EC_KEY* + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public ECDiffieHellmanOpenSsl(SafeEvpPKeyHandle pkeyHandle) { if (pkeyHandle == null) @@ -46,6 +52,11 @@ public ECDiffieHellmanOpenSsl(SafeEvpPKeyHandle pkeyHandle) /// /// A pointer to an OpenSSL EC_KEY* /// is invalid + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public ECDiffieHellmanOpenSsl(IntPtr handle) { if (handle == IntPtr.Zero) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanWrapper.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanWrapper.cs new file mode 100644 index 0000000000000..91329c22713ba --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDiffieHellmanWrapper.cs @@ -0,0 +1,209 @@ +// 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; + +namespace System.Security.Cryptography +{ + internal sealed class ECDiffieHellmanWrapper : ECDiffieHellman + { + private readonly ECDiffieHellman _wrapped; + + internal ECDiffieHellmanWrapper(ECDiffieHellman wrapped) + { + Debug.Assert(wrapped != null); + _wrapped = wrapped; + } + + public override string KeyExchangeAlgorithm => _wrapped.KeyExchangeAlgorithm; + + public override string? SignatureAlgorithm => _wrapped.SignatureAlgorithm; + + public override ECDiffieHellmanPublicKey PublicKey => + new ECDiffieHellmanPublicKeyWrapper(_wrapped.PublicKey); + + public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) => + _wrapped.DeriveKeyMaterial(Unwrap(otherPartyPublicKey)); + + public override byte[] DeriveKeyFromHash( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? secretPrepend, + byte[]? secretAppend) => + _wrapped.DeriveKeyFromHash(Unwrap(otherPartyPublicKey), hashAlgorithm, secretPrepend, secretAppend); + + public override byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[]? hmacKey, + byte[]? secretPrepend, + byte[]? secretAppend) => + _wrapped.DeriveKeyFromHmac(Unwrap(otherPartyPublicKey), hashAlgorithm, hmacKey, secretPrepend, secretAppend); + + public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) => + _wrapped.DeriveKeyTls(Unwrap(otherPartyPublicKey), prfLabel, prfSeed); + + public override void FromXmlString(string xmlString) => _wrapped.FromXmlString(xmlString); + + public override string ToXmlString(bool includePrivateParameters) => + _wrapped.ToXmlString(includePrivateParameters); + + public override ECParameters ExportParameters(bool includePrivateParameters) => + _wrapped.ExportParameters(includePrivateParameters); + + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) => + _wrapped.ExportExplicitParameters(includePrivateParameters); + + public override void ImportParameters(ECParameters parameters) => + _wrapped.ImportParameters(parameters); + + public override void GenerateKey(ECCurve curve) => _wrapped.GenerateKey(curve); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters, destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(password, pbeParameters, destination, out bytesWritten); + + // Do not wrap ExportPkcs8PrivateKey, let it fall back to reconstructing it from parameters + // so that the ECDiffieHellman.Create()-returned object uses the same set of attributes on all platforms. + // (CNG adds the key usage attribute to distinguish ECDSA from ECDH) + //public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) => + // _wrapped.TryExportPkcs8PrivateKey(destination, out bytesWritten); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _wrapped.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + + public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportPkcs8PrivateKey(source, out bytesRead); + + public override void ImportSubjectPublicKeyInfo(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportSubjectPublicKeyInfo(source, out bytesRead); + + public override void ImportECPrivateKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportECPrivateKey(source, out bytesRead); + + public override byte[] ExportECPrivateKey() => _wrapped.ExportECPrivateKey(); + + public override bool TryExportECPrivateKey(Span destination, out int bytesWritten) => + _wrapped.TryExportECPrivateKey(destination, out bytesWritten); + + public override void ImportFromPem(ReadOnlySpan input) => _wrapped.ImportFromPem(input); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => + _wrapped.ImportFromEncryptedPem(input, password); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => + _wrapped.ImportFromEncryptedPem(input, passwordBytes); + + public override int KeySize + { + get => _wrapped.KeySize; + set => _wrapped.KeySize = value; + } + + public override KeySizes[] LegalKeySizes => _wrapped.LegalKeySizes; + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _wrapped.Dispose(); + } + } + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(password, pbeParameters); + + // Do not wrap ExportPkcs8PrivateKey, let it fall back to reconstructing it from parameters + // so that the ECDiffieHellman.Create()-returned object uses the same set of attributes on all platforms. + // (CNG adds the key usage attribute to distinguish ECDSA from ECDH) + //public override byte[] ExportPkcs8PrivateKey() => _wrapped.ExportPkcs8PrivateKey(); + + public override byte[] ExportSubjectPublicKeyInfo() => _wrapped.ExportSubjectPublicKeyInfo(); + + public override bool Equals(object? obj) => _wrapped.Equals(obj); + + public override int GetHashCode() => _wrapped.GetHashCode(); + + public override string ToString() => _wrapped.ToString()!; + + private static ECDiffieHellmanPublicKey Unwrap(ECDiffieHellmanPublicKey otherPartyPublicKey) + { + if (otherPartyPublicKey is ECDiffieHellmanPublicKeyWrapper wrapper) + { + return wrapper.WrappedKey; + } + + return otherPartyPublicKey; + } + + private sealed class ECDiffieHellmanPublicKeyWrapper : ECDiffieHellmanPublicKey + { + private readonly ECDiffieHellmanPublicKey _wrapped; + + internal ECDiffieHellmanPublicKey WrappedKey => _wrapped; + + internal ECDiffieHellmanPublicKeyWrapper(ECDiffieHellmanPublicKey wrapped) + { + Debug.Assert(wrapped != null); + _wrapped = wrapped; + } + + public override ECParameters ExportParameters() => _wrapped.ExportParameters(); + + public override ECParameters ExportExplicitParameters() => _wrapped.ExportExplicitParameters(); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _wrapped.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override byte[] ExportSubjectPublicKeyInfo() => + _wrapped.ExportSubjectPublicKeyInfo(); + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _wrapped.Dispose(); + } + } + + public override byte[] ToByteArray() => _wrapped.ToByteArray(); + + public override string ToXmlString() => _wrapped.ToXmlString(); + + public override bool Equals(object? obj) => _wrapped.Equals(obj); + + public override int GetHashCode() => _wrapped.GetHashCode(); + + public override string ToString() => _wrapped.ToString()!; + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.OpenSsl.cs index dbb00ed010b58..850fbf9766b14 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.OpenSsl.cs @@ -10,7 +10,7 @@ public partial class ECDsa : ECAlgorithm /// public static new partial ECDsa Create() { - return new ECDsaImplementation.ECDsaOpenSsl(); + return new ECDsaWrapper(new ECDsaOpenSsl()); } /// @@ -21,7 +21,7 @@ public partial class ECDsa : ECAlgorithm /// public static partial ECDsa Create(ECCurve curve) { - return new ECDsaImplementation.ECDsaOpenSsl(curve); + return new ECDsaWrapper(new ECDsaOpenSsl(curve)); } /// @@ -32,9 +32,18 @@ public static partial ECDsa Create(ECCurve curve) /// public static partial ECDsa Create(ECParameters parameters) { - ECDsa ec = new ECDsaImplementation.ECDsaOpenSsl(); - ec.ImportParameters(parameters); - return ec; + ECDsa ec = new ECDsaOpenSsl(); + + try + { + ec.ImportParameters(parameters); + return new ECDsaWrapper(ec); + } + catch + { + ec.Dispose(); + throw; + } } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.SecurityTransforms.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.SecurityTransforms.cs new file mode 100644 index 0000000000000..5dcbbde048c24 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.SecurityTransforms.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class ECDsa : ECAlgorithm + { + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + public static new partial ECDsa Create() + { + return new ECDsaImplementation.ECDsaSecurityTransforms(); + } + + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + /// + /// The representing the elliptic curve. + /// + public static partial ECDsa Create(ECCurve curve) + { + ECDsa ecdsa = Create(); + ecdsa.GenerateKey(curve); + return ecdsa; + } + + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + /// + /// The representing the elliptic curve parameters. + /// + public static partial ECDsa Create(ECParameters parameters) + { + ECDsa ecdsa = Create(); + ecdsa.ImportParameters(parameters); + return ecdsa; + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.Windows.cs new file mode 100644 index 0000000000000..3794ff6be455b --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.Create.Windows.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class ECDsa : ECAlgorithm + { + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + public static new partial ECDsa Create() + { + return new ECDsaWrapper(new ECDsaCng()); + } + + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + /// + /// The representing the elliptic curve. + /// + public static partial ECDsa Create(ECCurve curve) + { + return new ECDsaWrapper(new ECDsaCng(curve)); + + } + + /// + /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// + /// + /// The representing the elliptic curve parameters. + /// + public static partial ECDsa Create(ECParameters parameters) + { + ECDsa ec = new ECDsaCng(); + ec.ImportParameters(parameters); + return new ECDsaWrapper(ec); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.cs index 310e7e135ea67..735230cb2a9d9 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsa.cs @@ -51,14 +51,12 @@ public virtual byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) public virtual byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, offset, count, hashAlgorithm); return SignHash(hash); @@ -107,14 +105,12 @@ public byte[] SignData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -200,10 +196,8 @@ protected virtual byte[] SignDataCore( /// public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -233,10 +227,8 @@ public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, DSASignatur /// public byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -349,8 +341,7 @@ public virtual bool TrySignData( HashAlgorithmName hashAlgorithm, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); Span hashTmp = stackalloc byte[HashBufferStackSize]; ReadOnlySpan hash = HashSpanToTmp(data, hashAlgorithm, hashTmp); @@ -389,8 +380,7 @@ public bool TrySignData( DSASignatureFormat signatureFormat, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -431,10 +421,8 @@ protected virtual bool TrySignDataCore( public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, hashAlgorithm); return SignHash(hash); @@ -450,16 +438,13 @@ public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgo public virtual bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, offset, count, hashAlgorithm); return VerifyHash(hash, signature); @@ -510,16 +495,13 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -554,12 +536,9 @@ public bool VerifyData( /// public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -568,8 +547,7 @@ public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgo public virtual bool VerifyData(ReadOnlySpan data, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); Span hashTmp = stackalloc byte[HashBufferStackSize]; ReadOnlySpan hash = HashSpanToTmp(data, hashAlgorithm, hashTmp); @@ -598,8 +576,7 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); @@ -644,12 +621,9 @@ protected virtual bool VerifyDataCore( public bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); byte[] hash = HashData(data, hashAlgorithm); return VerifyHash(hash, signature); @@ -683,12 +657,9 @@ public bool VerifyData( HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); if (!signatureFormat.IsKnownValue()) throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.Key.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.Key.cs index 4382ec8165581..aabaf16795753 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.Key.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.Key.cs @@ -1,28 +1,123 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using static Internal.NativeCrypto.BCryptNative; - namespace System.Security.Cryptography { - internal static partial class ECDsaImplementation + using Microsoft.Win32.SafeHandles; + using System.Diagnostics; + + public sealed partial class ECDsaCng : ECDsa { - public sealed partial class ECDsaCng : ECDsa + /// + /// Gets the key that will be used by the ECDsa object for any cryptographic operation that it uses. + /// This key object will be disposed if the key is reset, for instance by changing the KeySize + /// property, using ImportParamers to create a new key, or by Disposing of the parent ECDsa object. + /// Therefore, you should make sure that the key object is no longer used in these scenarios. This + /// object will not be the same object as the CngKey passed to the ECDsaCng constructor if that + /// constructor was used, however it will point at the same CNG key. + /// + public CngKey Key + { + get + { + return GetKey(); + } + + private set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + if (!IsEccAlgorithmGroup(value.AlgorithmGroup)) + throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(value)); + _core.SetKey(value); + + // LegalKeySizes stores the values for either the current named curve or for the three + // curves that use size instead of name + ForceSetKeySize(value.KeySize); + } + } + + public override void GenerateKey(ECCurve curve) { - private readonly ECCngKey _key = new ECCngKey(AlgorithmName.ECDsa, nameof(ECDsa)); + curve.Validate(); + _core.DisposeKey(); - private string? GetCurveName(out string? oidValue) => _key.GetCurveName(KeySize, out oidValue); + if (curve.IsNamed) + { + if (string.IsNullOrEmpty(curve.Oid.FriendlyName)) + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value)); - public override void GenerateKey(ECCurve curve) + // Map curve name to algorithm to support pre-Win10 curves + CngAlgorithm alg = CngKey.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName); + if (CngKey.IsECNamedCurve(alg.Algorithm)) + { + CngKey key = _core.GetOrGenerateKey(curve); + ForceSetKeySize(key.KeySize); + } + else + { + int keySize; + // Get the proper KeySize from algorithm name + if (alg == CngAlgorithm.ECDsaP256) + keySize = 256; + else if (alg == CngAlgorithm.ECDsaP384) + keySize = 384; + else if (alg == CngAlgorithm.ECDsaP521) + keySize = 521; + else + { + Debug.Fail($"Unknown algorithm {alg}"); + throw new ArgumentException(SR.Cryptography_InvalidKeySize); + } + _core.GetOrGenerateKey(keySize, alg); + ForceSetKeySize(keySize); + } + } + else if (curve.IsExplicit) { - _key.GenerateKey(curve); - ForceSetKeySize(_key.KeySize); + CngKey key = _core.GetOrGenerateKey(curve); + ForceSetKeySize(key.KeySize); } + else + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString())); + } + } - private SafeNCryptKeyHandle GetDuplicatedKeyHandle() => _key.GetDuplicatedKeyHandle(KeySize); + private CngKey GetKey() + { + CngKey key; - private void DisposeKey() => _key.DisposeKey(); + if (_core.IsKeyGeneratedNamedCurve()) + { + // Curve was previously created, so use that + key = _core.GetOrGenerateKey(null); + } + else + { + CngAlgorithm algorithm; + + // Map the current key size to a CNG algorithm name + int keySize = KeySize; + switch (keySize) + { + case 256: algorithm = CngAlgorithm.ECDsaP256; break; + case 384: algorithm = CngAlgorithm.ECDsaP384; break; + case 521: algorithm = CngAlgorithm.ECDsaP521; break; + default: + Debug.Fail("Should not have invalid key size"); + throw new ArgumentException(SR.Cryptography_InvalidKeySize); + } + key = _core.GetOrGenerateKey(keySize, algorithm); + } + + return key; + } + + private SafeNCryptKeyHandle GetDuplicatedKeyHandle() + { + return Key.Handle; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.cs index 5e9b4fe7bccba..597f077883686 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaCng.cs @@ -1,157 +1,156 @@ // 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 Microsoft.Win32.SafeHandles; -using static Internal.NativeCrypto.BCryptNative; +using System.IO; +using System.Runtime.Versioning; +using Internal.Cryptography; namespace System.Security.Cryptography { - public partial class ECDsa : ECAlgorithm + public sealed partial class ECDsaCng : ECDsa { + private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(ECDsaCng)); + private CngAlgorithm _hashAlgorithm = CngAlgorithm.Sha256; + /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// Hash algorithm to use when generating a signature over arbitrary data /// - public static new partial ECDsa Create() + public CngAlgorithm HashAlgorithm { - return new ECDsaImplementation.ECDsaCng(); + get + { + return _hashAlgorithm; + } + set + { + _hashAlgorithm = value ?? throw new ArgumentNullException(nameof(value)); + } } /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. + /// Creates a new ECDsaCng object that will use the specified key. The key's + /// must be ECDsa. This constructor + /// creates a copy of the key. Hence, the caller can safely dispose of the + /// passed in key and continue using the ECDsaCng object. /// - /// - /// The representing the elliptic curve. - /// - public static partial ECDsa Create(ECCurve curve) + /// Key to use for ECDsa operations + /// if is not an ECDsa key + /// if is null. + [SupportedOSPlatform("windows")] + public ECDsaCng(CngKey key) { - return new ECDsaImplementation.ECDsaCng(curve); + if (key == null) + throw new ArgumentNullException(nameof(key)); + + if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) + throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(key)); + + Key = CngAlgorithmCore.Duplicate(key); } - /// - /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm. - /// - /// - /// The representing the elliptic curve parameters. - /// - public static partial ECDsa Create(ECParameters parameters) + protected override void Dispose(bool disposing) { - ECDsa ec = new ECDsaImplementation.ECDsaCng(); - ec.ImportParameters(parameters); - return ec; + _core.Dispose(); } - } - internal static partial class ECDsaImplementation - { - public sealed partial class ECDsaCng : ECDsa + private void ThrowIfDisposed() { - protected override void Dispose(bool disposing) - { - if (disposing) - { - _key?.FullDispose(); - } + _core.ThrowIfDisposed(); + } - base.Dispose(disposing); - } + private void DisposeKey() + { + _core.DisposeKey(); + } - private void ThrowIfDisposed() - { - _key.ThrowIfDisposed(); - } + private static bool IsEccAlgorithmGroup(CngAlgorithmGroup? algorithmGroup) + { + // Sometimes, when reading from certificates, ECDSA keys get identified as ECDH. + // Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA), + // so either value is acceptable for the ECDSA wrapper object. + // + // It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG. + return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman; + } - private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPUBLIC_BLOB; + internal string? GetCurveName(out string? oidValue) + { + return Key.GetCurveName(out oidValue); + } + + private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) + { + Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); + } + + private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) + { + Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); + } - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecfullKeyBlob); + private byte[] ExportKeyBlob(bool includePrivateParameters) + { + return ECCng.ExportKeyBlob(Key, includePrivateParameters); + } - Debug.Assert(!keyHandle.IsInvalid); + private byte[] ExportFullKeyBlob(bool includePrivateParameters) + { + return ECCng.ExportFullKeyBlob(Key, includePrivateParameters); + } - _key.SetHandle(keyHandle, AlgorithmName.ECDsa); - ForceSetKeySize(_key.KeySize); - } + private void AcceptImport(CngPkcs8.Pkcs8Response response) + { + Key = response.Key; + } - private void ImportKeyBlob(byte[] ecKeyBlob, string curveName, bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; + public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) + { + return Key.TryExportKeyBlob( + Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB, + destination, + out bytesWritten); + } - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecKeyBlob, curveName); + private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) + { + return Key.ExportPkcs8KeyBlob(pkcs8Password, kdfCount); + } - Debug.Assert(!keyHandle.IsInvalid); + private bool TryExportEncryptedPkcs8( + ReadOnlySpan pkcs8Password, + int kdfCount, + Span destination, + out int bytesWritten) + { + return Key.TryExportPkcs8KeyBlob( + pkcs8Password, + kdfCount, + destination, + out bytesWritten); + } - _key.SetHandle(keyHandle, ECCng.EcdsaCurveNameToAlgorithm(curveName)); - ForceSetKeySize(_key.KeySize); - } + public void FromXmlString(string xml, ECKeyXmlFormat format) + => throw new PlatformNotSupportedException(); - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; - - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + public byte[] SignData(byte[] data) + => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); - private byte[] ExportFullKeyBlob(bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_ECCFULLPUBLIC_BLOB; - - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + public byte[] SignData(byte[] data, int offset, int count) => + SignData(data, offset, count, new HashAlgorithmName(HashAlgorithm.Algorithm)); - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportPkcs8KeyBlob(keyHandle, pkcs8Password, kdfCount); - } - } + public byte[] SignData(Stream data) + => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.TryExportPkcs8KeyBlob( - keyHandle, - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - } + public string ToXmlString(ECKeyXmlFormat format) + => throw new PlatformNotSupportedException(); - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - SafeNCryptKeyHandle keyHandle = response.KeyHandle; + public bool VerifyData(byte[] data, byte[] signature) + => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); - _key.SetHandle( - keyHandle, - CngKeyLite.GetPropertyAsString( - keyHandle, - CngKeyLite.KeyPropertyName.Algorithm, - CngPropertyOptions.None)); + public bool VerifyData(byte[] data, int offset, int count, byte[] signature) + => VerifyData(data, offset, count, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); - ForceSetKeySize(_key.KeySize); - } - } + public bool VerifyData(Stream data, byte[] signature) + => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); } } diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDsaOpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaOpenSsl.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDsaOpenSsl.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaOpenSsl.cs index 27c08d7dfabb6..aeac93ad1637f 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/ECDsaOpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaOpenSsl.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography @@ -16,6 +17,11 @@ public sealed partial class ECDsaOpenSsl : ECDsa /// is null /// /// is not a valid enveloped EC_KEY* + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public ECDsaOpenSsl(SafeEvpPKeyHandle pkeyHandle) { if (pkeyHandle == null) @@ -46,6 +52,11 @@ public ECDsaOpenSsl(SafeEvpPKeyHandle pkeyHandle) /// /// A pointer to an OpenSSL EC_KEY* /// is invalid + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public ECDsaOpenSsl(IntPtr handle) { if (handle == IntPtr.Zero) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaWrapper.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaWrapper.cs new file mode 100644 index 0000000000000..ae194055f1d58 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECDsaWrapper.cs @@ -0,0 +1,190 @@ +// 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 System.IO; +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + internal sealed partial class ECDsaWrapper : ECDsa + { + private readonly ECDsa _wrapped; + + internal ECDsaWrapper(ECDsa wrapped) + { + Debug.Assert(wrapped != null); + _wrapped = wrapped; + } + + public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) => + _wrapped.SignData(data, hashAlgorithm); + + public override byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + _wrapped.SignData(data, offset, count, hashAlgorithm); + + public override bool TrySignData( + ReadOnlySpan data, + Span destination, + HashAlgorithmName hashAlgorithm, + out int bytesWritten) => + _wrapped.TrySignData(data, destination, hashAlgorithm, out bytesWritten); + + public override byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) => + _wrapped.SignData(data, hashAlgorithm); + + public override bool VerifyData( + byte[] data, + int offset, + int count, + byte[] signature, + HashAlgorithmName hashAlgorithm) => + _wrapped.VerifyData(data, offset, count, signature, hashAlgorithm); + + public override bool VerifyData( + ReadOnlySpan data, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm) => + _wrapped.VerifyData(data, signature, hashAlgorithm); + + public override byte[] SignHash(byte[] hash) => _wrapped.SignHash(hash); + + public override bool VerifyHash(byte[] hash, byte[] signature) => _wrapped.VerifyHash(hash, signature); + + public override string? KeyExchangeAlgorithm => _wrapped.KeyExchangeAlgorithm; + + public override void FromXmlString(string xmlString) => _wrapped.FromXmlString(xmlString); + + public override string ToXmlString(bool includePrivateParameters) => + _wrapped.ToXmlString(includePrivateParameters); + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _wrapped.Dispose(); + } + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + + public override void ImportPkcs8PrivateKey( + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportPkcs8PrivateKey(source, out bytesRead); + + public override void ImportSubjectPublicKeyInfo( + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportSubjectPublicKeyInfo(source, out bytesRead); + + public override unsafe void ImportECPrivateKey( + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportECPrivateKey(source, out bytesRead); + + public override byte[] ExportECPrivateKey() => _wrapped.ExportECPrivateKey(); + + public override bool TryExportECPrivateKey( + Span destination, + out int bytesWritten) => + _wrapped.TryExportECPrivateKey(destination, out bytesWritten); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(password, pbeParameters); + + // Do not wrap ExportPkcs8PrivateKey, let it fall back to reconstructing it from parameters + // so that the ECDsa.Create()-returned object uses the same set of attributes on all platforms. + // (CNG adds the key usage attribute to distinguish ECDSA from ECDH) + //public override byte[] ExportPkcs8PrivateKey() => _wrapped.ExportPkcs8PrivateKey(); + + public override byte[] ExportSubjectPublicKeyInfo() => _wrapped.ExportSubjectPublicKeyInfo(); + + public override ECParameters ExportParameters(bool includePrivateParameters) => + _wrapped.ExportParameters(includePrivateParameters); + + public override ECParameters ExportExplicitParameters(bool includePrivateParameters) => + _wrapped.ExportExplicitParameters(includePrivateParameters); + + public override void ImportParameters(ECParameters parameters) => + _wrapped.ImportParameters(parameters); + + public override void GenerateKey(ECCurve curve) => _wrapped.GenerateKey(curve); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters, destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(password, pbeParameters, destination, out bytesWritten); + + // Do not wrap TryExportPkcs8PrivateKey, let it fall back to reconstructing it from parameters + // so that the ECDsa.Create()-returned object uses the same set of attributes on all platforms. + // (CNG adds the key usage attribute to distinguish ECDSA from ECDH) + //public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) => + // _wrapped.TryExportPkcs8PrivateKey(destination, out bytesWritten); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _wrapped.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => + _wrapped.ImportFromEncryptedPem(input, password); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => + _wrapped.ImportFromEncryptedPem(input, passwordBytes); + + public override void ImportFromPem(ReadOnlySpan input) => _wrapped.ImportFromPem(input); + + public override int KeySize + { + get => _wrapped.KeySize; + set => _wrapped.KeySize = value; + } + + public override KeySizes[] LegalKeySizes => _wrapped.LegalKeySizes; + + public override string SignatureAlgorithm => _wrapped.SignatureAlgorithm; + + public override bool TrySignHash(ReadOnlySpan hash, Span destination, out int bytesWritten) => + _wrapped.TrySignHash(hash, destination, out bytesWritten); + + public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature) => + _wrapped.VerifyHash(hash, signature); + + public override bool Equals(object? obj) => _wrapped.Equals(obj); + + public override int GetHashCode() => _wrapped.GetHashCode(); + + public override string ToString() => _wrapped.ToString()!; + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECKeyXmlFormat.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECKeyXmlFormat.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/ECKeyXmlFormat.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ECKeyXmlFormat.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACMD5.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACMD5.cs index 97067a63b3f93..eff5baa635b8d 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACMD5.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACMD5.cs @@ -2,7 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.IO; using System.Runtime.Versioning; +using System.Threading; +using System.Threading.Tasks; using Internal.Cryptography; namespace System.Security.Cryptography @@ -162,6 +165,175 @@ public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source return true; } + /// + /// Computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated HMAC + /// size. The MD5 algorithm always produces a 128-bit HMAC, or 16 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.MD5, HashSizeInBytes, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.MD5, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.MD5, HashSizeInBytes, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the MD5 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The MD5 algorithm always produces a 128-bit hash, or 16 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.MD5, + HashSizeInBytes, + key.Span, + source, + destination, + cancellationToken); + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA1.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA1.cs index 006898d72c6ac..cc8d5619da208 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA1.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA1.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using System; using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Runtime.Versioning; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -171,6 +173,175 @@ public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source return true; } + /// + /// Computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA1 algorithm always produces a 160-bit HMAC, or 20 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA1, HashSizeInBytes, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA1, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA1, HashSizeInBytes, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA1 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA1 algorithm always produces a 160-bit hash, or 20 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA1, + HashSizeInBytes, + key.Span, + source, + destination, + cancellationToken); + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA256.cs index 0cb3ff2ab423d..797f60dd3b49b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA256.cs @@ -3,8 +3,10 @@ using Internal.Cryptography; using System.Diagnostics; +using System.IO; using System.Runtime.Versioning; -using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -163,6 +165,175 @@ public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source return true; } + /// + /// Computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA256 algorithm always produces a 256-bit HMAC, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA256, HashSizeInBytes, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA256, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA256, HashSizeInBytes, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA256 algorithm always produces a 256-bit hash, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA256, + HashSizeInBytes, + key.Span, + source, + destination, + cancellationToken); + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA384.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA384.cs index db9781f1fea2b..1162850933c35 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA384.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA384.cs @@ -1,11 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; -using System; using System.Diagnostics; +using System.IO; using System.Runtime.Versioning; -using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; +using Internal.Cryptography; namespace System.Security.Cryptography { @@ -181,6 +182,175 @@ public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source return true; } + /// + /// Computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA384 algorithm always produces a 384-bit HMAC, or 48 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA384, HashSizeInBytes, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA384, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA384, HashSizeInBytes, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA384 algorithm always produces a 384-bit hash, or 48 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA384, + HashSizeInBytes, + key.Span, + source, + destination, + cancellationToken); + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA512.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA512.cs index ee743669edf8a..079798b459a2b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA512.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA512.cs @@ -1,11 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; -using System; using System.Diagnostics; +using System.IO; using System.Runtime.Versioning; -using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; +using Internal.Cryptography; namespace System.Security.Cryptography { @@ -178,6 +179,175 @@ public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source return true; } + /// + /// Computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA512 algorithm always produces a 512-bit HMAC, or 64 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA512, HashSizeInBytes, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA512, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA512, HashSizeInBytes, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA512 algorithm always produces a 512-bit hash, or 64 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA512, + HashSizeInBytes, + key.Span, + source, + destination, + cancellationToken); + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.Apple.cs new file mode 100644 index 0000000000000..3cc658ee23164 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.Apple.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using PAL_HashAlgorithm = Interop.AppleCrypto.PAL_HashAlgorithm; + +namespace System.Security.Cryptography +{ + internal static partial class HashAlgorithmNames + { + internal static PAL_HashAlgorithm HashAlgorithmToPal(string hashAlgorithmId) => hashAlgorithmId switch { + HashAlgorithmNames.MD5 => PAL_HashAlgorithm.Md5, + HashAlgorithmNames.SHA1 => PAL_HashAlgorithm.Sha1, + HashAlgorithmNames.SHA256 => PAL_HashAlgorithm.Sha256, + HashAlgorithmNames.SHA384 => PAL_HashAlgorithm.Sha384, + HashAlgorithmNames.SHA512 => PAL_HashAlgorithm.Sha512, + _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)) + }; + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs index dc0a42f78ac8d..24cb46bdc2fd5 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs @@ -5,7 +5,7 @@ namespace System.Security.Cryptography { - internal static class HashAlgorithmNames + internal static partial class HashAlgorithmNames { // These are accepted by CNG public const string MD5 = "MD5"; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs index fa80816a75abf..296cafef90359 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs @@ -5,31 +5,22 @@ using System.Security.Cryptography.Apple; using Internal.Cryptography; +using PAL_HashAlgorithm = Interop.AppleCrypto.PAL_HashAlgorithm; + namespace System.Security.Cryptography { internal static partial class HashProviderDispenser { public static HashProvider CreateHashProvider(string hashAlgorithmId) { - Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmToPal(hashAlgorithmId); - return new AppleDigestProvider(algorithm); + return new AppleDigestProvider(hashAlgorithmId); } public static HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpan key) { - Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmToPal(hashAlgorithmId); - return new AppleHmacProvider(algorithm, key); + return new AppleHmacProvider(hashAlgorithmId, key); } - private static Interop.AppleCrypto.PAL_HashAlgorithm HashAlgorithmToPal(string hashAlgorithmId) => hashAlgorithmId switch { - HashAlgorithmNames.MD5 => Interop.AppleCrypto.PAL_HashAlgorithm.Md5, - HashAlgorithmNames.SHA1 => Interop.AppleCrypto.PAL_HashAlgorithm.Sha1, - HashAlgorithmNames.SHA256 => Interop.AppleCrypto.PAL_HashAlgorithm.Sha256, - HashAlgorithmNames.SHA384 => Interop.AppleCrypto.PAL_HashAlgorithm.Sha384, - HashAlgorithmNames.SHA512 => Interop.AppleCrypto.PAL_HashAlgorithm.Sha512, - _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)) - }; - internal static class OneShotHashProvider { public static unsafe int MacData( @@ -38,7 +29,7 @@ public static unsafe int MacData( ReadOnlySpan source, Span destination) { - Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmToPal(hashAlgorithmId); + Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmNames.HashAlgorithmToPal(hashAlgorithmId); fixed (byte* pKey = key) fixed (byte* pSource = source) @@ -69,7 +60,7 @@ public static unsafe int MacData( public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan source, Span destination) { - Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmToPal(hashAlgorithmId); + Interop.AppleCrypto.PAL_HashAlgorithm algorithm = HashAlgorithmNames.HashAlgorithmToPal(hashAlgorithmId); fixed (byte* pSource = source) fixed (byte* pDestination = destination) @@ -96,205 +87,117 @@ public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan sou } } - private sealed class AppleHmacProvider : HashProvider + private sealed class AppleDigestProvider : HashProvider { - private readonly byte[] _key; - private readonly SafeHmacHandle _ctx; - + private readonly LiteHash _liteHash; private bool _running; - public override int HashSizeInBytes { get; } - - internal AppleHmacProvider(Interop.AppleCrypto.PAL_HashAlgorithm algorithm, ReadOnlySpan key) + public AppleDigestProvider(string hashAlgorithmId) { - _key = key.ToArray(); - int hashSizeInBytes = 0; - _ctx = Interop.AppleCrypto.HmacCreate(algorithm, ref hashSizeInBytes); - - if (hashSizeInBytes < 0) - { - _ctx.Dispose(); - throw new PlatformNotSupportedException( - SR.Format( - SR.Cryptography_UnknownHashAlgorithm, - Enum.GetName(typeof(Interop.AppleCrypto.PAL_HashAlgorithm), algorithm))); - } - - if (_ctx.IsInvalid) - { - _ctx.Dispose(); - throw new CryptographicException(); - } - - HashSizeInBytes = hashSizeInBytes; + _liteHash = LiteHashProvider.CreateHash(hashAlgorithmId); } public override void AppendHashData(ReadOnlySpan data) { - if (!_running) - { - SetKey(); - } - - if (Interop.AppleCrypto.HmacUpdate(_ctx, data) != 1) - { - throw new CryptographicException(); - } - } - - private void SetKey() - { - if (Interop.AppleCrypto.HmacInit(_ctx, _key, _key.Length) != 1) - { - throw new CryptographicException(); - } - + _liteHash.Append(data); _running = true; } - public override unsafe int FinalizeHashAndReset(Span destination) + public override int FinalizeHashAndReset(Span destination) { - Debug.Assert(destination.Length >= HashSizeInBytes); - - if (!_running) - { - SetKey(); - } - - if (Interop.AppleCrypto.HmacFinal(_ctx, destination) != 1) - { - throw new CryptographicException(); - } - + int written = _liteHash.Finalize(destination); + // Apple's DigestFinal self-resets, so don't bother calling reset. _running = false; - return HashSizeInBytes; + return written; } - public override unsafe int GetCurrentHash(Span destination) + public override int GetCurrentHash(Span destination) { - Debug.Assert(destination.Length >= HashSizeInBytes); + return _liteHash.Current(destination); + } - if (!_running) - { - SetKey(); - } + public override int HashSizeInBytes => _liteHash.HashSizeInBytes; - if (Interop.AppleCrypto.HmacCurrent(_ctx, destination) != 1) + public override void Dispose(bool disposing) + { + if (disposing) { - throw new CryptographicException(); + _liteHash.Dispose(); } - - return HashSizeInBytes; } - public override void Dispose(bool disposing) + public override void Reset() { - if (disposing) + if (_running) { - _ctx?.Dispose(); - Array.Clear(_key); + _liteHash.Reset(); + _running = false; } } - - public override void Reset() => _running = false; } - private sealed class AppleDigestProvider : HashProvider + private sealed class AppleHmacProvider : HashProvider { - private readonly SafeDigestCtxHandle _ctx; + private readonly LiteHmac _liteHmac; + private readonly byte[] _key; private bool _running; - public override int HashSizeInBytes { get; } - - internal AppleDigestProvider(Interop.AppleCrypto.PAL_HashAlgorithm algorithm) + public AppleHmacProvider(string hashAlgorithmId, ReadOnlySpan key) { - int hashSizeInBytes; - _ctx = Interop.AppleCrypto.DigestCreate(algorithm, out hashSizeInBytes); - - if (hashSizeInBytes < 0) - { - _ctx.Dispose(); - throw new PlatformNotSupportedException( - SR.Format( - SR.Cryptography_UnknownHashAlgorithm, - Enum.GetName(typeof(Interop.AppleCrypto.PAL_HashAlgorithm), algorithm))); - } - - if (_ctx.IsInvalid) - { - _ctx.Dispose(); - throw new CryptographicException(); - } - - HashSizeInBytes = hashSizeInBytes; + PAL_HashAlgorithm algorithm = HashAlgorithmNames.HashAlgorithmToPal(hashAlgorithmId); + _liteHmac = new LiteHmac(algorithm, key, preinitialize: false); + _key = key.ToArray(); } public override void AppendHashData(ReadOnlySpan data) { - _running = true; - int ret = Interop.AppleCrypto.DigestUpdate(_ctx, data); - - if (ret != 1) + if (!_running) { - Debug.Assert(ret == 0, $"DigestUpdate return value {ret} was not 0 or 1"); - throw new CryptographicException(); + _liteHmac.Reset(_key); } + + _liteHmac.Append(data); + _running = true; } public override int FinalizeHashAndReset(Span destination) { - Debug.Assert(destination.Length >= HashSizeInBytes); - - int ret = Interop.AppleCrypto.DigestFinal(_ctx, destination); - _running = false; - - if (ret != 1) + if (!_running) { - Debug.Assert(ret == 0, $"DigestFinal return value {ret} was not 0 or 1"); - throw new CryptographicException(); + _liteHmac.Reset(_key); } - return HashSizeInBytes; + int written = _liteHmac.Finalize(destination); + _liteHmac.Reset(_key); + _running = false; + return written; } public override int GetCurrentHash(Span destination) { - Debug.Assert(destination.Length >= HashSizeInBytes); - - int ret = Interop.AppleCrypto.DigestCurrent(_ctx, destination); - - if (ret != 1) + if (!_running) { - Debug.Assert(ret == 0, $"DigestFinal return value {ret} was not 0 or 1"); - throw new CryptographicException(); + _liteHmac.Reset(_key); } - return HashSizeInBytes; + return _liteHmac.Current(destination); } - public override void Reset() - { - if (_running) - { - int ret = Interop.AppleCrypto.DigestReset(_ctx); - - if (ret != 1) - { - Debug.Assert(ret == 0, $"DigestReset return value {ret} was not 0 or 1"); - throw new CryptographicException(); - } - - _running = false; - } - } + public override int HashSizeInBytes => _liteHmac.HashSizeInBytes; public override void Dispose(bool disposing) { if (disposing) { - _ctx?.Dispose(); + _liteHmac.Dispose(); + Array.Clear(_key); } } + + public override void Reset() + { + _running = false; + } } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs index db75677b66ae8..32cdc7dd93b1c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs @@ -14,14 +14,12 @@ internal static partial class HashProviderDispenser { internal static HashProvider CreateHashProvider(string hashAlgorithmId) { - IntPtr evpType = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithmId); - return new EvpHashProvider(evpType); + return new EvpHashProvider(hashAlgorithmId); } internal static HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpan key) { - IntPtr evpType = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithmId); - return new HmacHashProvider(evpType, key); + return new HmacHashProvider(hashAlgorithmId, key); } internal static class OneShotHashProvider @@ -61,8 +59,16 @@ public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan sou fixed (byte* pSource = source) fixed (byte* pDestination = destination) { + const int Success = 1; uint length = (uint)destination.Length; - Check(Interop.Crypto.EvpDigestOneShot(evpType, pSource, source.Length, pDestination, &length)); + int ret = Interop.Crypto.EvpDigestOneShot(evpType, pSource, source.Length, pDestination, &length); + + if (ret != Success) + { + Debug.Assert(ret == 0); + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + Debug.Assert(length == hashSize); } @@ -72,71 +78,40 @@ public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan sou private sealed class EvpHashProvider : HashProvider { - private readonly IntPtr _algorithmEvp; - private readonly int _hashSize; - private readonly SafeEvpMdCtxHandle _ctx; + private readonly LiteHash _liteHash; private bool _running; - public EvpHashProvider(IntPtr algorithmEvp) + public EvpHashProvider(string hashAlgorithmId) { - _algorithmEvp = algorithmEvp; - Debug.Assert(algorithmEvp != IntPtr.Zero); - - _hashSize = Interop.Crypto.EvpMdSize(_algorithmEvp); - if (_hashSize <= 0 || _hashSize > Interop.Crypto.EVP_MAX_MD_SIZE) - { - throw new CryptographicException(); - } - - _ctx = Interop.Crypto.EvpMdCtxCreate(_algorithmEvp); - - Interop.Crypto.CheckValidOpenSslHandle(_ctx); + _liteHash = LiteHashProvider.CreateHash(hashAlgorithmId); } public override void AppendHashData(ReadOnlySpan data) { - if (data.IsEmpty) - { - return; - } - + _liteHash.Append(data); _running = true; - Check(Interop.Crypto.EvpDigestUpdate(_ctx, data, data.Length)); } public override int FinalizeHashAndReset(Span destination) { - Debug.Assert(destination.Length >= _hashSize); - - uint length = (uint)destination.Length; - Check(Interop.Crypto.EvpDigestFinalEx(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); - Debug.Assert(length == _hashSize); - - // Reset the algorithm provider. - Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithmEvp)); + int written = _liteHash.Finalize(destination); + _liteHash.Reset(); _running = false; - - return _hashSize; + return written; } public override int GetCurrentHash(Span destination) { - Debug.Assert(destination.Length >= _hashSize); - - uint length = (uint)destination.Length; - Check(Interop.Crypto.EvpDigestCurrent(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); - Debug.Assert(length == _hashSize); - - return _hashSize; + return _liteHash.Current(destination); } - public override int HashSizeInBytes => _hashSize; + public override int HashSizeInBytes => _liteHash.HashSizeInBytes; public override void Dispose(bool disposing) { if (disposing) { - _ctx.Dispose(); + _liteHash.Dispose(); } } @@ -144,7 +119,7 @@ public override void Reset() { if (_running) { - Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithmEvp)); + _liteHash.Reset(); _running = false; } } @@ -152,67 +127,40 @@ public override void Reset() private sealed class HmacHashProvider : HashProvider { - private readonly int _hashSize; - private SafeHmacCtxHandle _hmacCtx; + private readonly LiteHmac _liteHmac; private bool _running; - public HmacHashProvider(IntPtr algorithmEvp, ReadOnlySpan key) + public HmacHashProvider(string hashAlgorithmId, ReadOnlySpan key) { - Debug.Assert(algorithmEvp != IntPtr.Zero); - - _hashSize = Interop.Crypto.EvpMdSize(algorithmEvp); - if (_hashSize <= 0 || _hashSize > Interop.Crypto.EVP_MAX_MD_SIZE) - { - throw new CryptographicException(); - } - - _hmacCtx = Interop.Crypto.HmacCreate(ref MemoryMarshal.GetReference(key), key.Length, algorithmEvp); - Interop.Crypto.CheckValidOpenSslHandle(_hmacCtx); + _liteHmac = LiteHashProvider.CreateHmac(hashAlgorithmId, key); } public override void AppendHashData(ReadOnlySpan data) { - if (data.IsEmpty) - { - return; - } - + _liteHmac.Append(data); _running = true; - Check(Interop.Crypto.HmacUpdate(_hmacCtx, data, data.Length)); } public override int FinalizeHashAndReset(Span destination) { - Debug.Assert(destination.Length >= _hashSize); - - int length = destination.Length; - Check(Interop.Crypto.HmacFinal(_hmacCtx, ref MemoryMarshal.GetReference(destination), ref length)); - Debug.Assert(length == _hashSize); - - Check(Interop.Crypto.HmacReset(_hmacCtx)); + int written = _liteHmac.Finalize(destination); + _liteHmac.Reset(); _running = false; - return _hashSize; + return written; } public override int GetCurrentHash(Span destination) { - Debug.Assert(destination.Length >= _hashSize); - - int length = destination.Length; - Check(Interop.Crypto.HmacCurrent(_hmacCtx, ref MemoryMarshal.GetReference(destination), ref length)); - Debug.Assert(length == _hashSize); - - return _hashSize; + return _liteHmac.Current(destination); } - public override int HashSizeInBytes => _hashSize; + public override int HashSizeInBytes => _liteHmac.HashSizeInBytes; public override void Dispose(bool disposing) { - if (disposing && _hmacCtx != null) + if (disposing) { - _hmacCtx.Dispose(); - _hmacCtx = null!; + _liteHmac.Dispose(); } } @@ -220,20 +168,10 @@ public override void Reset() { if (_running) { - Check(Interop.Crypto.HmacReset(_hmacCtx)); + _liteHmac.Reset(); _running = false; } } } - - private static void Check(int result) - { - const int Success = 1; - if (result != Success) - { - Debug.Assert(result == 0); - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } - } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs index 76c7608cf0a88..7a60ff24841bb 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs @@ -2,15 +2,32 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; -using System.Numerics; +using System.Formats.Asn1; +using System.Globalization; using System.Security.Cryptography; -using System.Security.Cryptography.Asn1; namespace Internal.Cryptography { internal static partial class Helpers { + internal static ReadOnlySpan AsSpanParameter(this byte[] array, string paramName) + { + if (array == null) + throw new ArgumentNullException(paramName); + + return new ReadOnlySpan(array); + } + + internal static void AddRange(this ICollection coll, IEnumerable newData) + { + foreach (T datum in newData) + { + coll.Add(datum); + } + } + public static bool UsesIv(this CipherMode cipherMode) { return cipherMode != CipherMode.ECB; @@ -51,5 +68,267 @@ public static byte[] FixupKeyParity(this byte[] key) } return oddParityKey; } + + internal static byte[] GenerateRandom(int count) + { + byte[] buffer = new byte[count]; + RandomNumberGenerator.Fill(buffer); + return buffer; + } + + // Encode a byte array as an array of upper-case hex characters. + internal static char[] ToHexArrayUpper(this byte[] bytes) + { + char[] chars = new char[bytes.Length * 2]; + HexConverter.EncodeToUtf16(bytes, chars); + return chars; + } + + // Encode a byte array as an upper case hex string. + internal static string ToHexStringUpper(this byte[] bytes) => + Convert.ToHexString(bytes); + + // Decode a hex string-encoded byte array passed to various X509 crypto api. + // The parsing rules are overly forgiving but for compat reasons, they cannot be tightened. + internal static byte[] LaxDecodeHexString(this string hexString) + { + int whitespaceCount = 0; + + ReadOnlySpan s = hexString; + + if (s.Length != 0 && s[0] == '\u200E') + { + s = s.Slice(1); + } + + for (int i = 0; i < s.Length; i++) + { + if (char.IsWhiteSpace(s[i])) + whitespaceCount++; + } + + uint cbHex = (uint)(s.Length - whitespaceCount) / 2; + byte[] hex = new byte[cbHex]; + byte accum = 0; + bool byteInProgress = false; + int index = 0; + + for (int i = 0; i < s.Length; i++) + { + char c = s[i]; + + if (char.IsWhiteSpace(c)) + { + continue; + } + + accum <<= 4; + accum |= (byte)HexConverter.FromChar(c); + + byteInProgress = !byteInProgress; + + // If we've flipped from 0 to 1, back to 0, we have a whole byte + // so add it to the buffer. + if (!byteInProgress) + { + Debug.Assert(index < cbHex, "index < cbHex"); + + hex[index] = accum; + index++; + } + } + + // .NET Framework compat: + // The .NET Framework algorithm removed all whitespace before the loop, then went up to length/2 + // of what was left. This means that in the event of odd-length input the last char is + // ignored, no exception should be raised. + Debug.Assert(index == cbHex, "index == cbHex"); + + return hex; + } + + internal static bool ContentsEqual(this byte[]? a1, byte[]? a2) + { + if (a1 == null) + { + return a2 == null; + } + + if (a2 == null || a1.Length != a2.Length) + { + return false; + } + + return a1.AsSpan().SequenceEqual(a2); + } + + internal static ReadOnlyMemory DecodeOctetStringAsMemory(ReadOnlyMemory encodedOctetString) + { + try + { + ReadOnlySpan input = encodedOctetString.Span; + + if (AsnDecoder.TryReadPrimitiveOctetString( + input, + AsnEncodingRules.BER, + out ReadOnlySpan primitive, + out int consumed)) + { + if (consumed != input.Length) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + if (input.Overlaps(primitive, out int offset)) + { + return encodedOctetString.Slice(offset, primitive.Length); + } + + Debug.Fail("input.Overlaps(primitive) failed after TryReadPrimitiveOctetString succeeded"); + } + + byte[] ret = AsnDecoder.ReadOctetString(input, AsnEncodingRules.BER, out consumed); + + if (consumed != input.Length) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + return ret; + } + catch (AsnContentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + } + + internal static bool AreSamePublicECParameters(ECParameters aParameters, ECParameters bParameters) + { + if (aParameters.Curve.CurveType != bParameters.Curve.CurveType) + return false; + + if (!aParameters.Q.X!.ContentsEqual(bParameters.Q.X!) || + !aParameters.Q.Y!.ContentsEqual(bParameters.Q.Y!)) + { + return false; + } + + ECCurve aCurve = aParameters.Curve; + ECCurve bCurve = bParameters.Curve; + + if (aCurve.IsNamed) + { + // On Windows we care about FriendlyName, on Unix we care about Value + return (aCurve.Oid.Value == bCurve.Oid.Value && aCurve.Oid.FriendlyName == bCurve.Oid.FriendlyName); + } + + if (!aCurve.IsExplicit) + { + // Implicit curve, always fail. + return false; + } + + // Ignore Cofactor (which is derivable from the prime or polynomial and Order) + // Ignore Seed and Hash (which are entirely optional, and about how A and B were built) + if (!aCurve.G.X!.ContentsEqual(bCurve.G.X!) || + !aCurve.G.Y!.ContentsEqual(bCurve.G.Y!) || + !aCurve.Order.ContentsEqual(bCurve.Order) || + !aCurve.A.ContentsEqual(bCurve.A) || + !aCurve.B.ContentsEqual(bCurve.B)) + { + return false; + } + + if (aCurve.IsPrime) + { + return aCurve.Prime.ContentsEqual(bCurve.Prime); + } + + if (aCurve.IsCharacteristic2) + { + return aCurve.Polynomial.ContentsEqual(bCurve.Polynomial); + } + + Debug.Fail($"Missing match criteria for curve type {aCurve.CurveType}"); + return false; + } + + internal static bool IsValidDay(this Calendar calendar, int year, int month, int day, int era) + { + return (calendar.IsValidMonth(year, month, era) && day >= 1 && day <= calendar.GetDaysInMonth(year, month, era)); + } + + private static bool IsValidMonth(this Calendar calendar, int year, int month, int era) + { + return (calendar.IsValidYear(year, era) && month >= 1 && month <= calendar.GetMonthsInYear(year, era)); + } + + private static bool IsValidYear(this Calendar calendar, int year, int era) + { + return (year >= calendar.GetYear(calendar.MinSupportedDateTime) && year <= calendar.GetYear(calendar.MaxSupportedDateTime)); + } + + internal static void DisposeAll(this IEnumerable disposables) + { + foreach (IDisposable disposable in disposables) + { + disposable.Dispose(); + } + } + + internal static void ValidateDer(ReadOnlySpan encodedValue) + { + try + { + Asn1Tag tag; + AsnValueReader reader = new AsnValueReader(encodedValue, AsnEncodingRules.DER); + + while (reader.HasData) + { + tag = reader.PeekTag(); + + // If the tag is in the UNIVERSAL class + // + // DER limits the constructed encoding to SEQUENCE and SET, as well as anything which gets + // a defined encoding as being an IMPLICIT SEQUENCE. + if (tag.TagClass == TagClass.Universal) + { + switch ((UniversalTagNumber)tag.TagValue) + { + case UniversalTagNumber.External: + case UniversalTagNumber.Embedded: + case UniversalTagNumber.Sequence: + case UniversalTagNumber.Set: + case UniversalTagNumber.UnrestrictedCharacterString: + if (!tag.IsConstructed) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + break; + default: + if (tag.IsConstructed) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + break; + } + } + + if (tag.IsConstructed) + { + ValidateDer(reader.PeekContentBytes()); + } + + // Skip past the current value. + reader.ReadEncodedValue(); + } + } + catch (AsnContentException e) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); + } + } } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ICngSymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ICngSymmetricAlgorithm.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ICngSymmetricAlgorithm.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ICngSymmetricAlgorithm.cs index fa46b5cd2ad0b..1e5c3c31465d8 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ICngSymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ICngSymmetricAlgorithm.cs @@ -1,10 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Security.Cryptography; using Internal.NativeCrypto; -namespace Internal.Cryptography +namespace System.Security.Cryptography { // // Internal interface that allows CngSymmetricAlgorithmCore to communicate back with the SymmetricAlgorithm it's embedded in. diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/ICspAsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ICspAsymmetricAlgorithm.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/ICspAsymmetricAlgorithm.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ICspAsymmetricAlgorithm.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs index 55d4ee2f8294d..23fbadceab255 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs @@ -319,8 +319,7 @@ public void Dispose() /// is not a known hash algorithm. public static IncrementalHash CreateHash(HashAlgorithmName hashAlgorithm) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); return new IncrementalHash(hashAlgorithm, HashProviderDispenser.CreateHashProvider(hashAlgorithm.Name)); } @@ -381,8 +380,7 @@ public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, byte[] [UnsupportedOSPlatform("browser")] public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, ReadOnlySpan key) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); return new IncrementalHash(hashAlgorithm, new HMACCommon(hashAlgorithm.Name, key, -1)); } diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/KeyNumber.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyNumber.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/KeyNumber.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyNumber.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs new file mode 100644 index 0000000000000..d00b61334320c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs @@ -0,0 +1,215 @@ +// 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 System.Security.Cryptography.Apple; + +using PAL_HashAlgorithm = Interop.AppleCrypto.PAL_HashAlgorithm; + +namespace System.Security.Cryptography +{ + internal static partial class LiteHashProvider + { + internal static LiteHash CreateHash(string hashAlgorithmId) + { + PAL_HashAlgorithm algorithm = HashAlgorithmNames.HashAlgorithmToPal(hashAlgorithmId); + return new LiteHash(algorithm); + } + + internal static LiteHmac CreateHmac(string hashAlgorithmId, ReadOnlySpan key) + { + PAL_HashAlgorithm algorithm = HashAlgorithmNames.HashAlgorithmToPal(hashAlgorithmId); + return new LiteHmac(algorithm, key, preinitialize: true); + } + } + + internal readonly struct LiteHash : ILiteHash + { + private readonly SafeDigestCtxHandle _ctx; + private readonly int _hashSizeInBytes; + + private const int Success = 1; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHash(PAL_HashAlgorithm algorithm) + { + int hashSizeInBytes; + _ctx = Interop.AppleCrypto.DigestCreate(algorithm, out hashSizeInBytes); + + if (hashSizeInBytes < 0) + { + _ctx.Dispose(); + throw new PlatformNotSupportedException( + SR.Format( + SR.Cryptography_UnknownHashAlgorithm, + Enum.GetName(typeof(PAL_HashAlgorithm), algorithm))); + } + + if (_ctx.IsInvalid) + { + _ctx.Dispose(); + throw new CryptographicException(); + } + + _hashSizeInBytes = hashSizeInBytes; + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + int ret = Interop.AppleCrypto.DigestUpdate(_ctx, data); + + if (ret != Success) + { + Debug.Assert(ret == 0, $"{nameof(Interop.AppleCrypto.DigestUpdate)} return value {ret} was not 0 or 1"); + throw new CryptographicException(); + } + } + + public int Current(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + int ret = Interop.AppleCrypto.DigestCurrent(_ctx, destination); + + if (ret != Success) + { + Debug.Assert(ret == 0, $"{nameof(Interop.AppleCrypto.DigestCurrent)} return value {ret} was not 0 or 1"); + throw new CryptographicException(); + } + + return _hashSizeInBytes; + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + int ret = Interop.AppleCrypto.DigestFinal(_ctx, destination); + + if (ret != Success) + { + Debug.Assert(ret == 0, $"{nameof(Interop.AppleCrypto.DigestFinal)} return value {ret} was not 0 or 1"); + throw new CryptographicException(); + } + + return _hashSizeInBytes; + } + + public void Reset() + { + int ret = Interop.AppleCrypto.DigestReset(_ctx); + + if (ret != Success) + { + Debug.Assert(ret == 0, $"DigestReset return value {ret} was not 0 or 1"); + throw new CryptographicException(); + } + } + + public void Dispose() + { + _ctx.Dispose(); + } + } + + internal readonly struct LiteHmac : ILiteHash + { + private readonly SafeHmacHandle _ctx; + private readonly int _hashSizeInBytes; + + private const int Success = 1; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHmac(PAL_HashAlgorithm algorithm, ReadOnlySpan key, bool preinitialize) + { + int hashSizeInBytes = 0; + _ctx = Interop.AppleCrypto.HmacCreate(algorithm, ref hashSizeInBytes); + + if (hashSizeInBytes < 0) + { + _ctx.Dispose(); + throw new PlatformNotSupportedException( + SR.Format( + SR.Cryptography_UnknownHashAlgorithm, + Enum.GetName(typeof(Interop.AppleCrypto.PAL_HashAlgorithm), algorithm))); + } + + if (_ctx.IsInvalid) + { + _ctx.Dispose(); + throw new CryptographicException(); + } + + if (preinitialize) + { + if (Interop.AppleCrypto.HmacInit(_ctx, key) != Success) + { + _ctx.Dispose(); + throw new CryptographicException(); + } + } + + _hashSizeInBytes = hashSizeInBytes; + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + if (Interop.AppleCrypto.HmacUpdate(_ctx, data) != Success) + { + Debug.Fail($"{nameof(Interop.AppleCrypto.HmacUpdate)} unexpectedly failed."); + throw new CryptographicException(); + } + } + + public int Current(ReadOnlySpan destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + if (Interop.AppleCrypto.HmacCurrent(_ctx, destination) != Success) + { + Debug.Fail($"{nameof(Interop.AppleCrypto.HmacCurrent)} unexpectedly failed."); + throw new CryptographicException(); + } + + return _hashSizeInBytes; + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + if (Interop.AppleCrypto.HmacFinal(_ctx, destination) != Success) + { + Debug.Fail($"{nameof(Interop.AppleCrypto.HmacFinal)} unexpectedly failed."); + throw new CryptographicException(); + } + + return _hashSizeInBytes; + } + + public void Reset(ReadOnlySpan key) + { + if (Interop.AppleCrypto.HmacInit(_ctx, key) != Success) + { + Debug.Fail($"{nameof(Interop.AppleCrypto.HmacInit)} unexpectedly failed."); + } + } + + public void Dispose() + { + _ctx.Dispose(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs new file mode 100644 index 0000000000000..706427758605c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs @@ -0,0 +1,57 @@ +// 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.Cryptography; + +namespace System.Security.Cryptography +{ + internal static partial class LiteHashProvider + { + private static LiteHash CreateHash(string hashAlgorithmId) + { + return new LiteHash(hashAlgorithmId); + } + + private static LiteHmac CreateHmac(string hashAlgorithmId, ReadOnlySpan key) + { + return new LiteHmac(hashAlgorithmId, key); + } + } + + internal readonly struct LiteHash : ILiteHash + { + private readonly HashProvider _provider; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHash(string hashAlgorithmId) + { + _provider = HashProviderDispenser.CreateHashProvider(hashAlgorithmId); + _hashSizeInBytes = _provider.HashSizeInBytes; + } + + public void Append(ReadOnlySpan data) => _provider.AppendHashData(data); + public int Finalize(Span destination) => _provider.FinalizeHashAndReset(destination); + public void Dispose() => _provider.Dispose(); + } + + internal readonly struct LiteHmac : ILiteHash + { + private readonly HashProvider _provider; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHmac(string hashAlgorithmId, ReadOnlySpan key) + { + _provider = HashProviderDispenser.CreateMacProvider(hashAlgorithmId, key); + _hashSizeInBytes = _provider.HashSizeInBytes; + } + + public void Append(ReadOnlySpan data) => _provider.AppendHashData(data); + public int Finalize(Span destination) => _provider.FinalizeHashAndReset(destination); + public void Dispose() => _provider.Dispose(); + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs new file mode 100644 index 0000000000000..05b55230e14b7 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs @@ -0,0 +1,174 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Security.Cryptography +{ + internal static partial class LiteHashProvider + { + internal static LiteHash CreateHash(string hashAlgorithmId) + { + IntPtr algorithm = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithmId); + return new LiteHash(algorithm); + } + + internal static LiteHmac CreateHmac(string hashAlgorithmId, ReadOnlySpan key) + { + IntPtr algorithm = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithmId); + return new LiteHmac(algorithm, key); + } + } + + internal readonly struct LiteHash : ILiteHash + { + private readonly SafeEvpMdCtxHandle _ctx; + private readonly IntPtr _algorithm; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHash(IntPtr algorithm) + { + Debug.Assert(algorithm != IntPtr.Zero); + + _algorithm = algorithm; + _hashSizeInBytes = Interop.Crypto.EvpMdSize(algorithm); + + if (_hashSizeInBytes <= 0 || _hashSizeInBytes > Interop.Crypto.EVP_MAX_MD_SIZE) + { + Debug.Fail($"Unexpected hash '{_hashSizeInBytes}' size from {nameof(Interop.Crypto.EvpMdSize)}."); + throw new CryptographicException(); + } + + _ctx = Interop.Crypto.EvpMdCtxCreate(algorithm); + Interop.Crypto.CheckValidOpenSslHandle(_ctx); + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + Check(Interop.Crypto.EvpDigestUpdate(_ctx, data, data.Length)); + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + uint length = (uint)destination.Length; + Check(Interop.Crypto.EvpDigestFinalEx(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); + + Debug.Assert(length == _hashSizeInBytes); + return _hashSizeInBytes; + } + + public void Reset() + { + Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithm)); + } + + public int Current(Span destination) + { + uint length = (uint)destination.Length; + Check(Interop.Crypto.EvpDigestCurrent(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); + Debug.Assert(length == _hashSizeInBytes); + return _hashSizeInBytes; + } + + public void Dispose() + { + _ctx.Dispose(); + } + + private static void Check(int result) + { + const int Success = 1; + + if (result != Success) + { + Debug.Assert(result == 0); + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + } + } + + internal readonly struct LiteHmac : ILiteHash + { + private readonly SafeHmacCtxHandle _ctx; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHmac(IntPtr algorithm, ReadOnlySpan key) + { + Debug.Assert(algorithm != IntPtr.Zero); + _hashSizeInBytes = Interop.Crypto.EvpMdSize(algorithm); + + if (_hashSizeInBytes <= 0 || _hashSizeInBytes > Interop.Crypto.EVP_MAX_MD_SIZE) + { + Debug.Fail($"Unexpected hash '{_hashSizeInBytes}' size from {nameof(Interop.Crypto.EvpMdSize)}."); + throw new CryptographicException(); + } + + _ctx = Interop.Crypto.HmacCreate(ref MemoryMarshal.GetReference(key), key.Length, algorithm); + Interop.Crypto.CheckValidOpenSslHandle(_ctx); + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + Check(Interop.Crypto.HmacUpdate(_ctx, data, data.Length)); + } + + public int Current(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + int length = destination.Length; + Check(Interop.Crypto.HmacCurrent(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); + Debug.Assert(length == _hashSizeInBytes); + return _hashSizeInBytes; + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + int length = destination.Length; + Check(Interop.Crypto.HmacFinal(_ctx, ref MemoryMarshal.GetReference(destination), ref length)); + Debug.Assert(length == _hashSizeInBytes); + return _hashSizeInBytes; + } + + public void Reset() + { + Check(Interop.Crypto.HmacReset(_ctx)); + } + + public void Dispose() + { + _ctx.Dispose(); + } + + private static void Check(int result) + { + const int Success = 1; + + if (result != Success) + { + Debug.Assert(result == 0); + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs new file mode 100644 index 0000000000000..0fa10b16cbabb --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; +using System.Diagnostics; +using System.Runtime.InteropServices; + +using BCryptCreateHashFlags = Interop.BCrypt.BCryptCreateHashFlags; +using BCryptOpenAlgorithmProviderFlags = Interop.BCrypt.BCryptOpenAlgorithmProviderFlags; +using NTSTATUS = Interop.BCrypt.NTSTATUS; + +namespace System.Security.Cryptography +{ + internal static partial class LiteHashProvider + { + private static LiteHash CreateHash(string hashAlgorithmId) + { + return new LiteHash(hashAlgorithmId); + } + + private static LiteHmac CreateHmac(string hashAlgorithmId, ReadOnlySpan key) + { + return new LiteHmac(hashAlgorithmId, key); + } + } + + internal readonly struct LiteHash : ILiteHash + { + private readonly SafeBCryptHashHandle _hashHandle; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHash(string algorithm) + { + + BCryptOpenAlgorithmProviderFlags algorithmFlags = + BCryptOpenAlgorithmProviderFlags.None; + + // This is a shared handle, do not put this in a using. + SafeBCryptAlgorithmHandle algorithmHandle = Interop.BCrypt.BCryptAlgorithmCache.GetCachedBCryptAlgorithmHandle( + algorithm, + algorithmFlags, + out _hashSizeInBytes); + + SafeBCryptHashHandle hashHandle; + + NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( + algorithmHandle, + out hashHandle, + pbHashObject: IntPtr.Zero, + cbHashObject: 0, + secret: ReadOnlySpan.Empty, + cbSecret: 0, + BCryptCreateHashFlags.None); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + hashHandle.Dispose(); + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + _hashHandle = hashHandle; + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hashHandle, data, data.Length, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hashHandle, destination, _hashSizeInBytes, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + return _hashSizeInBytes; + } + + public void Dispose() + { + _hashHandle.Dispose(); + } + } + + internal readonly struct LiteHmac : ILiteHash + { + private readonly SafeBCryptHashHandle _hashHandle; + private readonly int _hashSizeInBytes; + + public int HashSizeInBytes => _hashSizeInBytes; + + internal LiteHmac(string algorithm, ReadOnlySpan key) + { + BCryptOpenAlgorithmProviderFlags algorithmFlags = + BCryptOpenAlgorithmProviderFlags.BCRYPT_ALG_HANDLE_HMAC_FLAG; + + // This is a shared handle, do not put this in a using. + SafeBCryptAlgorithmHandle algorithmHandle = Interop.BCrypt.BCryptAlgorithmCache.GetCachedBCryptAlgorithmHandle( + algorithm, + algorithmFlags, + out _hashSizeInBytes); + + SafeBCryptHashHandle hashHandle; + + NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( + algorithmHandle, + out hashHandle, + pbHashObject: IntPtr.Zero, + cbHashObject: 0, + key, + key.Length, + BCryptCreateHashFlags.None); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + hashHandle.Dispose(); + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + _hashHandle = hashHandle; + } + + public void Append(ReadOnlySpan data) + { + if (data.IsEmpty) + { + return; + } + + NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hashHandle, data, data.Length, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + } + + public int Finalize(Span destination) + { + Debug.Assert(destination.Length >= _hashSizeInBytes); + + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hashHandle, destination, _hashSizeInBytes, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + return _hashSizeInBytes; + } + + public void Dispose() + { + _hashHandle.Dispose(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHashProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHashProvider.cs new file mode 100644 index 0000000000000..82aceb127fb62 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHashProvider.cs @@ -0,0 +1,195 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + internal static partial class LiteHashProvider + { + internal static int HashStream(string hashAlgorithmId, int hashSizeInBytes, Stream source, Span destination) + { + LiteHash hash = CreateHash(hashAlgorithmId); + return ProcessStream(hash, source, destination); + } + + internal static byte[] HashStream(string hashAlgorithmId, int hashSizeInBytes, Stream source) + { + byte[] result = new byte[hashSizeInBytes]; + LiteHash hash = CreateHash(hashAlgorithmId); + int written = ProcessStream(hash, source, result); + Debug.Assert(written == hashSizeInBytes); + return result; + } + + internal static ValueTask HashStreamAsync( + string hashAlgorithmId, + int hashSizeInBytes, + Stream source, + Memory destination, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return ValueTask.FromCanceled(cancellationToken); + } + + LiteHash hash = CreateHash(hashAlgorithmId); + return ProcessStreamAsync(hash, source, destination, cancellationToken); + } + + internal static ValueTask HashStreamAsync( + string hashAlgorithmId, + int hashSizeInBytes, + Stream source, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return ValueTask.FromCanceled(cancellationToken); + } + + LiteHash hash = CreateHash(hashAlgorithmId); + return ProcessStreamAsync(hash, source, cancellationToken); + } + + internal static int HmacStream( + string hashAlgorithmId, + int hashSizeInBytes, + ReadOnlySpan key, + Stream source, + Span destination) + { + LiteHmac hash = CreateHmac(hashAlgorithmId, key); + return ProcessStream(hash, source, destination); + } + + internal static byte[] HmacStream( + string hashAlgorithmId, + int hashSizeInBytes, + ReadOnlySpan key, + Stream source) + { + byte[] result = new byte[hashSizeInBytes]; + LiteHmac hash = CreateHmac(hashAlgorithmId, key); + int written = ProcessStream(hash, source, result); + Debug.Assert(written == hashSizeInBytes); + return result; + } + + internal static ValueTask HmacStreamAsync( + string hashAlgorithmId, + int hashSizeInBytes, + ReadOnlySpan key, + Stream source, + Memory destination, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return ValueTask.FromCanceled(cancellationToken); + } + + LiteHmac hash = CreateHmac(hashAlgorithmId, key); + return ProcessStreamAsync(hash, source, destination, cancellationToken); + } + + internal static ValueTask HmacStreamAsync( + string hashAlgorithmId, + int hashSizeInBytes, + ReadOnlySpan key, + Stream source, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return ValueTask.FromCanceled(cancellationToken); + } + + LiteHmac hash = CreateHmac(hashAlgorithmId, key); + return ProcessStreamAsync(hash, source, cancellationToken); + } + + /// This takes ownership of the hash parameter and disposes of it when done. + private static int ProcessStream(T hash, Stream source, Span destination) where T : ILiteHash + { + using (hash) + { + byte[] rented = CryptoPool.Rent(4096); + + int maxRead = 0; + int read; + + try + { + while ((read = source.Read(rented)) > 0) + { + maxRead = Math.Max(maxRead, read); + hash.Append(rented.AsSpan(0, read)); + } + + return hash.Finalize(destination); + } + finally + { + CryptoPool.Return(rented, clearSize: maxRead); + } + } + } + + /// This takes ownership of the hash parameter and disposes of it when done. + private static async ValueTask ProcessStreamAsync( + T hash, + Stream source, + Memory destination, + CancellationToken cancellationToken) where T : ILiteHash + { + using (hash) + { + byte[] rented = CryptoPool.Rent(4096); + + int maxRead = 0; + int read; + + try + { + while ((read = await source.ReadAsync(rented, cancellationToken).ConfigureAwait(false)) > 0) + { + maxRead = Math.Max(maxRead, read); + hash.Append(rented.AsSpan(0, read)); + } + + return hash.Finalize(destination.Span); + } + finally + { + CryptoPool.Return(rented, clearSize: maxRead); + } + } + } + + /// This takes ownership of the hash parameter and disposes of it when done. + private static async ValueTask ProcessStreamAsync( + T hash, + Stream source, + CancellationToken cancellationToken) where T : ILiteHash + { + byte[] result = new byte[hash.HashSizeInBytes]; + int written = await ProcessStreamAsync(hash, source, result, cancellationToken).ConfigureAwait(false); + + Debug.Assert(written == result.Length); + return result; + } + } + + internal interface ILiteHash : IDisposable + { + int HashSizeInBytes { get; } + + void Append(ReadOnlySpan data); + int Finalize(Span destination); + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5.cs index ce70b333089bc..c1ba826d59355 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5.cs @@ -3,7 +3,10 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Runtime.Versioning; +using System.Threading; +using System.Threading.Tasks; using Internal.Cryptography; namespace System.Security.Cryptography @@ -112,6 +115,128 @@ public static bool TryHashData(ReadOnlySpan source, Span destination return true; } + /// + /// Computes the hash of a stream using the MD5 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The MD5 algorithm always produces a 128-bit hash, or 16 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.MD5, HashSizeInBytes, source, destination); + } + + /// + /// Computes the hash of a stream using the MD5 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.MD5, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the MD5 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.MD5, HashSizeInBytes, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the MD5 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The MD5 algorithm always produces a 128-bit hash, or 16 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.MD5, + HashSizeInBytes, + source, + destination, + cancellationToken); + } + private sealed class Implementation : MD5 { private readonly HashProvider _hashProvider; diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs index 8b0a74d682f8e..3342ad70e5638 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs @@ -16,14 +16,18 @@ public sealed class MD5CryptoServiceProvider : MD5 public MD5CryptoServiceProvider() { _incrementalHash = IncrementalHash.CreateHash(HashAlgorithmName.MD5); +#pragma warning disable CA1416 // MD5.HashSizeInBits is unsupported on browser HashSizeValue = HashSizeInBits; +#pragma warning restore CA1416 } public override void Initialize() { if (_running) { +#pragma warning disable CA1416 // MD5.HashSizeInBytes is unsupported on browser Span destination = stackalloc byte[HashSizeInBytes]; +#pragma warning restore CA1416 if (!_incrementalHash.TryGetHashAndReset(destination, out _)) { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSsl.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSsl.NotSupported.cs new file mode 100644 index 0000000000000..b5611338e8daa --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSsl.NotSupported.cs @@ -0,0 +1,270 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace System.Security.Cryptography +{ + public sealed class DSAOpenSsl : DSA + { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl(DSAParameters parameters) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public DSAOpenSsl(SafeEvpPKeyHandle pkeyHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + public SafeEvpPKeyHandle DuplicateKeyHandle() => null!; + public override byte[] CreateSignature(byte[] rgbHash) => null!; + public override DSAParameters ExportParameters(bool includePrivateParameters) => default; + public override void ImportParameters(DSAParameters parameters) { } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) => false; + } + public sealed class ECDiffieHellmanOpenSsl : ECDiffieHellman + { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(ECCurve curve) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDiffieHellmanOpenSsl(SafeEvpPKeyHandle pkeyHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + public SafeEvpPKeyHandle DuplicateKeyHandle() => null!; + public override ECDiffieHellmanPublicKey PublicKey => null!; + public override ECParameters ExportParameters(bool includePrivateParameters) => default; + public override void ImportParameters(ECParameters parameters) { } + } + public sealed class ECDsaOpenSsl : ECDsa + { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(ECCurve curve) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public ECDsaOpenSsl(SafeEvpPKeyHandle pkeyHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + public SafeEvpPKeyHandle DuplicateKeyHandle() => null!; + public override byte[] SignHash(byte[] hash) => null!; + public override bool VerifyHash(byte[] hash, byte[] signature) => default; + } + public sealed class RSAOpenSsl : RSA + { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public RSAOpenSsl() + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public RSAOpenSsl(int keySize) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public RSAOpenSsl(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public RSAOpenSsl(RSAParameters parameters) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public RSAOpenSsl(SafeEvpPKeyHandle pkeyHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + public SafeEvpPKeyHandle DuplicateKeyHandle() => null!; + public override RSAParameters ExportParameters(bool includePrivateParameters) => default; + public override void ImportParameters(RSAParameters parameters) { } + } + public sealed class SafeEvpPKeyHandle : SafeHandle + { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public SafeEvpPKeyHandle() : base(IntPtr.Zero, false) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public SafeEvpPKeyHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) + { + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + } + + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] + public static long OpenSslVersion => + throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL); + + public SafeEvpPKeyHandle DuplicateHandle() => null!; + public override bool IsInvalid => true; + protected override bool ReleaseHandle() => false; + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.NotSupported.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.NotSupported.cs diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs index c516653016400..51b244f025dbf 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.Windows.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.NativeCrypto; using System.Runtime.Versioning; #pragma warning disable CA5373 // Call to obsolete key derivation function PasswordDeriveBytes.* diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PasswordDeriveBytes.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PinAndClear.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PinAndClear.cs new file mode 100644 index 0000000000000..43435cda41619 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/PinAndClear.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace System.Security.Cryptography +{ + internal struct PinAndClear : IDisposable + { + private byte[] _data; + private GCHandle _gcHandle; + + internal static PinAndClear Track(byte[] data) + { + return new PinAndClear + { + _gcHandle = GCHandle.Alloc( + data, + GCHandleType.Pinned), + _data = data, + }; + } + + public void Dispose() + { + Array.Clear(_data); + _gcHandle.Free(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ProviderPropertyName.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ProviderPropertyName.cs similarity index 83% rename from src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ProviderPropertyName.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ProviderPropertyName.cs index 7ec02f680d675..eac3ad6b42566 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/Internal/Cryptography/ProviderPropertyName.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ProviderPropertyName.cs @@ -1,10 +1,7 @@ // 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.Diagnostics; - -namespace Internal.Cryptography +namespace System.Security.Cryptography { /// /// Well known names of provider properties diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.NotSupported.cs new file mode 100644 index 0000000000000..4fc7781d189b5 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.NotSupported.cs @@ -0,0 +1,31 @@ +// 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.CodeAnalysis; +using System.Runtime.Versioning; + +namespace System.Security.Cryptography +{ + public sealed partial class RC2CryptoServiceProvider : RC2 + { + [SuppressMessage("Microsoft.Security", "CA5351", Justification = "This is the implementation of RC2CryptoServiceProvider")] + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + public RC2CryptoServiceProvider() + { + throw new PlatformNotSupportedException(); + } + + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + public override void GenerateIV() { } + public override void GenerateKey() { } + + public bool UseSalt + { + get { return false; } + [SupportedOSPlatform("windows")] + set { } + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs index 4aeb4ec3c607b..72e06ca794655 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Unix.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; using System.Runtime.Versioning; namespace System.Security.Cryptography @@ -16,6 +15,8 @@ public sealed partial class RC2CryptoServiceProvider : RC2 }; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "This is the implementation of RC2CryptoServiceProvider")] + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] public RC2CryptoServiceProvider() { _impl = RC2.Create(); @@ -32,10 +33,10 @@ public override int BlockSize public override ICryptoTransform CreateEncryptor() => _impl.CreateEncryptor(); public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateEncryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateEncryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateDecryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateDecryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs index b76119432af1b..d3da83fa8a6a5 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.NativeCrypto; using System.ComponentModel; using System.Diagnostics; using System.Runtime.Versioning; @@ -21,6 +20,8 @@ public sealed class RC2CryptoServiceProvider : RC2 new KeySizes(40, 128, 8) // csp implementation only goes up to 128 }; + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] public RC2CryptoServiceProvider() { LegalKeySizesValue = s_legalKeySizes.CloneKeySizesArray(); diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RNGCryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RNGCryptoServiceProvider.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RNGCryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RNGCryptoServiceProvider.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.OpenSsl.cs new file mode 100644 index 0000000000000..ba66ba58fe078 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.OpenSsl.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class RSA : AsymmetricAlgorithm + { + public static new partial RSA Create() + { + return new RSAWrapper(new RSAOpenSsl()); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.SecurityTransforms.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.SecurityTransforms.cs new file mode 100644 index 0000000000000..a53e3e1b3cf3a --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.SecurityTransforms.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class RSA : AsymmetricAlgorithm + { + public static new partial RSA Create() + { + return new RSAImplementation.RSASecurityTransforms(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.Windows.cs new file mode 100644 index 0000000000000..1871e87f87c66 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.Create.Windows.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + public partial class RSA : AsymmetricAlgorithm + { + public static new partial RSA Create() + { + return new RSAWrapper(new RSACng()); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs index e5fa800517f38..da0a5aedd5b2f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs @@ -168,16 +168,13 @@ public virtual byte[] SignData( HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); byte[] hash = HashData(data, offset, count, hashAlgorithm); return SignHash(hash, hashAlgorithm, padding); @@ -185,12 +182,9 @@ public virtual byte[] SignData( public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(data); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); byte[] hash = HashData(data, hashAlgorithm); return SignHash(hash, hashAlgorithm, padding); @@ -198,14 +192,8 @@ public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RSA public virtual bool TrySignData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (TryHashData(data, destination, hashAlgorithm, out int hashLength) && TrySignHash(destination.Slice(0, hashLength), destination, hashAlgorithm, padding, out bytesWritten)) @@ -233,18 +221,14 @@ public virtual bool VerifyData( HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (data == null) - throw new ArgumentNullException(nameof(data)); + ArgumentNullException.ThrowIfNull(data); if (offset < 0 || offset > data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count < 0 || count > data.Length - offset) throw new ArgumentOutOfRangeException(nameof(count)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); byte[] hash = HashData(data, offset, count, hashAlgorithm); return VerifyHash(hash, signature, hashAlgorithm, padding); @@ -252,14 +236,10 @@ public virtual bool VerifyData( public bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (data == null) - throw new ArgumentNullException(nameof(data)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(data); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); byte[] hash = HashData(data, hashAlgorithm); return VerifyHash(hash, signature, hashAlgorithm, padding); @@ -267,14 +247,8 @@ public bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgo public virtual bool VerifyData(ReadOnlySpan data, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); for (int i = 256; ; i = checked(i * 2)) { @@ -1015,8 +989,5 @@ private static void ClearPrivateParameters(in RSAParameters rsaParameters) public override string? KeyExchangeAlgorithm => "RSA"; public override string SignatureAlgorithm => "RSA"; - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.ImportExport.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.ImportExport.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.ImportExport.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.ImportExport.cs diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.Key.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.Key.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/RSACng.Key.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.Key.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.cs index a329786852519..6038ea68ce7e1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACng.cs @@ -1,153 +1,44 @@ // 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 Microsoft.Win32.SafeHandles; +using System.Runtime.Versioning; +using Internal.Cryptography; namespace System.Security.Cryptography { - public partial class RSA : AsymmetricAlgorithm - { - public static new partial RSA Create() - { - return new RSAImplementation.RSACng(); - } - } - - internal static partial class RSAImplementation + public sealed partial class RSACng : RSA { - public sealed partial class RSACng : RSA + private CngAlgorithmCore _core = new CngAlgorithmCore(nameof(RSACng)); + + /// + /// Creates a new RSACng object that will use the specified key. The key's + /// must be Rsa. This constructor + /// creates a copy of the key. Hence, the caller can safely dispose of the + /// passed in key and continue using the RSACng object. + /// + /// Key to use for RSA operations + /// if is not an RSA key + /// if is null. + [SupportedOSPlatform("windows")] + public RSACng(CngKey key) { - private SafeNCryptKeyHandle? _keyHandle; - private int _lastKeySize; - private bool _disposed; - - private void ThrowIfDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(RSA)); - } - } - - private SafeNCryptKeyHandle GetDuplicatedKeyHandle() - { - ThrowIfDisposed(); - - int keySize = KeySize; - - if (_lastKeySize != keySize) - { - if (_keyHandle != null) - { - _keyHandle.Dispose(); - } - - const string BCRYPT_RSA_ALGORITHM = "RSA"; - - _keyHandle = CngKeyLite.GenerateNewExportableKey(BCRYPT_RSA_ALGORITHM, keySize); - _lastKeySize = keySize; - } - - return new DuplicateSafeNCryptKeyHandle(_keyHandle!); - } - - private byte[] ExportKeyBlob(bool includePrivateParameters) - { - string blobType = includePrivateParameters ? - Interop.BCrypt.KeyBlobType.BCRYPT_RSAFULLPRIVATE_BLOB : - Interop.BCrypt.KeyBlobType.BCRYPT_RSAPUBLIC_KEY_BLOB; - - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportKeyBlob(keyHandle, blobType); - } - } + if (key == null) + throw new ArgumentNullException(nameof(key)); - private byte[] ExportEncryptedPkcs8(ReadOnlySpan pkcs8Password, int kdfCount) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.ExportPkcs8KeyBlob(keyHandle, pkcs8Password, kdfCount); - } - } + if (key.AlgorithmGroup != CngAlgorithmGroup.Rsa) + throw new ArgumentException(SR.Cryptography_ArgRSARequiresRSAKey, nameof(key)); - private bool TryExportEncryptedPkcs8( - ReadOnlySpan pkcs8Password, - int kdfCount, - Span destination, - out int bytesWritten) - { - using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) - { - return CngKeyLite.TryExportPkcs8KeyBlob( - keyHandle, - pkcs8Password, - kdfCount, - destination, - out bytesWritten); - } - } - - private void ImportKeyBlob(byte[] rsaBlob, bool includePrivate) - { - ThrowIfDisposed(); - - string blobType = includePrivate - ? Interop.BCrypt.KeyBlobType.BCRYPT_RSAPRIVATE_BLOB - : Interop.BCrypt.KeyBlobType.BCRYPT_RSAPUBLIC_KEY_BLOB; - - SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, rsaBlob); - SetKeyHandle(keyHandle); - } - - private void AcceptImport(CngPkcs8.Pkcs8Response response) - { - ThrowIfDisposed(); - - SafeNCryptKeyHandle keyHandle = response.KeyHandle; - SetKeyHandle(keyHandle); - } - - private void SetKeyHandle(SafeNCryptKeyHandle keyHandle) - { - Debug.Assert(!keyHandle.IsInvalid); - - _keyHandle = keyHandle; - - int newKeySize = CngKeyLite.GetKeyLength(keyHandle); - - // Our LegalKeySizes value stores the values that we encoded as being the correct - // legal key size limitations for this algorithm, as documented on MSDN. - // - // But on a new OS version we might not question if our limit is accurate, or MSDN - // could have been inaccurate to start with. - // - // Since the key is already loaded, we know that Windows thought it to be valid; - // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance - // check. - // - // For RSA there are known cases where this change matters. RSACryptoServiceProvider can - // create a 384-bit RSA key, which we consider too small to be legal. It can also create - // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit - // alignment requirement. (In both cases Windows loads it just fine) - ForceSetKeySize(newKeySize); - _lastKeySize = newKeySize; - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _keyHandle?.Dispose(); - _keyHandle = null!; - _disposed = true; - } + Key = CngAlgorithmCore.Duplicate(key); + } + protected override void Dispose(bool disposing) + { + _core.Dispose(); + } - base.Dispose(disposing); - } + private void ThrowIfDisposed() + { + _core.ThrowIfDisposed(); } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.NotSupported.cs new file mode 100644 index 0000000000000..4be85c451896d --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.NotSupported.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Runtime.Versioning; + +namespace System.Security.Cryptography +{ + public sealed partial class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgorithm + { + [UnsupportedOSPlatform("browser")] + public RSACryptoServiceProvider() + { + throw new PlatformNotSupportedException(); + } + + [UnsupportedOSPlatform("browser")] + public RSACryptoServiceProvider(int dwKeySize) + { + throw new PlatformNotSupportedException(); + } + + [SupportedOSPlatform("windows")] + public RSACryptoServiceProvider(int dwKeySize, CspParameters parameters) => + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspParameters))); + + [SupportedOSPlatform("windows")] + public RSACryptoServiceProvider(CspParameters parameters) => + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspParameters))); + + [SupportedOSPlatform("windows")] + public CspKeyContainerInfo CspKeyContainerInfo => default!; + + public byte[] Decrypt(byte[] rgb, bool fOAEP) => default!; + public byte[] Encrypt(byte[] rgb, bool fOAEP) => default!; + public byte[] ExportCspBlob(bool includePrivateParameters) => default!; + public override RSAParameters ExportParameters(bool includePrivateParameters) => default; + public void ImportCspBlob(byte[] keyBlob) { } + public override void ImportParameters(RSAParameters parameters) { } + public bool PersistKeyInCsp { get; set; } + public bool PublicOnly => default; + public byte[] SignData(byte[] buffer, object halg) => default!; + public byte[] SignData(byte[] buffer, int offset, int count, object halg) => default!; + public byte[] SignData(Stream inputStream, object halg) => default!; + public byte[] SignHash(byte[] rgbHash, string str) => default!; + public bool VerifyData(byte[] buffer, object halg, byte[] signature) => default; + public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) => default; + + // UseMachineKeyStore has no effect in non-Windows + public static bool UseMachineKeyStore { get; set; } + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs index 168a456800e5b..70ba680b3f6fd 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.NativeCrypto; using System.IO; using System.Runtime.Versioning; @@ -15,9 +14,11 @@ public sealed partial class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgori private readonly RSA _impl; private bool _publicOnly; + [UnsupportedOSPlatform("browser")] public RSACryptoServiceProvider() : this(DefaultKeySize) { } + [UnsupportedOSPlatform("browser")] public RSACryptoServiceProvider(int dwKeySize) { if (dwKeySize < 0) @@ -205,13 +206,13 @@ public override bool TrySignData(ReadOnlySpan data, Span destination _impl.TrySignData(data, destination, hashAlgorithm, padding, out bytesWritten); public byte[] SignData(byte[] buffer, int offset, int count, object halg) => - _impl.SignData(buffer, offset, count, HashAlgorithmNames.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); + _impl.SignData(buffer, offset, count, CapiHelper.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); public byte[] SignData(byte[] buffer, object halg) => - _impl.SignData(buffer, HashAlgorithmNames.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); + _impl.SignData(buffer, CapiHelper.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); public byte[] SignData(Stream inputStream, object halg) => - _impl.SignData(inputStream, HashAlgorithmNames.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); + _impl.SignData(inputStream, CapiHelper.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) => padding == null ? throw new ArgumentNullException(nameof(padding)) : @@ -230,14 +231,14 @@ public byte[] SignHash(byte[] rgbHash, string str) if (PublicOnly) throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); - HashAlgorithmName algName = HashAlgorithmNames.NameOrOidToHashAlgorithmName(str); + HashAlgorithmName algName = CapiHelper.NameOrOidToHashAlgorithmName(str); return _impl.SignHash(rgbHash, algName, RSASignaturePadding.Pkcs1); } public override string ToXmlString(bool includePrivateParameters) => _impl.ToXmlString(includePrivateParameters); public bool VerifyData(byte[] buffer, object halg, byte[] signature) => - _impl.VerifyData(buffer, signature, HashAlgorithmNames.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); + _impl.VerifyData(buffer, signature, CapiHelper.ObjToHashAlgorithmName(halg), RSASignaturePadding.Pkcs1); public override bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) => padding == null ? throw new ArgumentNullException(nameof(padding)) : @@ -281,7 +282,7 @@ public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) return VerifyHash( (ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature, - HashAlgorithmNames.NameOrOidToHashAlgorithmName(str), RSASignaturePadding.Pkcs1); + CapiHelper.NameOrOidToHashAlgorithmName(str), RSASignaturePadding.Pkcs1); } // UseMachineKeyStore has no effect in Unix diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs index 6843a3aa30fca..e8706e6c57a65 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Windows.cs @@ -6,9 +6,6 @@ using System.IO; using System.Runtime.Versioning; using Internal.Cryptography; -using Internal.NativeCrypto; -using Microsoft.Win32.SafeHandles; -using static Internal.NativeCrypto.CapiHelper; namespace System.Security.Cryptography { @@ -17,11 +14,12 @@ public sealed partial class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgori private int _keySize; private readonly CspParameters _parameters; private readonly bool _randomKeyContainer; - private SafeKeyHandle? _safeKeyHandle; + private SafeCapiKeyHandle? _safeKeyHandle; private SafeProvHandle? _safeProvHandle; private static volatile CspProviderFlags s_useMachineKeyStore; private bool _disposed; + [UnsupportedOSPlatform("browser")] public RSACryptoServiceProvider() : this(0, new CspParameters(CapiHelper.DefaultRsaProviderType, null, @@ -31,6 +29,7 @@ public RSACryptoServiceProvider() { } + [UnsupportedOSPlatform("browser")] public RSACryptoServiceProvider(int dwKeySize) : this(dwKeySize, new CspParameters(CapiHelper.DefaultRsaProviderType, @@ -72,7 +71,7 @@ private RSACryptoServiceProvider(int keySize, CspParameters? parameters, bool us if (!_randomKeyContainer) { // Force-read the SafeKeyHandle property, which will summon it into existence. - SafeKeyHandle localHandle = SafeKeyHandle; + SafeCapiKeyHandle localHandle = SafeKeyHandle; Debug.Assert(localHandle != null); } } @@ -115,7 +114,7 @@ private SafeProvHandle SafeProvHandle if (current != null) { - SafeKeyHandle? keyHandle = _safeKeyHandle; + SafeCapiKeyHandle? keyHandle = _safeKeyHandle; _safeKeyHandle = null; keyHandle?.Dispose(); current.Dispose(); @@ -126,7 +125,7 @@ private SafeProvHandle SafeProvHandle } } - private SafeKeyHandle SafeKeyHandle + private SafeCapiKeyHandle SafeKeyHandle { get { @@ -136,7 +135,7 @@ private SafeKeyHandle SafeKeyHandle { if (_safeKeyHandle == null) { - SafeKeyHandle hKey = CapiHelper.GetKeyPairHelper( + SafeCapiKeyHandle hKey = CapiHelper.GetKeyPairHelper( CapiHelper.CspAlgorithmType.Rsa, _parameters, _keySize, @@ -158,7 +157,7 @@ private SafeKeyHandle SafeKeyHandle { lock (_parameters) { - SafeKeyHandle? current = _safeKeyHandle; + SafeCapiKeyHandle? current = _safeKeyHandle; if (ReferenceEquals(value, current)) { @@ -181,7 +180,7 @@ public CspKeyContainerInfo CspKeyContainerInfo { // .NET Framework compat: Read the SafeKeyHandle property to force the key to load, // because it might throw here. - SafeKeyHandle localHandle = SafeKeyHandle; + SafeCapiKeyHandle localHandle = SafeKeyHandle; Debug.Assert(localHandle != null); return new CspKeyContainerInfo(_parameters, _randomKeyContainer); @@ -195,7 +194,7 @@ public override int KeySize { get { - byte[] keySize = CapiHelper.GetKeyParameter(SafeKeyHandle, Constants.CLR_KEYLEN); + byte[] keySize = CapiHelper.GetKeyParameter(SafeKeyHandle, CapiHelper.ClrPropertyId.CLR_KEYLEN); _keySize = BinaryPrimitives.ReadInt32LittleEndian(keySize); return _keySize; } @@ -236,7 +235,7 @@ public bool PublicOnly { get { - byte[] publicKey = CapiHelper.GetKeyParameter(SafeKeyHandle, Constants.CLR_PUBLICKEYONLY); + byte[] publicKey = CapiHelper.GetKeyParameter(SafeKeyHandle, CapiHelper.ClrPropertyId.CLR_PUBLICKEYONLY); return (publicKey[0] == 1); } } @@ -385,7 +384,7 @@ private SafeProvHandle AcquireSafeProviderHandle() public void ImportCspBlob(byte[] keyBlob) { ThrowIfDisposed(); - SafeKeyHandle safeKeyHandle; + SafeCapiKeyHandle safeKeyHandle; if (IsPublic(keyBlob)) { @@ -678,12 +677,9 @@ public override byte[] SignHash( HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (padding != RSASignaturePadding.Pkcs1) throw PaddingModeNotSupported(); @@ -696,14 +692,10 @@ public override bool VerifyHash( HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (signature == null) - throw new ArgumentNullException(nameof(signature)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentNullException.ThrowIfNull(signature); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (padding != RSASignaturePadding.Pkcs1) throw PaddingModeNotSupported(); @@ -735,11 +727,6 @@ private static Exception PaddingModeNotSupported() return new CryptographicException(SR.Cryptography_InvalidPaddingMode); } - private static Exception HashAlgorithmNameNullOrEmpty() - { - return new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); - } - private void ThrowIfDisposed() { if (_disposed) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs index cfc36cbbacf55..c31f665ad4000 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs @@ -56,10 +56,7 @@ private RSAEncryptionPadding(RSAEncryptionPaddingMode mode, HashAlgorithmName oa /// public static RSAEncryptionPadding CreateOaep(HashAlgorithmName hashAlgorithm) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); return new RSAEncryptionPadding(RSAEncryptionPaddingMode.Oaep, hashAlgorithm); } diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/RSAOpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAOpenSsl.cs similarity index 84% rename from src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/RSAOpenSsl.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAOpenSsl.cs index 151dfba522f40..1ef165c992e8e 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/RSAOpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAOpenSsl.cs @@ -2,12 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { public sealed partial class RSAOpenSsl : RSA { + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public RSAOpenSsl(RSAParameters parameters) { ThrowIfNotSupported(); @@ -27,6 +33,11 @@ public RSAOpenSsl(RSAParameters parameters) /// /// A pointer to an OpenSSL RSA* /// is invalid + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public RSAOpenSsl(IntPtr handle) { if (handle == IntPtr.Zero) @@ -49,6 +60,11 @@ public RSAOpenSsl(IntPtr handle) /// /// /// is not a valid enveloped RSA* + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public RSAOpenSsl(SafeEvpPKeyHandle pkeyHandle) { if (pkeyHandle == null) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAWrapper.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAWrapper.cs new file mode 100644 index 0000000000000..8842974664029 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAWrapper.cs @@ -0,0 +1,219 @@ +// 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 System.IO; + +namespace System.Security.Cryptography +{ + internal sealed class RSAWrapper : RSA + { + private readonly RSA _wrapped; + + internal RSAWrapper(RSA wrapped) + { + Debug.Assert(wrapped != null); + _wrapped = wrapped; + } + + public override int KeySize + { + get => _wrapped.KeySize; + set => _wrapped.KeySize = value; + } + + public override KeySizes[] LegalKeySizes => _wrapped.LegalKeySizes; + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) => + _wrapped.ExportEncryptedPkcs8PrivateKey(password, pbeParameters); + + public override byte[] ExportPkcs8PrivateKey() => _wrapped.ExportPkcs8PrivateKey(); + + public override byte[] ExportSubjectPublicKeyInfo() => _wrapped.ExportSubjectPublicKeyInfo(); + + public override void FromXmlString(string xmlString) => _wrapped.FromXmlString(xmlString); + + public override string ToXmlString(bool includePrivateParameters) => + _wrapped.ToXmlString(includePrivateParameters); + + public override RSAParameters ExportParameters(bool includePrivateParameters) => + _wrapped.ExportParameters(includePrivateParameters); + + public override void ImportParameters(RSAParameters parameters) => _wrapped.ImportParameters(parameters); + + public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) => _wrapped.Encrypt(data, padding); + + public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => _wrapped.Decrypt(data, padding); + + public override byte[] SignHash( + byte[] hash, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.SignHash(hash, hashAlgorithm, padding); + + public override bool VerifyHash( + byte[] hash, + byte[] signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.VerifyHash(hash, signature, hashAlgorithm, padding); + + public override bool TryDecrypt( + ReadOnlySpan data, + Span destination, + RSAEncryptionPadding padding, + out int bytesWritten) => + _wrapped.TryDecrypt(data, destination, padding, out bytesWritten); + + public override bool TryEncrypt( + ReadOnlySpan data, + Span destination, + RSAEncryptionPadding padding, + out int bytesWritten) => + _wrapped.TryEncrypt(data, destination, padding, out bytesWritten); + + public override bool TrySignHash( + ReadOnlySpan hash, + Span destination, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding, + out int bytesWritten) => + _wrapped.TrySignHash(hash, destination, hashAlgorithm, padding, out bytesWritten); + + public override bool VerifyHash( + ReadOnlySpan hash, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.VerifyHash(hash, signature, hashAlgorithm, padding); + + public override byte[] DecryptValue(byte[] rgb) => _wrapped.DecryptValue(rgb); + + public override byte[] EncryptValue(byte[] rgb) => _wrapped.EncryptValue(rgb); + + public override byte[] SignData( + byte[] data, + int offset, + int count, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.SignData(data, offset, count, hashAlgorithm, padding); + + public override byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) => + _wrapped.SignData(data, hashAlgorithm, padding); + + public override bool TrySignData( + ReadOnlySpan data, + Span destination, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding, + out int bytesWritten) => + _wrapped.TrySignData(data, destination, hashAlgorithm, padding, out bytesWritten); + + public override bool VerifyData( + byte[] data, + int offset, + int count, + byte[] signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.VerifyData(data, offset, count, signature, hashAlgorithm, padding); + + public override bool VerifyData( + ReadOnlySpan data, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _wrapped.VerifyData(data, signature, hashAlgorithm, padding); + + public override byte[] ExportRSAPrivateKey() => _wrapped.ExportRSAPrivateKey(); + + public override bool TryExportRSAPrivateKey(Span destination, out int bytesWritten) => + _wrapped.TryExportRSAPrivateKey(destination, out bytesWritten); + + public override byte[] ExportRSAPublicKey() => _wrapped.ExportRSAPublicKey(); + + public override bool TryExportRSAPublicKey(Span destination, out int bytesWritten) => + _wrapped.TryExportRSAPublicKey(destination, out bytesWritten); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _wrapped.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) => + _wrapped.TryExportPkcs8PrivateKey(destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(password, pbeParameters, destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _wrapped.TryExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters, destination, out bytesWritten); + + public override void ImportSubjectPublicKeyInfo(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportSubjectPublicKeyInfo(source, out bytesRead); + + public override void ImportRSAPublicKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportRSAPublicKey(source, out bytesRead); + + public override void ImportRSAPrivateKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportRSAPrivateKey(source, out bytesRead); + + public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead) => + _wrapped.ImportPkcs8PrivateKey(source, out bytesRead); + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) => + _wrapped.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + + public override void ImportFromPem(ReadOnlySpan input) => + _wrapped.ImportFromPem(input); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => + _wrapped.ImportFromEncryptedPem(input, password); + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => + _wrapped.ImportFromEncryptedPem(input, passwordBytes); + + public override string? KeyExchangeAlgorithm => _wrapped.KeyExchangeAlgorithm; + + public override string SignatureAlgorithm => _wrapped.SignatureAlgorithm; + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _wrapped.Dispose(); + } + + base.Dispose(disposing); + } + + public override bool Equals(object? obj) => _wrapped.Equals(obj); + + public override int GetHashCode() => _wrapped.GetHashCode(); + + public override string ToString() => _wrapped.ToString()!; + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs index 205bb91860c1f..20190fd32fcd9 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs @@ -329,10 +329,8 @@ private static void Pbkdf2Core( private static void ValidateHashAlgorithm(HashAlgorithmName hashAlgorithm) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - - string hashAlgorithmName = hashAlgorithm.Name; + string? hashAlgorithmName = hashAlgorithm.Name; + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); // MD5 intentionally left out. if (hashAlgorithmName != HashAlgorithmName.SHA1.Name && diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1.cs index 0a66bc18b2854..684d69e9a228c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1.cs @@ -4,6 +4,9 @@ using Internal.Cryptography; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -111,6 +114,128 @@ public static bool TryHashData(ReadOnlySpan source, Span destination return true; } + /// + /// Computes the hash of a stream using the SHA1 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA1 algorithm always produces a 160-bit hash, or 20 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA1, HashSizeInBytes, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA1 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA1, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA1 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA1, HashSizeInBytes, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA1 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA1 algorithm always produces a 160-bit hash, or 20 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA1, + HashSizeInBytes, + source, + destination, + cancellationToken); + } + private sealed class Implementation : SHA1 { private readonly HashProvider _hashProvider; diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256.cs index da16eb8606430..fb48e9ffe0031 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256.cs @@ -4,6 +4,9 @@ using Internal.Cryptography; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -111,6 +114,128 @@ public static bool TryHashData(ReadOnlySpan source, Span destination return true; } + /// + /// Computes the hash of a stream using the SHA256 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA256 algorithm always produces a 256-bit hash, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA256, HashSizeInBytes, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA256 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA256, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA256 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA256, HashSizeInBytes, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA256 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA256 algorithm always produces a 256-bit hash, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA256, + HashSizeInBytes, + source, + destination, + cancellationToken); + } + private sealed class Implementation : SHA256 { private readonly HashProvider _hashProvider; diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384.cs index 1ed1b72c04f61..89ba9d5c78b85 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384.cs @@ -4,6 +4,9 @@ using Internal.Cryptography; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -110,6 +113,128 @@ public static bool TryHashData(ReadOnlySpan source, Span destination return true; } + /// + /// Computes the hash of a stream using the SHA384 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA384 algorithm always produces a 384-bit hash, or 48 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA384, HashSizeInBytes, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA384 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA384, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA384 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA384, HashSizeInBytes, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA384 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA384 algorithm always produces a 384-bit hash, or 48 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA384, + HashSizeInBytes, + source, + destination, + cancellationToken); + } + private sealed class Implementation : SHA384 { private readonly HashProvider _hashProvider; diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512.cs index 5c6e52ab9cd9a..924af115013d9 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512.cs @@ -4,6 +4,9 @@ using Internal.Cryptography; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace System.Security.Cryptography { @@ -110,6 +113,128 @@ public static bool TryHashData(ReadOnlySpan source, Span destination return true; } + /// + /// Computes the hash of a stream using the SHA512 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA512 algorithm always produces a 512-bit hash, or 64 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA512, HashSizeInBytes, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA512 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA512, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA512 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA512, HashSizeInBytes, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA512 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA512 algorithm always produces a 512-bit hash, or 64 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA512, + HashSizeInBytes, + source, + destination, + cancellationToken); + } + private sealed class Implementation : SHA512 { private readonly HashProvider _hashProvider; diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs diff --git a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SafeEvpPKeyHandle.OpenSsl.cs similarity index 77% rename from src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SafeEvpPKeyHandle.OpenSsl.cs index 9e67a1a9df2d6..47b6ba4812e54 100644 --- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SafeEvpPKeyHandle.OpenSsl.cs @@ -3,23 +3,29 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using System.Runtime.Versioning; namespace System.Security.Cryptography { -#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - internal -#else - public -#endif - sealed class SafeEvpPKeyHandle : SafeHandle + public sealed class SafeEvpPKeyHandle : SafeHandle { internal static readonly SafeEvpPKeyHandle InvalidHandle = new SafeEvpPKeyHandle(); + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public SafeEvpPKeyHandle() : base(IntPtr.Zero, ownsHandle: true) { } + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public SafeEvpPKeyHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { @@ -65,7 +71,6 @@ public SafeEvpPKeyHandle DuplicateHandle() return safeHandle; } -#if !INTERNAL_ASYMMETRIC_IMPLEMENTATIONS /// /// The runtime version number for the loaded version of OpenSSL. /// @@ -73,7 +78,11 @@ public SafeEvpPKeyHandle DuplicateHandle() /// For OpenSSL 1.1+ this is the result of OpenSSL_version_num(), /// for OpenSSL 1.0.x this is the result of SSLeay(). /// + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("windows")] public static long OpenSslVersion { get; } = Interop.OpenSsl.OpenSslVersionNumber(); -#endif } } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/TripleDESCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCng.Windows.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/TripleDESCng.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCng.Windows.cs index 710053fa4e559..808b8902d34eb 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System/Security/Cryptography/TripleDESCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCng.Windows.cs @@ -8,6 +8,7 @@ // that each of these derive from a different class, it can't be helped. // +using System.Runtime.Versioning; using Internal.Cryptography; using Internal.NativeCrypto; @@ -16,21 +17,25 @@ namespace System.Security.Cryptography [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "We are providing the implementation for TripleDES, not consuming it")] public sealed class TripleDESCng : TripleDES, ICngSymmetricAlgorithm { + [SupportedOSPlatform("windows")] public TripleDESCng() { _core = new CngSymmetricAlgorithmCore(this); } + [SupportedOSPlatform("windows")] public TripleDESCng(string keyName) : this(keyName, CngProvider.MicrosoftSoftwareKeyStorageProvider) { } + [SupportedOSPlatform("windows")] public TripleDESCng(string keyName, CngProvider provider) : this(keyName, provider, CngKeyOpenOptions.None) { } + [SupportedOSPlatform("windows")] public TripleDESCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) { _core = new CngSymmetricAlgorithmCore(this, keyName, provider, openOptions); @@ -238,7 +243,7 @@ SafeAlgorithmHandle ICngSymmetricAlgorithm.GetEphemeralModeHandle(CipherMode mod string ICngSymmetricAlgorithm.GetNCryptAlgorithmIdentifier() { - return Interop.NCrypt.NCRYPT_3DES_ALGORITHM; + return Cng.BCRYPT_3DES_ALGORITHM; } byte[] ICngSymmetricAlgorithm.PreprocessKey(byte[] key) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.NotSupported.cs new file mode 100644 index 0000000000000..7de61d03744f5 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.NotSupported.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + [Obsolete(Obsoletions.DerivedCryptographicTypesMessage, DiagnosticId = Obsoletions.DerivedCryptographicTypesDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class TripleDESCryptoServiceProvider : TripleDES + { + [SuppressMessage("Microsoft.Security", "CA5350", Justification = "This is the implementation of TripleDES")] + public TripleDESCryptoServiceProvider() + { + throw new PlatformNotSupportedException(); + } + + public override void GenerateIV() { } + public override void GenerateKey() { } + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => default!; + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.Wrap.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.Wrap.cs index 6e40774f0f855..156eae13904ae 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/TripleDESCryptoServiceProvider.Wrap.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; -using Internal.Cryptography; namespace System.Security.Cryptography { @@ -68,10 +67,10 @@ public override PaddingMode Padding public override void GenerateKey() => _impl.GenerateKey(); public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateEncryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateEncryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) => - _impl.CreateDecryptor(rgbKey, Helpers.TrimLargeIV(rgbIV, BlockSize)); + _impl.CreateDecryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize)); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/Utils.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Utils.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/Utils.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Utils.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidCertificatePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs index d765cd0b56a4d..87affa5408d58 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs @@ -1,20 +1,17 @@ // 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.Diagnostics.CodeAnalysis; using System.Formats.Asn1; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using System.Text; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class AndroidCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidPkcs12Reader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidPkcs12Reader.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidPkcs12Reader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidPkcs12Reader.cs index af679b1342bcc..a22e15530798f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/AndroidPkcs12Reader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidPkcs12Reader.cs @@ -1,16 +1,13 @@ // 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.Diagnostics; using System.Formats.Asn1; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class AndroidPkcs12Reader : UnixPkcs12Reader { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificateExporter.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificateExporter.iOS.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificateExporter.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificateExporter.iOS.cs index 54bf659a1fcca..542dcf8d36c2a 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificateExporter.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificateExporter.iOS.cs @@ -1,13 +1,9 @@ // 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.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class AppleCertificateExporter : UnixExportProvider { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.ImportExport.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.ImportExport.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs index dd8fb2ac2ddaf..26fbe98478b54 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.ImportExport.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs @@ -1,22 +1,14 @@ // 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.Buffers; -using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; -using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.Asn1.Pkcs12; using System.Security.Cryptography.Asn1.Pkcs7; -using System.Text; -using System.Threading; +using System.Security.Cryptography.Asn1.Pkcs12; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.ImportExport.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.ImportExport.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs index f6b19f9bb0394..f15d48e8ea61f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.ImportExport.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs @@ -1,19 +1,14 @@ // 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.Buffers; -using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; -using System.Text; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Keys.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.iOS.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Keys.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.iOS.cs index 98a8df28cf255..9076f0c4899a1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Keys.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.iOS.cs @@ -1,10 +1,7 @@ // 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.Security.Cryptography; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Keys.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.macOS.cs similarity index 80% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Keys.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.macOS.cs index 4231c82f0ac95..49107777cd5ba 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Keys.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Keys.macOS.cs @@ -1,19 +1,16 @@ // 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.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { @@ -57,13 +54,30 @@ public ICertificatePal CopyWithPrivateKey(DSA privateKey) public ICertificatePal CopyWithPrivateKey(ECDsa privateKey) { var typedKey = privateKey as ECDsaImplementation.ECDsaSecurityTransforms; + byte[] ecPrivateKey; if (typedKey != null) { - return CopyWithPrivateKey(typedKey.GetKeys().PrivateKey); + ECParameters ecParameters = default; + + if (typedKey.TryExportDataKeyParameters(includePrivateParameters: true, ref ecParameters)) + { + using (PinAndClear.Track(ecParameters.D!)) + { + AsnWriter writer = EccKeyFormatHelper.WriteECPrivateKey(ecParameters); + ecPrivateKey = writer.Encode(); + writer.Reset(); + } + } + else + { + return CopyWithPrivateKey(typedKey.GetKeys().PrivateKey); + } + } + else + { + ecPrivateKey = privateKey.ExportECPrivateKey(); } - - byte[] ecPrivateKey = privateKey.ExportECPrivateKey(); using (PinAndClear.Track(ecPrivateKey)) using (SafeSecKeyRefHandle privateSecKey = Interop.AppleCrypto.ImportEphemeralKey(ecPrivateKey, true)) @@ -75,13 +89,30 @@ public ICertificatePal CopyWithPrivateKey(ECDsa privateKey) public ICertificatePal CopyWithPrivateKey(ECDiffieHellman privateKey) { var typedKey = privateKey as ECDiffieHellmanImplementation.ECDiffieHellmanSecurityTransforms; + byte[] ecPrivateKey; if (typedKey != null) { - return CopyWithPrivateKey(typedKey.GetKeys().PrivateKey); + ECParameters ecParameters = default; + + if (typedKey.TryExportDataKeyParameters(includePrivateParameters: true, ref ecParameters)) + { + using (PinAndClear.Track(ecParameters.D!)) + { + AsnWriter writer = EccKeyFormatHelper.WriteECPrivateKey(ecParameters); + ecPrivateKey = writer.Encode(); + writer.Reset(); + } + } + else + { + return CopyWithPrivateKey(typedKey.GetKeys().PrivateKey); + } + } + else + { + ecPrivateKey = privateKey.ExportECPrivateKey(); } - - byte[] ecPrivateKey = privateKey.ExportECPrivateKey(); using (PinAndClear.Track(ecPrivateKey)) using (SafeSecKeyRefHandle privateSecKey = Interop.AppleCrypto.ImportEphemeralKey(ecPrivateKey, true)) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pem.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pem.iOS.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pem.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pem.iOS.cs index 73d0e7b237127..6862508a7845c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pem.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pem.iOS.cs @@ -1,15 +1,12 @@ // 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.Buffers; using System.Diagnostics; using System.Text; -using System.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pkcs12.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs similarity index 82% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pkcs12.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs index 8ff5988f557d2..01a6095841618 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/AppleCertificatePal.Pkcs12.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs @@ -1,20 +1,9 @@ // 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.Buffers; -using System.Collections.Generic; -using System.Diagnostics; -using System.Formats.Asn1; -using System.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; -using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.Asn1.Pkcs12; -using System.Text; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Pkcs12.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.macOS.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Pkcs12.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.macOS.cs index 1eaa3f8323adc..118f7067691e6 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.Pkcs12.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.macOS.cs @@ -1,13 +1,11 @@ // 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.Diagnostics; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.TempExportPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.TempExportPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs index 58553f50307b0..035dde20c5f08 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.TempExportPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs @@ -1,13 +1,11 @@ // 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.Diagnostics; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs index 5334d9eb31a0b..fb8c18acdcb39 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs @@ -1,19 +1,17 @@ // 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.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { @@ -62,11 +60,12 @@ internal sealed partial class AppleCertificatePal : ICertificatePal return null; } - public static ICertificatePal? FromOtherCert(X509Certificate cert) + public static ICertificatePal FromOtherCert(X509Certificate cert) { Debug.Assert(cert.Pal != null); ICertificatePal? pal = FromHandle(cert.Handle); + Debug.Assert(pal != null); GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use return pal; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12CertLoader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12CertLoader.iOS.cs similarity index 84% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12CertLoader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12CertLoader.iOS.cs index 8de11e24f7d80..c190f3400b959 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12CertLoader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12CertLoader.iOS.cs @@ -1,15 +1,10 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class ApplePkcs12CertLoader : ILoaderPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12Reader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.iOS.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12Reader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.iOS.cs index bb7acb4e27d9c..5900a979ed83c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/ApplePkcs12Reader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.iOS.cs @@ -1,16 +1,12 @@ // 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.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; -using System.Security.Cryptography.Apple; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class ApplePkcs12Reader : UnixPkcs12Reader { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ApplePkcs12Reader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.macOS.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ApplePkcs12Reader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.macOS.cs index 6820eec7b9d0b..7c1121a6c86ac 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ApplePkcs12Reader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ApplePkcs12Reader.macOS.cs @@ -1,16 +1,13 @@ // 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.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class ApplePkcs12Reader : UnixPkcs12Reader { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/AccessDescriptionAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/BasicConstraintsAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificatePolicyMappingAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificateTemplateAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/CertificationRequestInfoAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/DistributionPointNameAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/KeyUsageFlagsAsn.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/KeyUsageFlagsAsn.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/KeyUsageFlagsAsn.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/KeyUsageFlagsAsn.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyConstraintsAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/PolicyInformationAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ReasonFlagsAsn.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ReasonFlagsAsn.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ReasonFlagsAsn.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ReasonFlagsAsn.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.manual.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.manual.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.manual.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.manual.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TbsCertificateAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.manual.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.manual.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.manual.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.manual.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/TimeAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.manual.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.manual.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.manual.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.manual.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Asn1/ValidityAsn.xml.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertCollectionLoader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertCollectionLoader.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertCollectionLoader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertCollectionLoader.cs index 96e7477f0baa8..d4c802217fc29 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertCollectionLoader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertCollectionLoader.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Security.Cryptography.X509Certificates; using System.Threading; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class CertCollectionLoader : ILoaderPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateData.ManagedDecode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateData.ManagedDecode.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs index af1935e78dc42..0fffcd29701a6 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateData.ManagedDecode.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs @@ -1,17 +1,14 @@ // 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.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; using System.Text; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal enum GeneralNameType { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/CertificateExtensionsCommon.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/CertificateExtensionsCommon.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs index 78a34ac1d86c9..1476cea2d57f4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/CertificateExtensionsCommon.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs @@ -1,13 +1,9 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal static class CertificateExtensionsCommon { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Android.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Android.cs new file mode 100644 index 0000000000000..b11b726037ecd --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Android.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class CertificatePal + { + internal static partial ICertificatePal FromHandle(IntPtr handle) + { + return AndroidCertificatePal.FromHandle(handle); + } + + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom) + { + return AndroidCertificatePal.FromOtherCert(copyFrom); + } + + internal static partial ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + return AndroidCertificatePal.FromBlob(rawData, password, keyStorageFlags); + } + + internal static partial ICertificatePal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + return AndroidCertificatePal.FromFile(fileName, password, keyStorageFlags); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Apple.cs new file mode 100644 index 0000000000000..79ecb6e1586dc --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Apple.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class CertificatePal + { + internal static partial ICertificatePal FromHandle(IntPtr handle) + { + return AppleCertificatePal.FromHandle(handle, true)!; + } + + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom) + { + return AppleCertificatePal.FromOtherCert(copyFrom); + } + + internal static partial ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + return AppleCertificatePal.FromBlob(rawData, password, keyStorageFlags); + } + + internal static partial ICertificatePal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + return AppleCertificatePal.FromFile(fileName, password, keyStorageFlags); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.NotSupported.cs new file mode 100644 index 0000000000000..eb782130613cf --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.NotSupported.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class CertificatePal + { + internal static partial ICertificatePal FromHandle(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial ICertificatePal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.OpenSsl.cs new file mode 100644 index 0000000000000..7cec9a343b4e9 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.OpenSsl.cs @@ -0,0 +1,33 @@ +// 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.Diagnostics; +using System.Security.Cryptography; +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class CertificatePal + { + internal static partial ICertificatePal FromHandle(IntPtr handle) + { + return OpenSslX509CertificateReader.FromHandle(handle); + } + + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom) + { + return OpenSslX509CertificateReader.FromOtherCert(copyFrom); + } + + internal static partial ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return OpenSslX509CertificateReader.FromBlob(rawData, password, keyStorageFlags); + } + + internal static partial ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return OpenSslX509CertificateReader.FromFile(fileName, password, keyStorageFlags); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.Import.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs index d9c2d1364c45c..c3d082cec1577 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs @@ -1,26 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.IO; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -using Internal.Cryptography.Pal.Native; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class CertificatePal : IDisposable, ICertificatePal + internal sealed partial class CertificatePal { - public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { return FromBlobOrFile(rawData, null, password, keyStorageFlags); } - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { return FromBlobOrFile(ReadOnlySpan.Empty, fileName, password, keyStorageFlags); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.PrivateKey.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.PrivateKey.cs index 264079d50d9d1..a93817fac81cd 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.PrivateKey.cs @@ -1,16 +1,12 @@ // 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.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -using Internal.Cryptography.Pal.Native; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class CertificatePal : IDisposable, ICertificatePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs index a6fc4c8e57a90..244e151372c07 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs @@ -1,26 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Text; using System.Diagnostics; using System.Collections.Generic; using System.Runtime.InteropServices; -using Internal.Cryptography.Pal.Native; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -using System.Security.Cryptography; using SafeX509ChainHandle = Microsoft.Win32.SafeHandles.SafeX509ChainHandle; using SafePasswordHandle = Microsoft.Win32.SafeHandles.SafePasswordHandle; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class CertificatePal : IDisposable, ICertificatePal { private SafeCertContextHandle _certContext; - public static ICertificatePal FromHandle(IntPtr handle) + internal static partial ICertificatePal FromHandle(IntPtr handle) { if (handle == IntPtr.Zero) throw new ArgumentException(SR.Arg_InvalidHandle, nameof(handle)); @@ -39,7 +36,7 @@ public static ICertificatePal FromHandle(IntPtr handle) /// creating another X509Certificate object based on this one to ensure the underlying /// cert context is not released at the wrong time. ///
- public static ICertificatePal FromOtherCert(X509Certificate copyFrom) + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom) { CertificatePal pal = new CertificatePal((CertificatePal)copyFrom.Pal!); return pal; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.cs new file mode 100644 index 0000000000000..5703ec35dd47b --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal partial class CertificatePal + { + internal static partial ICertificatePal FromHandle(IntPtr handle); + + internal static partial ICertificatePal FromOtherCert(X509Certificate copyFrom); + + internal static partial ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags); + + internal static partial ICertificatePal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePolicy.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePolicy.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs index 5d3fe08cbfc76..22430e72cb5ea 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificatePolicy.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs @@ -1,14 +1,11 @@ // 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.Formats.Asn1; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class CertificatePolicy { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs index d1c6fc4f9fab7..02061235b3935 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Formats.Asn1; +using System.Runtime.Versioning; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.X509Certificates.Asn1; using Internal.Cryptography; @@ -16,6 +17,7 @@ namespace System.Security.Cryptography.X509Certificates /// allowing callers to create self-signed or chain-signed X.509 Public-Key Certificates, as well as /// create a certificate signing request blob to send to a Certificate Authority (CA). ///
+ [UnsupportedOSPlatform("browser")] public sealed class CertificateRequest { private readonly AsymmetricAlgorithm? _key; @@ -58,12 +60,9 @@ public sealed class CertificateRequest /// public CertificateRequest(string subjectName, ECDsa key, HashAlgorithmName hashAlgorithm) { - if (subjectName == null) - throw new ArgumentNullException(nameof(subjectName)); - if (key == null) - throw new ArgumentNullException(nameof(key)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(subjectName); + ArgumentNullException.ThrowIfNull(key); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); SubjectName = new X500DistinguishedName(subjectName); @@ -88,12 +87,9 @@ public CertificateRequest(string subjectName, ECDsa key, HashAlgorithmName hashA /// public CertificateRequest(X500DistinguishedName subjectName, ECDsa key, HashAlgorithmName hashAlgorithm) { - if (subjectName == null) - throw new ArgumentNullException(nameof(subjectName)); - if (key == null) - throw new ArgumentNullException(nameof(key)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(subjectName); + ArgumentNullException.ThrowIfNull(key); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); SubjectName = subjectName; @@ -122,14 +118,10 @@ public CertificateRequest(X500DistinguishedName subjectName, ECDsa key, HashAlgo /// public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (subjectName == null) - throw new ArgumentNullException(nameof(subjectName)); - if (key == null) - throw new ArgumentNullException(nameof(key)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(subjectName); + ArgumentNullException.ThrowIfNull(key); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); SubjectName = new X500DistinguishedName(subjectName); @@ -162,14 +154,10 @@ public CertificateRequest( HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (subjectName == null) - throw new ArgumentNullException(nameof(subjectName)); - if (key == null) - throw new ArgumentNullException(nameof(key)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(subjectName); + ArgumentNullException.ThrowIfNull(key); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); SubjectName = subjectName; @@ -194,12 +182,9 @@ public CertificateRequest( /// public CertificateRequest(X500DistinguishedName subjectName, PublicKey publicKey, HashAlgorithmName hashAlgorithm) { - if (subjectName == null) - throw new ArgumentNullException(nameof(subjectName)); - if (publicKey == null) - throw new ArgumentNullException(nameof(publicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(subjectName); + ArgumentNullException.ThrowIfNull(publicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); SubjectName = subjectName; PublicKey = publicKey; @@ -629,7 +614,7 @@ public X509Certificate2 Create( signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER); if (signatureAlgorithmAsn.Parameters.HasValue) { - Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value); + Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value.Span); } ArraySegment normalizedSerial = NormalizeSerialNumber(serialNumber); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs index 1af847e0defe9..3096f31fed005 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs @@ -6,33 +6,32 @@ using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class ChainPal { - public static IChainPal FromHandle(IntPtr chainContext) + internal static partial IChainPal FromHandle(IntPtr chainContext) { throw new PlatformNotSupportedException(); } - public static bool ReleaseSafeX509ChainHandle(IntPtr handle) + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle) { return true; } - public static IChainPal BuildChain( + internal static partial IChainPal? BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection? extraStore, - OidCollection applicationPolicy, - OidCollection certificatePolicy, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, @@ -86,13 +85,13 @@ public void Dispose() return false; } - return ChainVerifier.Verify(ChainElements!, flags); + return UnixChainVerifier.Verify(ChainElements!, flags); } internal void Initialize( ICertificatePal cert, X509Certificate2Collection? extraStore, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode) { List extraCertHandles = new List() { ((AndroidCertificatePal)cert).SafeHandle }; @@ -186,8 +185,8 @@ internal void Initialize( internal void Evaluate( DateTime verificationTime, - OidCollection applicationPolicy, - OidCollection certificatePolicy, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ChainPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs index 2a26d06f80580..81e9b3678b540 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/ChainPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs @@ -1,15 +1,13 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class SecTrustChainPal : IChainPal { @@ -37,7 +35,7 @@ internal void OpenTrustHandle( ICertificatePal leafCert, X509Certificate2Collection? extraStore, X509RevocationMode revocationMode, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode) { _revocationMode = revocationMode; @@ -115,7 +113,7 @@ public void Dispose() { exception = null; - return ChainVerifier.Verify(ChainElements!, flags); + return UnixChainVerifier.Verify(ChainElements!, flags); } private SafeCreateHandle PreparePoliciesArray(bool checkRevocation) @@ -150,7 +148,7 @@ private SafeCreateHandle PreparePoliciesArray(bool checkRevocation) private SafeCreateHandle PrepareCertsArray( ICertificatePal cert, X509Certificate2Collection? extraStore, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode) { List safeHandles = new List { ((AppleCertificatePal)cert).CertificateHandle }; @@ -227,8 +225,8 @@ private SafeCreateHandle GetCertsArray(IList safeHandles) internal void Execute( DateTime verificationTime, bool allowNetwork, - OidCollection applicationPolicy, - OidCollection certificatePolicy, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, X509RevocationFlag revocationFlag) { int osStatus; @@ -310,8 +308,8 @@ private static (X509Certificate2, int)[] ParseResults( private bool IsPolicyMatch( (X509Certificate2, int)[] elements, - OidCollection applicationPolicy, - OidCollection certificatePolicy) + OidCollection? applicationPolicy, + OidCollection? certificatePolicy) { if (applicationPolicy?.Count > 0 || certificatePolicy?.Count > 0) { @@ -551,7 +549,7 @@ private X509ChainErrorMapping(X509ChainStatusFlags flag) internal sealed partial class ChainPal { - public static IChainPal FromHandle(IntPtr chainContext) + internal static partial IChainPal FromHandle(IntPtr chainContext) { // This is possible to do on Apple's platform, but is tricky in execution. // In Windows, CertGetCertificateChain is what allocates the handle, and it does @@ -581,21 +579,21 @@ public static IChainPal FromHandle(IntPtr chainContext) throw new PlatformNotSupportedException(); } - public static bool ReleaseSafeX509ChainHandle(IntPtr handle) + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle) { Interop.CoreFoundation.CFRelease(handle); return true; } - public static IChainPal BuildChain( + internal static partial IChainPal? BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection? extraStore, - OidCollection applicationPolicy, - OidCollection certificatePolicy, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.NotSupported.cs new file mode 100644 index 0000000000000..fd6bf95e4baa3 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.NotSupported.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class ChainPal + { + internal static partial IChainPal FromHandle(IntPtr chainContext) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial IChainPal? BuildChain( + bool useMachineContext, + ICertificatePal cert, + X509Certificate2Collection? extraStore, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, + X509RevocationMode revocationMode, + X509RevocationFlag revocationFlag, + X509Certificate2Collection? customTrustStore, + X509ChainTrustMode trustMode, + DateTime verificationTime, + TimeSpan timeout, + bool disableAia) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs index 29cdfa5f71cb7..fa6db427ac752 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs @@ -1,24 +1,21 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class ChainPal { private static readonly TimeSpan s_maxUrlRetrievalTimeout = TimeSpan.FromMinutes(1); - public static IChainPal FromHandle(IntPtr chainContext) + internal static partial IChainPal FromHandle(IntPtr chainContext) { throw new PlatformNotSupportedException(); } - public static bool ReleaseSafeX509ChainHandle(IntPtr handle) + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle) { return true; } @@ -28,15 +25,15 @@ public static void FlushStores() OpenSslX509ChainProcessor.FlushStores(); } - public static IChainPal BuildChain( + internal static partial IChainPal? BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection? extraStore, - OidCollection applicationPolicy, - OidCollection certificatePolicy, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.BuildChain.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.BuildChain.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.BuildChain.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.BuildChain.cs index ce38255742da7..e1fee5d313766 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.BuildChain.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.BuildChain.cs @@ -1,25 +1,20 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Runtime.InteropServices; - -using Internal.Cryptography.Pal.Native; - -using System.Security.Cryptography; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; using SafeX509ChainHandle = Microsoft.Win32.SafeHandles.SafeX509ChainHandle; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class ChainPal : IDisposable, IChainPal { /// /// Does not throw on error. Returns null ChainPal instead. /// - public static ChainPal? BuildChain( + internal static partial IChainPal? BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection? extraStore, @@ -138,10 +133,5 @@ private static Interop.Crypt32.CertChainFlags MapRevocationFlags( return dwFlags; } - - private ChainPal(SafeX509ChainHandle chain) - { - _chain = chain; - } } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.GetChainStatusInformation.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.GetChainStatusInformation.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.GetChainStatusInformation.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.GetChainStatusInformation.cs index cd5b60e21dd25..e22f6c8adb49a 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.GetChainStatusInformation.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.GetChainStatusInformation.cs @@ -1,14 +1,9 @@ // 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.Text; using System.Diagnostics; -using System.Security.Cryptography.X509Certificates; -using Internal.Cryptography.Pal.Native; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class ChainPal : IDisposable, IChainPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.cs index 5b80a71eb8c48..53006b879413b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/ChainPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Windows.cs @@ -1,20 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal.Native; -using Microsoft.Win32.SafeHandles; -using System; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class ChainPal : IDisposable, IChainPal { private SafeX509ChainHandle _chain; - public static IChainPal FromHandle(IntPtr chainContext) + private ChainPal(SafeX509ChainHandle chain) + { + _chain = chain; + } + + internal static partial IChainPal FromHandle(IntPtr chainContext) { if (chainContext == IntPtr.Zero) throw new ArgumentNullException(nameof(chainContext)); @@ -103,7 +105,7 @@ public SafeX509ChainHandle SafeHandle } } - public static bool ReleaseSafeX509ChainHandle(IntPtr handle) + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle) { Interop.Crypt32.CertFreeCertificateChain(handle); return true; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.cs new file mode 100644 index 0000000000000..2d765b6f8158d --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal partial class ChainPal + { + internal static partial IChainPal FromHandle(IntPtr chainContext); + + internal static partial bool ReleaseSafeX509ChainHandle(IntPtr handle); + + internal static partial IChainPal? BuildChain( + bool useMachineContext, + ICertificatePal cert, + X509Certificate2Collection? extraStore, + OidCollection? applicationPolicy, + OidCollection? certificatePolicy, + X509RevocationMode revocationMode, + X509RevocationFlag revocationFlag, + X509Certificate2Collection? customTrustStore, + X509ChainTrustMode trustMode, + DateTime verificationTime, + TimeSpan timeout, + bool disableAia); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs index c234da0847316..ac63e7062228d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.Cryptography.Pal; using System.Runtime.Versioning; namespace System.Security.Cryptography.X509Certificates diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs index 4ba58e63590e3..8694dc25423a2 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ECDsaCertificateExtensions.cs @@ -1,9 +1,7 @@ // 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.Cryptography; -using Internal.Cryptography.Pal; namespace System.Security.Cryptography.X509Certificates { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/ECDsaX509SignatureGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ECDsaX509SignatureGenerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/ECDsaX509SignatureGenerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ECDsaX509SignatureGenerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ErrorCode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ErrorCode.cs similarity index 83% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ErrorCode.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ErrorCode.cs index a309d5963e3a8..06973a4da75bf 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ErrorCode.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ErrorCode.cs @@ -1,19 +1,13 @@ // 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.Text; -using System.Diagnostics; -using System.Globalization; -using System.Security.Cryptography; - -namespace Internal.Cryptography +namespace System.Security.Cryptography.X509Certificates { + // Error codes for specific throw sites. // - // Error codes for specific throw sites. Defined outside of Internal.Crytography.Pal.Native as some non-Pal code uses these. - // Since these error codes are publicly surfaced through the Exception class, these hresults are effectively managed exchange values despite + // Since these error codes are publicly surfaced through the Exception class, + // these HResults are effectively managed exchange values despite // their Win32 origin. - // internal static class ErrorCode { public const int CERT_E_CHAINING = unchecked((int)0x800B010A); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/FindPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Android.cs similarity index 79% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/FindPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Android.cs index 6775a18d5626c..c7fb948ee82ae 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/FindPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Android.cs @@ -1,15 +1,11 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class FindPal { - internal static IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) + private static partial IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) { return new AndroidCertificateFinder(findFrom, copyTo, validOnly); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Apple.cs similarity index 81% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Apple.cs index 645d2bd398c2d..8060d6d9a01da 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Apple.cs @@ -1,15 +1,11 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class FindPal { - internal static IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) + private static partial IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) { return new AppleCertificateFinder(findFrom, copyTo, validOnly); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.NotSupported.cs new file mode 100644 index 0000000000000..0c3dd97f84219 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.NotSupported.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class FindPal + { + private static partial IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.OpenSsl.cs new file mode 100644 index 0000000000000..d7a6a64acec6c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.OpenSsl.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Numerics; +using Internal.Cryptography; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class FindPal + { + private static partial IFindPal OpenPal( + X509Certificate2Collection findFrom, + X509Certificate2Collection copyTo, + bool validOnly) + { + return new OpenSslCertificateFinder(findFrom, copyTo, validOnly); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/FindPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Windows.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/FindPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Windows.cs index 4cadc49aaf2c6..8d02c46c3f52a 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/FindPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.Windows.cs @@ -1,16 +1,13 @@ // 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.Diagnostics; using System.Numerics; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Internal.Cryptography.Pal.Native; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class FindPal : IFindPal { @@ -18,14 +15,14 @@ internal sealed partial class FindPal : IFindPal private readonly X509Certificate2Collection _copyTo; private readonly bool _validOnly; - internal FindPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) + private FindPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) { _storePal = (StorePal)StorePal.LinkFromCertificateCollection(findFrom); _copyTo = copyTo; _validOnly = validOnly; } - internal static IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) + private static partial IFindPal OpenPal(X509Certificate2Collection findFrom, X509Certificate2Collection copyTo, bool validOnly) { return new FindPal(findFrom, copyTo, validOnly); } @@ -369,7 +366,7 @@ private static bool VerifyCertificateIgnoringErrors(SafeCertContextHandle pCertC { // This needs to be kept in sync with IsCertValid in the // Unix/OpenSSL PAL version (and potentially any other PALs that come about) - ChainPal? chainPal = ChainPal.BuildChain( + ChainPal? chainPal = (ChainPal?)ChainPal.BuildChain( false, CertificatePal.FromHandle(pCertContext.DangerousGetHandle()), extraStore: null, diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/FindPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.cs similarity index 60% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/FindPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.cs index 0cdbbe6555ebe..d62a967df7959 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/FindPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/FindPal.cs @@ -1,16 +1,14 @@ // 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.Numerics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class FindPal + internal partial class FindPal { private const int NamedKeyUsageFlagsCount = 9; @@ -35,6 +33,11 @@ static FindPal() } #endif + private static partial IFindPal OpenPal( + X509Certificate2Collection findFrom, + X509Certificate2Collection copyTo, + bool validOnly); + public static X509Certificate2Collection FindFromCollection( X509Certificate2Collection coll, X509FindType findType, @@ -48,107 +51,107 @@ public static X509Certificate2Collection FindFromCollection( switch (findType) { case X509FindType.FindByThumbprint: - { - byte[] thumbPrint = ConfirmedCast(findValue).DecodeHexString(); - findPal.FindByThumbprint(thumbPrint); - break; - } + { + byte[] thumbPrint = ConfirmedCast(findValue).LaxDecodeHexString(); + findPal.FindByThumbprint(thumbPrint); + break; + } case X509FindType.FindBySubjectName: - { - string subjectName = ConfirmedCast(findValue); - findPal.FindBySubjectName(subjectName); - break; - } + { + string subjectName = ConfirmedCast(findValue); + findPal.FindBySubjectName(subjectName); + break; + } case X509FindType.FindBySubjectDistinguishedName: - { - string subjectDistinguishedName = ConfirmedCast(findValue); - findPal.FindBySubjectDistinguishedName(subjectDistinguishedName); - break; - } + { + string subjectDistinguishedName = ConfirmedCast(findValue); + findPal.FindBySubjectDistinguishedName(subjectDistinguishedName); + break; + } case X509FindType.FindByIssuerName: - { - string issuerName = ConfirmedCast(findValue); - findPal.FindByIssuerName(issuerName); - break; - } + { + string issuerName = ConfirmedCast(findValue); + findPal.FindByIssuerName(issuerName); + break; + } case X509FindType.FindByIssuerDistinguishedName: - { - string issuerDistinguishedName = ConfirmedCast(findValue); - findPal.FindByIssuerDistinguishedName(issuerDistinguishedName); - break; - } + { + string issuerDistinguishedName = ConfirmedCast(findValue); + findPal.FindByIssuerDistinguishedName(issuerDistinguishedName); + break; + } case X509FindType.FindBySerialNumber: - { - string decimalOrHexString = ConfirmedCast(findValue); - - // FindBySerialNumber allows the input format to be either in - // hex or decimal. Since we can't know which one was intended, - // it compares against both interpretations and treats a match - // of either as a successful find. - - // string is big-endian, BigInteger constructor requires little-endian. - byte[] hexBytes = decimalOrHexString.DecodeHexString(); - Array.Reverse(hexBytes); - - BigInteger hexValue = PositiveBigIntegerFromByteArray(hexBytes); - BigInteger decimalValue = LaxParseDecimalBigInteger(decimalOrHexString); - findPal.FindBySerialNumber(hexValue, decimalValue); - break; - } + { + string decimalOrHexString = ConfirmedCast(findValue); + + // FindBySerialNumber allows the input format to be either in + // hex or decimal. Since we can't know which one was intended, + // it compares against both interpretations and treats a match + // of either as a successful find. + + // string is big-endian, BigInteger constructor requires little-endian. + byte[] hexBytes = decimalOrHexString.LaxDecodeHexString(); + Array.Reverse(hexBytes); + + BigInteger hexValue = PositiveBigIntegerFromByteArray(hexBytes); + BigInteger decimalValue = LaxParseDecimalBigInteger(decimalOrHexString); + findPal.FindBySerialNumber(hexValue, decimalValue); + break; + } case X509FindType.FindByTimeValid: - { - DateTime dateTime = ConfirmedCast(findValue); - findPal.FindByTimeValid(dateTime); - break; - } + { + DateTime dateTime = ConfirmedCast(findValue); + findPal.FindByTimeValid(dateTime); + break; + } case X509FindType.FindByTimeNotYetValid: - { - DateTime dateTime = ConfirmedCast(findValue); - findPal.FindByTimeNotYetValid(dateTime); - break; - } + { + DateTime dateTime = ConfirmedCast(findValue); + findPal.FindByTimeNotYetValid(dateTime); + break; + } case X509FindType.FindByTimeExpired: - { - DateTime dateTime = ConfirmedCast(findValue); - findPal.FindByTimeExpired(dateTime); - break; - } + { + DateTime dateTime = ConfirmedCast(findValue); + findPal.FindByTimeExpired(dateTime); + break; + } case X509FindType.FindByTemplateName: - { - string expected = ConfirmedCast(findValue); - findPal.FindByTemplateName(expected); - break; - } + { + string expected = ConfirmedCast(findValue); + findPal.FindByTemplateName(expected); + break; + } case X509FindType.FindByApplicationPolicy: - { - string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.Policy); - findPal.FindByApplicationPolicy(oidValue); - break; - } + { + string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.Policy); + findPal.FindByApplicationPolicy(oidValue); + break; + } case X509FindType.FindByCertificatePolicy: - { - string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.Policy); - findPal.FindByCertificatePolicy(oidValue); - break; - } + { + string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.Policy); + findPal.FindByCertificatePolicy(oidValue); + break; + } case X509FindType.FindByExtension: - { - string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.ExtensionOrAttribute); - findPal.FindByExtension(oidValue); - break; - } + { + string oidValue = ConfirmedOidValue(findPal, findValue, OidGroup.ExtensionOrAttribute); + findPal.FindByExtension(oidValue); + break; + } case X509FindType.FindByKeyUsage: - { - X509KeyUsageFlags keyUsage = ConfirmedX509KeyUsage(findValue); - findPal.FindByKeyUsage(keyUsage); - break; - } + { + X509KeyUsageFlags keyUsage = ConfirmedX509KeyUsage(findValue); + findPal.FindByKeyUsage(keyUsage); + break; + } case X509FindType.FindBySubjectKeyIdentifier: - { - byte[] keyIdentifier = ConfirmedCast(findValue).DecodeHexString(); - findPal.FindBySubjectKeyIdentifier(keyIdentifier); - break; - } + { + byte[] keyIdentifier = ConfirmedCast(findValue).LaxDecodeHexString(); + findPal.FindBySubjectKeyIdentifier(keyIdentifier); + break; + } default: throw new CryptographicException(SR.Cryptography_X509_InvalidFindType); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePal.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePal.cs index d32ddcef440b2..931e5b17618ec 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePal.cs @@ -1,14 +1,11 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Text; -namespace Internal.Cryptography +namespace System.Security.Cryptography.X509Certificates { [StructLayout(LayoutKind.Sequential)] internal struct PolicyData diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePalCore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs similarity index 83% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePalCore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs index 6a8fa71d23343..6103cae191763 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ICertificatePalCore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs @@ -1,14 +1,9 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography +namespace System.Security.Cryptography.X509Certificates { /// Provides specific implementation for X509Certificate. internal interface ICertificatePalCore : IDisposable diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IChainPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IChainPal.cs similarity index 80% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IChainPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IChainPal.cs index 576d095671f01..797c071f7e7ca 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IChainPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IChainPal.cs @@ -1,13 +1,9 @@ // 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.Diagnostics.CodeAnalysis; -using System.Security.Cryptography.X509Certificates; - using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface IChainPal : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IExportPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IExportPal.cs similarity index 75% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IExportPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IExportPal.cs index 1c5748310eb5d..36937ea17690c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IExportPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IExportPal.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Win32.SafeHandles; -using System; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface IExportPal : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IFindPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IFindPal.cs similarity index 89% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IFindPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IFindPal.cs index 93ea832597f74..13173cd06e558 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IFindPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IFindPal.cs @@ -1,12 +1,9 @@ // 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.Numerics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface IFindPal : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ILoaderPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ILoaderPal.cs similarity index 71% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ILoaderPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ILoaderPal.cs index 95bb7259062c1..47d3cb8435903 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/ILoaderPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ILoaderPal.cs @@ -1,10 +1,7 @@ // 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.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface ILoaderPal : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IStorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IStorePal.cs similarity index 80% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IStorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IStorePal.cs index 82faad45710e2..a785607792ea9 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IStorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IStorePal.cs @@ -1,11 +1,9 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface IStorePal : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IX509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IX509Pal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs index dcc3150a35ef8..d83470c3ea1ae 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/IX509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs @@ -1,11 +1,7 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal interface IX509Pal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedCertificateFinder.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedCertificateFinder.cs index e174a9fd59366..d56db1a0c2611 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedCertificateFinder.cs @@ -1,16 +1,14 @@ // 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.Formats.Asn1; using System.Numerics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal abstract class ManagedCertificateFinder : IFindPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedX509ExtensionProcessor.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedX509ExtensionProcessor.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedX509ExtensionProcessor.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedX509ExtensionProcessor.cs index 976021ff7a748..1749598a6f547 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedX509ExtensionProcessor.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ManagedX509ExtensionProcessor.cs @@ -1,15 +1,12 @@ // 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.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal class ManagedX509ExtensionProcessor { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/OpenFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/OpenFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenFlags.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedDirectoryStoreProvider.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedDirectoryStoreProvider.cs index 8c3727b98289d..da0fc5dff1580 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedDirectoryStoreProvider.cs @@ -1,14 +1,13 @@ // 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.Diagnostics; using System.IO; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed class CachedDirectoryStoreProvider + internal sealed class OpenSslCachedDirectoryStoreProvider { // These intervals are mostly arbitrary. // Prior to this caching these stores were always read "hot" from disk, and 30 seconds @@ -24,9 +23,9 @@ internal sealed class CachedDirectoryStoreProvider private DateTime _loadLastWrite; private bool _forceRefresh; - internal CachedDirectoryStoreProvider(string storeName) + internal OpenSslCachedDirectoryStoreProvider(string storeName) { - string storePath = DirectoryBasedStoreProvider.GetStorePath(storeName); + string storePath = OpenSslDirectoryBasedStoreProvider.GetStorePath(storeName); _storeDirectoryInfo = new DirectoryInfo(storePath); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs index b6a9ea5505c16..4c9643c01e2fc 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs @@ -1,18 +1,16 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed class CachedSystemStoreProvider : IStorePal + internal sealed class OpenSslCachedSystemStoreProvider : IStorePal { // These intervals are mostly arbitrary. // Prior to this refreshing cache the system collections were read just once per process, on the @@ -34,16 +32,16 @@ internal sealed class CachedSystemStoreProvider : IStorePal private readonly bool _isRoot; - private CachedSystemStoreProvider(bool isRoot) + private OpenSslCachedSystemStoreProvider(bool isRoot) { _isRoot = isRoot; } - internal static CachedSystemStoreProvider MachineRoot { get; } = - new CachedSystemStoreProvider(true); + internal static OpenSslCachedSystemStoreProvider MachineRoot { get; } = + new OpenSslCachedSystemStoreProvider(true); - internal static CachedSystemStoreProvider MachineIntermediate { get; } = - new CachedSystemStoreProvider(false); + internal static OpenSslCachedSystemStoreProvider MachineIntermediate { get; } = + new OpenSslCachedSystemStoreProvider(false); public void Dispose() diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs index cd7ef4b84858a..1c5656ac5b462 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs @@ -1,19 +1,16 @@ // 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.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal static class CertificateAssetDownloader + internal static class OpenSslCertificateAssetDownloader { private static readonly Func? s_downloadBytes = CreateDownloadBytesFunc(); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateFinder.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateFinder.cs index 8c6d167fdba9d..03566b40a492c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateFinder.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class OpenSslCertificateFinder : ManagedCertificateFinder { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CrlCache.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CrlCache.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs index 4dd122871b0a7..d1c4a946c629f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CrlCache.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs @@ -1,20 +1,17 @@ // 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.Diagnostics; using System.Formats.Asn1; using System.IO; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal static class CrlCache + internal static class OpenSslCrlCache { private static readonly string s_crlDir = PersistedFiles.GetUserFeatureDirectory( @@ -156,7 +153,7 @@ private static void DownloadAndAddCrl( { // X509_STORE_add_crl will increase the refcount on the CRL object, so we should still // dispose our copy. - using (SafeX509CrlHandle? crl = CertificateAssetDownloader.DownloadCrl(url, downloadTimeout)) + using (SafeX509CrlHandle? crl = OpenSslCertificateAssetDownloader.DownloadCrl(url, downloadTimeout)) { // null is a valid return (e.g. no remainingDownloadTime) if (crl != null && !crl.IsInvalid) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslDirectoryBasedStoreProvider.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslDirectoryBasedStoreProvider.cs index 0928ced4c2784..085ae91f870d3 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslDirectoryBasedStoreProvider.cs @@ -1,21 +1,18 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Text; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { /// /// Provides an implementation of an X509Store which is backed by files in a directory. /// - internal sealed class DirectoryBasedStoreProvider : IStorePal + internal sealed class OpenSslDirectoryBasedStoreProvider : IStorePal { // {thumbprint}.1.pfx to {thumbprint}.9.pfx private const int MaxSaveAttempts = 9; @@ -32,7 +29,7 @@ internal sealed class DirectoryBasedStoreProvider : IStorePal private readonly bool _readOnly; #if DEBUG - static DirectoryBasedStoreProvider() + static OpenSslDirectoryBasedStoreProvider() { Debug.Assert( 0 == OpenFlags.ReadOnly, @@ -40,7 +37,7 @@ static DirectoryBasedStoreProvider() } #endif - internal DirectoryBasedStoreProvider(string storeName, OpenFlags openFlags) + internal OpenSslDirectoryBasedStoreProvider(string storeName, OpenFlags openFlags) { if (string.IsNullOrEmpty(storeName)) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ExportProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslExportProvider.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ExportProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslExportProvider.cs index e692706909fb1..e8dcae113b2fe 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ExportProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslExportProvider.cs @@ -1,22 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed class ExportProvider : UnixExportProvider + internal sealed class OpenSslExportProvider : UnixExportProvider { - internal ExportProvider(ICertificatePalCore singleCertPal) + internal OpenSslExportProvider(ICertificatePalCore singleCertPal) : base(singleCertPal) { } - internal ExportProvider(X509Certificate2Collection certs) + internal OpenSslExportProvider(X509Certificate2Collection certs) : base(certs) { } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslPkcs12Reader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcs12Reader.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslPkcs12Reader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcs12Reader.cs index 78acf1c2adac1..79b7aed738772 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslPkcs12Reader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcs12Reader.cs @@ -1,13 +1,11 @@ // 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.Diagnostics.CodeAnalysis; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class OpenSslPkcs12Reader : UnixPkcs12Reader { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/PkcsFormatReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/PkcsFormatReader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs index b7f10c81a8c66..4e07816023dae 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/PkcsFormatReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs @@ -8,9 +8,9 @@ using System.Security.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal static class PkcsFormatReader + internal static class OpenSslPkcsFormatReader { internal static bool IsPkcs7(ReadOnlySpan rawData) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/SingleCertLoader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslSingleCertLoader.cs similarity index 79% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/SingleCertLoader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslSingleCertLoader.cs index 0e149ff00c88f..35ef452c74b6b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/SingleCertLoader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslSingleCertLoader.cs @@ -2,16 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Security.Cryptography.X509Certificates; using System.Threading; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed class SingleCertLoader : ILoaderPal + internal sealed class OpenSslSingleCertLoader : ILoaderPal { private ICertificatePal? _cert; - public SingleCertLoader(ICertificatePal cert) + public OpenSslSingleCertLoader(ICertificatePal cert) { _cert = cert; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509CertificateReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509CertificateReader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs index 27f1df388e7f1..5ab92850cbd07 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509CertificateReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs @@ -1,19 +1,16 @@ // 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.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Text; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class OpenSslX509CertificateReader : ICertificatePal { @@ -53,9 +50,9 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH if (TryReadX509Der(rawData, out cert) || TryReadX509Pem(rawData, out cert) || - PkcsFormatReader.TryReadPkcs7Der(rawData, out cert) || - PkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) || - PkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out cert, out openSslException)) + OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out cert) || + OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) || + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out cert, out openSslException)) { if (cert == null) { @@ -86,7 +83,7 @@ public static ICertificatePal FromFile(string fileName, SafePasswordHandle passw if (pal == null) { - PkcsFormatReader.TryReadPkcs12( + OpenSslPkcsFormatReader.TryReadPkcs12( File.ReadAllBytes(fileName), password, ephemeralSpecified, @@ -127,7 +124,7 @@ public static ICertificatePal FromFile(string fileName, SafePasswordHandle passw // Rewind, try again. RewindBio(bio, bioPosition); - if (PkcsFormatReader.TryReadPkcs7Pem(bio, out certPal)) + if (OpenSslPkcsFormatReader.TryReadPkcs7Pem(bio, out certPal)) { return certPal; } @@ -135,7 +132,7 @@ public static ICertificatePal FromFile(string fileName, SafePasswordHandle passw // Rewind, try again. RewindBio(bio, bioPosition); - if (PkcsFormatReader.TryReadPkcs7Der(bio, out certPal)) + if (OpenSslPkcsFormatReader.TryReadPkcs7Der(bio, out certPal)) { return certPal; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs index 7ec3e6f8f28ba..a8d232497f4b3 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs @@ -1,23 +1,21 @@ // 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.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates.Asn1; using System.Text; using Microsoft.Win32.SafeHandles; +using Internal.Cryptography; using X509VerifyStatusCodeUniversal = Interop.Crypto.X509VerifyStatusCodeUniversal; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class OpenSslX509ChainProcessor : IChainPal { @@ -27,14 +25,14 @@ internal sealed class OpenSslX509ChainProcessor : IChainPal // 10 is plenty big. private const int DefaultChainCapacity = 10; - private static readonly CachedDirectoryStoreProvider s_userRootStore = - new CachedDirectoryStoreProvider(X509Store.RootStoreName); + private static readonly OpenSslCachedDirectoryStoreProvider s_userRootStore = + new OpenSslCachedDirectoryStoreProvider(X509Store.RootStoreName); - private static readonly CachedDirectoryStoreProvider s_userIntermediateStore = - new CachedDirectoryStoreProvider(X509Store.IntermediateCAStoreName); + private static readonly OpenSslCachedDirectoryStoreProvider s_userIntermediateStore = + new OpenSslCachedDirectoryStoreProvider(X509Store.IntermediateCAStoreName); - private static readonly CachedDirectoryStoreProvider s_userPersonalStore = - new CachedDirectoryStoreProvider(X509Store.MyStoreName); + private static readonly OpenSslCachedDirectoryStoreProvider s_userPersonalStore = + new OpenSslCachedDirectoryStoreProvider(X509Store.MyStoreName); // Save the results of GetX509VerifyCertErrorString as we look them up. // On Windows we preload the entire string table, but on Linux we'll delay-load memoize @@ -82,7 +80,7 @@ public void Dispose() public bool? Verify(X509VerificationFlags flags, out Exception? exception) { exception = null; - return ChainVerifier.Verify(ChainElements!, flags); + return UnixChainVerifier.Verify(ChainElements!, flags); } public X509ChainElement[]? ChainElements { get; private set; } @@ -95,12 +93,12 @@ public SafeX509ChainHandle? SafeHandle internal static OpenSslX509ChainProcessor InitiateChain( SafeX509Handle leafHandle, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan remainingDownloadTime) { - CachedSystemStoreProvider.GetNativeCollections( + OpenSslCachedSystemStoreProvider.GetNativeCollections( out SafeX509StackHandle systemTrust, out SafeX509StackHandle systemIntermediate); @@ -145,7 +143,7 @@ internal static OpenSslX509ChainProcessor InitiateChain( private static SafeX509StoreHandle GetTrustStore( X509ChainTrustMode trustMode, - X509Certificate2Collection customTrustStore, + X509Certificate2Collection? customTrustStore, SafeX509StackHandle untrusted, SafeX509StackHandle systemTrust) { @@ -153,10 +151,17 @@ private static SafeX509StoreHandle GetTrustStore( { using (SafeX509StackHandle customTrust = Interop.Crypto.NewX509Stack()) { - foreach (X509Certificate2 cert in customTrustStore) + if (customTrustStore != null) { - SafeX509StackHandle toAdd = cert.SubjectName.RawData.ContentsEqual(cert.IssuerName.RawData) ? customTrust : untrusted; - AddToStackAndUpRef(((OpenSslX509CertificateReader)cert.Pal!).SafeHandle, toAdd); + foreach (X509Certificate2 cert in customTrustStore) + { + SafeX509StackHandle toAdd = + cert.SubjectName.RawData.ContentsEqual(cert.IssuerName.RawData) ? + customTrust : + untrusted; + + AddToStackAndUpRef(((OpenSslX509CertificateReader)cert.Pal!).SafeHandle, toAdd); + } } return Interop.Crypto.X509ChainNew(customTrust, SafeX509StackHandle.InvalidHandle); @@ -374,7 +379,7 @@ internal void ProcessRevocation( using (SafeX509Handle cert = Interop.Crypto.X509UpRef(Interop.Crypto.GetX509StackField(chainStack, i))) { - CrlCache.AddCrlForCertificate( + OpenSslCrlCache.AddCrlForCertificate( cert, _store, revocationMode, @@ -613,7 +618,7 @@ private WorkingChain BuildWorkingChain() return workingChain; } - internal void Finish(OidCollection applicationPolicy, OidCollection certificatePolicy) + internal void Finish(OidCollection? applicationPolicy, OidCollection? certificatePolicy) { WorkingChain? workingChain = _workingChain; @@ -659,7 +664,7 @@ private Interop.Crypto.X509VerifyStatusCode CheckOcsp( SafeX509Handle certHandle, X509RevocationMode revocationMode) { - string ocspCache = CrlCache.GetCachedOcspResponseDirectory(); + string ocspCache = OpenSslCrlCache.GetCachedOcspResponseDirectory(); Interop.Crypto.X509VerifyStatusCode status = Interop.Crypto.X509ChainGetCachedOcspStatus(_storeCtx, ocspCache, chainDepth); @@ -703,7 +708,7 @@ private Interop.Crypto.X509VerifyStatusCode CheckOcsp( // // So, for now, only try GET. SafeOcspResponseHandle? resp = - CertificateAssetDownloader.DownloadOcspGet(requestUrl, _downloadTimeout); + OpenSslCertificateAssetDownloader.DownloadOcspGet(requestUrl, _downloadTimeout); using (resp) { @@ -864,7 +869,7 @@ private static void ProcessPolicy( X509ChainElement[] elements, ref List? overallStatus, OidCollection? applicationPolicy, - OidCollection certificatePolicy) + OidCollection? certificatePolicy) { List certsToRead = new List(); @@ -1140,7 +1145,7 @@ private static X509ChainStatusFlags MapOpenSsl111Code(Interop.Crypto.X509VerifyS return null; } - return CertificateAssetDownloader.DownloadCertificate(uri, downloadTimeout); + return OpenSslCertificateAssetDownloader.DownloadCertificate(uri, downloadTimeout); } private static string? GetOcspEndpoint(SafeX509Handle cert) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509Encoder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509Encoder.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs index 5694c2c799206..a25546c7a44e2 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509Encoder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs @@ -1,16 +1,13 @@ // 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.Diagnostics; using System.Formats.Asn1; using System.IO; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class OpenSslX509Encoder : ManagedX509ExtensionProcessor, IX509Pal { @@ -78,7 +75,7 @@ public X509ContentType GetCertContentType(ReadOnlySpan rawData) } } - if (PkcsFormatReader.IsPkcs7(rawData)) + if (OpenSslPkcsFormatReader.IsPkcs7(rawData)) { return X509ContentType.Pkcs7; } @@ -133,14 +130,14 @@ public X509ContentType GetCertContentType(string fileName) // X509ContentType.Pkcs7 { - if (PkcsFormatReader.IsPkcs7Der(fileBio)) + if (OpenSslPkcsFormatReader.IsPkcs7Der(fileBio)) { return X509ContentType.Pkcs7; } OpenSslX509CertificateReader.RewindBio(fileBio, bioPosition); - if (PkcsFormatReader.IsPkcs7Pem(fileBio)) + if (OpenSslPkcsFormatReader.IsPkcs7Pem(fileBio)) { return X509ContentType.Pkcs7; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs index 963ec96438197..ae14cc735a48f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs @@ -50,7 +50,7 @@ internal byte[] ToPkcs10Request(X509SignatureGenerator signatureGenerator, HashA signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER); if (signatureAlgorithmAsn.Parameters.HasValue) { - Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value); + Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value.Span); } SubjectPublicKeyInfoAsn spki = default; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs9ExtensionRequest.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs9ExtensionRequest.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs9ExtensionRequest.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs9ExtensionRequest.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs index 129932a334505..33f24dd1f50a5 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs @@ -1,16 +1,12 @@ // 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.Buffers; using System.Formats.Asn1; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography.Asn1; -using Internal.Cryptography; -using Internal.Cryptography.Pal; - namespace System.Security.Cryptography.X509Certificates { public sealed class PublicKey @@ -152,6 +148,7 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source /// /// The key contents are corrupt or could not be read successfully. /// + [UnsupportedOSPlatform("browser")] public RSA? GetRSAPublicKey() { if (_oid.Value != Oids.Rsa) @@ -180,6 +177,7 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source /// /// The key contents are corrupt or could not be read successfully. /// + [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] public DSA? GetDSAPublicKey() @@ -210,6 +208,7 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source /// /// The key contents are corrupt or could not be read successfully. /// + [UnsupportedOSPlatform("browser")] public ECDsa? GetECDsaPublicKey() { if (_oid.Value != Oids.EcPublicKey) @@ -239,6 +238,7 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source /// /// The key contents are corrupt or could not be read successfully. /// + [UnsupportedOSPlatform("browser")] public ECDiffieHellman? GetECDiffieHellmanPublicKey() { if (_oid.Value != Oids.EcPublicKey) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs index e38450eccdc8c..f88157eec37d4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.Cryptography.Pal; namespace System.Security.Cryptography.X509Certificates { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSAPkcs1X509SignatureGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSAPkcs1X509SignatureGenerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSAPkcs1X509SignatureGenerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSAPkcs1X509SignatureGenerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SafeLocalAllocHandle.cs similarity index 93% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SafeLocalAllocHandle.cs index c9cf3d62fe055..1fe163b1d5617 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SafeLocalAllocHandle.cs @@ -6,7 +6,7 @@ #pragma warning disable CA1419 // TODO https://github.com/dotnet/roslyn-analyzers/issues/5232: not intended for use with P/Invoke -namespace Internal.Cryptography.Pal.Native +namespace System.Security.Cryptography.X509Certificates { /// /// SafeHandle for LocalAlloc'd memory. diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/StoreLocation.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StoreLocation.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/StoreLocation.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StoreLocation.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/StoreName.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StoreName.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/StoreName.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StoreName.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.AndroidKeyStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.AndroidKeyStore.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.AndroidKeyStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.AndroidKeyStore.cs index 898d79c292da3..4a1abe1bd9a2b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.AndroidKeyStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.AndroidKeyStore.cs @@ -1,15 +1,12 @@ // 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.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.ExportPal.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.ExportPal.cs index b98ed82966316..fd08bb0f525d3 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.ExportPal.cs @@ -1,12 +1,9 @@ // 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.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.LoaderPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.LoaderPal.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.LoaderPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.LoaderPal.cs index cadb90643ce08..0bf66a2c3e6d4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.LoaderPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.LoaderPal.cs @@ -1,14 +1,12 @@ // 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.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Threading; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.TrustedStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.TrustedStore.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.TrustedStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.TrustedStore.cs index 6998610bd1c39..d6089421860a9 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.TrustedStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.TrustedStore.cs @@ -1,15 +1,12 @@ // 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.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs similarity index 86% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs index 6187979d905f8..7c31e1f373435 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs @@ -1,24 +1,21 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { - public static IStorePal FromHandle(IntPtr storeHandle) + internal static partial IStorePal FromHandle(IntPtr storeHandle) { throw new NotImplementedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -37,23 +34,23 @@ public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle } } - public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { byte[] fileBytes = File.ReadAllBytes(fileName); return FromBlob(fileBytes, password, keyStorageFlags); } - public static IExportPal FromCertificate(ICertificatePalCore cert) + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) { return new AndroidExportProvider(cert); } - public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) + internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { return new AndroidExportProvider(certificates); } - public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) + internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) { bool isReadWrite = (openFlags & OpenFlags.ReadWrite) == OpenFlags.ReadWrite; if (isReadWrite && storeLocation == StoreLocation.LocalMachine) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.NotSupported.cs new file mode 100644 index 0000000000000..2b7706b4a7a63 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.NotSupported.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class StorePal + { + internal static partial IStorePal FromHandle(IntPtr storeHandle) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial ILoaderPal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial ILoaderPal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial IExportPal LinkFromCertificateCollection( + X509Certificate2Collection certificates) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + + internal static partial IStorePal FromSystemStore( + string storeName, + StoreLocation storeLocation, + OpenFlags openFlags) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs similarity index 75% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs index bef72007c383a..e1c4a49284961 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs @@ -1,24 +1,21 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { - public static IStorePal FromHandle(IntPtr storeHandle) + internal static partial IStorePal FromHandle(IntPtr storeHandle) { throw new PlatformNotSupportedException(); } - public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -38,9 +35,9 @@ public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle List? certPals; Exception? openSslException; - if (PkcsFormatReader.TryReadPkcs7Der(rawData, out certPals) || - PkcsFormatReader.TryReadPkcs7Pem(rawData, out certPals) || - PkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out certPals, out openSslException)) + if (OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out certPals) || + OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out certPals) || + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out certPals, out openSslException)) { Debug.Assert(certPals != null); @@ -51,7 +48,7 @@ public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle throw openSslException; } - public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { bool ephemeralSpecified = keyStorageFlags.HasFlag(X509KeyStorageFlags.EphemeralKeySet); @@ -92,7 +89,7 @@ private static ILoaderPal FromBio( List? certPals; - if (PkcsFormatReader.TryReadPkcs7Pem(bio, out certPals)) + if (OpenSslPkcsFormatReader.TryReadPkcs7Pem(bio, out certPals)) { return ListToLoaderPal(certPals); } @@ -100,7 +97,7 @@ private static ILoaderPal FromBio( // Rewind, try again. OpenSslX509CertificateReader.RewindBio(bio, bioPosition); - if (PkcsFormatReader.TryReadPkcs7Der(bio, out certPals)) + if (OpenSslPkcsFormatReader.TryReadPkcs7Der(bio, out certPals)) { return ListToLoaderPal(certPals); } @@ -111,7 +108,7 @@ private static ILoaderPal FromBio( // Capture the exception so in case of failure, the call to BioSeek does not override it. Exception? openSslException; byte[] data = File.ReadAllBytes(fileName); - if (PkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, out certPals, out openSslException)) + if (OpenSslPkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, out certPals, out openSslException)) { return ListToLoaderPal(certPals); } @@ -130,26 +127,26 @@ private static ILoaderPal FromBio( throw openSslException; } - public static IExportPal FromCertificate(ICertificatePalCore cert) + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) { - return new ExportProvider(cert); + return new OpenSslExportProvider(cert); } - public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) + internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { - return new ExportProvider(certificates); + return new OpenSslExportProvider(certificates); } - public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) + internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) { if (storeLocation == StoreLocation.CurrentUser) { if (X509Store.DisallowedStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase)) { - return DirectoryBasedStoreProvider.OpenDisallowedStore(openFlags); + return OpenSslDirectoryBasedStoreProvider.OpenDisallowedStore(openFlags); } - return new DirectoryBasedStoreProvider(storeName, openFlags); + return new OpenSslDirectoryBasedStoreProvider(storeName, openFlags); } Debug.Assert(storeLocation == StoreLocation.LocalMachine); @@ -167,12 +164,12 @@ public static IStorePal FromSystemStore(string storeName, StoreLocation storeLoc if (X509Store.RootStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase)) { - return CachedSystemStoreProvider.MachineRoot; + return OpenSslCachedSystemStoreProvider.MachineRoot; } if (X509Store.IntermediateCAStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase)) { - return CachedSystemStoreProvider.MachineIntermediate; + return OpenSslCachedSystemStoreProvider.MachineIntermediate; } throw new CryptographicException( @@ -182,7 +179,7 @@ public static IStorePal FromSystemStore(string storeName, StoreLocation storeLoc private static ILoaderPal SingleCertToLoaderPal(ICertificatePal singleCert) { - return new SingleCertLoader(singleCert); + return new OpenSslSingleCertLoader(singleCert); } private static ILoaderPal ListToLoaderPal(List certPals) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Export.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Export.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Export.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Export.cs index 2a44fb6aba75e..b6bc38933fb85 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Export.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Export.cs @@ -1,14 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal : IDisposable, IStorePal, IExportPal, ILoaderPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Import.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs index ed4c5386e74bf..264e1bf11fb6d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs @@ -1,24 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal.Native; -using Microsoft.Win32.SafeHandles; -using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using System.Diagnostics; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal : IDisposable, IStorePal, IExportPal, ILoaderPal { - public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { return FromBlobOrFile(rawData, null, password, keyStorageFlags); } - public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { return FromBlobOrFile(null, fileName, password, keyStorageFlags); } @@ -99,7 +97,7 @@ private static StorePal FromBlobOrFile(ReadOnlySpan rawData, string? fileN } } - public static IExportPal FromCertificate(ICertificatePalCore cert) + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) { CertificatePal certificatePal = (CertificatePal)cert; @@ -120,7 +118,7 @@ public static IExportPal FromCertificate(ICertificatePalCore cert) /// Note: this factory method creates the store using links to the original certificates rather than copies. This means that any changes to certificate properties /// in the store changes the original. /// - public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) + internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. @@ -149,7 +147,7 @@ public static IExportPal LinkFromCertificateCollection(X509Certificate2Collectio return new StorePal(certStore); } - public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) + internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) { Interop.Crypt32.CertStoreFlags certStoreFlags = MapX509StoreFlags(storeLocation, openFlags); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.cs index 47bbfe4c7988d..f2e6494481f62 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.cs @@ -1,20 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using System.Security.Cryptography; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal : IDisposable, IStorePal, IExportPal, ILoaderPal { private SafeCertStoreHandle _certStore; - public static IStorePal FromHandle(IntPtr storeHandle) + internal static partial IStorePal FromHandle(IntPtr storeHandle) { if (storeHandle == IntPtr.Zero) throw new ArgumentNullException(nameof(storeHandle)); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.cs new file mode 100644 index 0000000000000..54a29a92fd65a --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography.X509Certificates +{ + internal partial class StorePal + { + internal static partial IStorePal FromHandle(IntPtr storeHandle); + + internal static partial ILoaderPal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags); + + internal static partial ILoaderPal FromFile( + string fileName, + SafePasswordHandle password, + X509KeyStorageFlags keyStorageFlags); + + internal static partial IExportPal FromCertificate(ICertificatePalCore cert); + + internal static partial IExportPal LinkFromCertificateCollection( + X509Certificate2Collection certificates); + + internal static partial IStorePal FromSystemStore( + string storeName, + StoreLocation storeLocation, + OpenFlags openFlags); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.AppleKeychainStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.AppleKeychainStore.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.AppleKeychainStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.AppleKeychainStore.cs index 88be19a1e03d5..b320c022ae248 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.AppleKeychainStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.AppleKeychainStore.cs @@ -1,16 +1,11 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs similarity index 86% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs index 47d7485c0f984..3e8c5acfd25ae 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/StorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs @@ -1,25 +1,21 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { - public static IStorePal FromHandle(IntPtr storeHandle) + internal static partial IStorePal FromHandle(IntPtr storeHandle) { throw new PlatformNotSupportedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { List? certificateList = null; @@ -85,7 +81,7 @@ public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle if (handle != IntPtr.Zero) { - ICertificatePal? certPal = CertificatePal.FromHandle(handle, throwOnFail: false); + ICertificatePal? certPal = AppleCertificatePal.FromHandle(handle, throwOnFail: false); if (certPal != null) { @@ -98,7 +94,7 @@ public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle return new CertCollectionLoader(certificateList); } - public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -106,17 +102,17 @@ public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, return FromBlob(fileBytes, password, keyStorageFlags); } - public static IExportPal FromCertificate(ICertificatePalCore cert) + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) { return new AppleCertificateExporter(cert); } - public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) + internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { return new AppleCertificateExporter(certificates); } - public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) + internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) { StringComparer ordinalIgnoreCase = StringComparer.OrdinalIgnoreCase; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleKeychainStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleKeychainStore.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleKeychainStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleKeychainStore.cs index c04a55f25a97f..7606d326495ba 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleKeychainStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleKeychainStore.cs @@ -1,16 +1,13 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleTrustStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleTrustStore.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleTrustStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleTrustStore.cs index e5cb0f882d386..6cbfb9cd0f62b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.AppleTrustStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.AppleTrustStore.cs @@ -1,15 +1,12 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.ExportPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.ExportPal.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.ExportPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.ExportPal.cs index c29221ad79ec3..eac97c8cead25 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.ExportPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.ExportPal.cs @@ -1,13 +1,7 @@ // 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.Diagnostics; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32.SafeHandles; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.LoaderPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.LoaderPal.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.LoaderPal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.LoaderPal.cs index a05387db060fa..c6f33bbf1ce3e 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.LoaderPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.LoaderPal.cs @@ -1,14 +1,11 @@ // 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.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using System.Threading; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { @@ -45,7 +42,7 @@ public void MoveTo(X509Certificate2Collection collection) if (handle != IntPtr.Zero) { - ICertificatePal? certPal = CertificatePal.FromHandle(handle, throwOnFail: false); + ICertificatePal? certPal = AppleCertificatePal.FromHandle(handle, throwOnFail: false); if (certPal != null) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs index e7cbefeb5b4d5..cfd418b27a545 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/StorePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs @@ -1,20 +1,17 @@ // 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.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal { - public static IStorePal FromHandle(IntPtr storeHandle) + internal static partial IStorePal FromHandle(IntPtr storeHandle) { if (storeHandle == IntPtr.Zero) throw new ArgumentNullException(nameof(storeHandle)); @@ -25,7 +22,7 @@ public static IStorePal FromHandle(IntPtr storeHandle) return new AppleKeychainStore(keychainHandle, OpenFlags.MaxAllowed); } - public static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -82,7 +79,7 @@ private static ILoaderPal ImportPkcs12( } } - public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -90,17 +87,17 @@ public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, return FromBlob(fileBytes, password, keyStorageFlags); } - public static IExportPal FromCertificate(ICertificatePalCore cert) + internal static partial IExportPal FromCertificate(ICertificatePalCore cert) { return new AppleCertificateExporter(cert); } - public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) + internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { return new AppleCertificateExporter(certificates); } - public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) + internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) { StringComparer ordinalIgnoreCase = StringComparer.OrdinalIgnoreCase; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainVerifier.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixChainVerifier.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainVerifier.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixChainVerifier.cs index d9b6839f4b6fb..73e195d7d1b84 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainVerifier.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixChainVerifier.cs @@ -1,15 +1,13 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal static class ChainVerifier + internal static class UnixChainVerifier { public static bool Verify(X509ChainElement[] chainElements, X509VerificationFlags flags) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixExportProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixExportProvider.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixExportProvider.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixExportProvider.cs index a6e50de9d4407..f569435e605c6 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixExportProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixExportProvider.cs @@ -1,19 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Win32.SafeHandles; -using System; using System.Buffers; using System.Diagnostics; using System.Formats.Asn1; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.Asn1.Pkcs12; using System.Security.Cryptography.Pkcs; -using System.Security.Cryptography.X509Certificates; +using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal abstract class UnixExportProvider : IExportPal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixPkcs12Reader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixPkcs12Reader.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixPkcs12Reader.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixPkcs12Reader.cs index 8cd7abe0660a8..f7454d5b7aae1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnixPkcs12Reader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnixPkcs12Reader.cs @@ -1,20 +1,19 @@ // 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.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Formats.Asn1; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.Asn1.Pkcs12; using System.Security.Cryptography.Asn1.Pkcs7; using System.Threading; +using Internal.Cryptography; using Microsoft.Win32.SafeHandles; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal abstract class UnixPkcs12Reader : IDisposable { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnsupportedDisallowedStore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnsupportedDisallowedStore.cs similarity index 92% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnsupportedDisallowedStore.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnsupportedDisallowedStore.cs index fbdcd08bceb75..e4b068f9ace42 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/UnsupportedDisallowedStore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/UnsupportedDisallowedStore.cs @@ -1,16 +1,13 @@ // 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.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Text; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed class UnsupportedDisallowedStore : IStorePal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Helpers.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsHelpers.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Helpers.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsHelpers.cs index 07dc27d9a39b3..fe3fa41389c1c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Helpers.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsHelpers.cs @@ -5,11 +5,12 @@ using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using System.Text; -namespace Internal.Cryptography.Pal.Native +namespace Internal.Cryptography { - internal static class Helpers + internal static partial class Helpers { /// /// Convert each Oid's value to an ASCII string, then create an unmanaged array of "numOids" LPSTR pointers, one for each Oid. diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsInterop.crypt32.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsInterop.crypt32.cs index 8df13c01e359c..fea9b7698e97d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsInterop.crypt32.cs @@ -11,9 +11,9 @@ using SafeNCryptKeyHandle = Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle; using Internal.Cryptography; -using Internal.Cryptography.Pal.Native; using Microsoft.Win32.SafeHandles; using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography.X509Certificates; internal static partial class Interop { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Primitives.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsStructs.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Primitives.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsStructs.cs index bec34b98cd60c..5746b4bdc3a16 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Primitives.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/WindowsStructs.cs @@ -1,10 +1,9 @@ // 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.Runtime.InteropServices; -namespace Internal.Cryptography.Pal.Native +namespace System.Security.Cryptography.X509Certificates { internal enum CertStoreProvider : int { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DictionaryStringHelper.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DictionaryStringHelper.cs new file mode 100644 index 0000000000000..4edef81da00f2 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DictionaryStringHelper.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Formats.Asn1; + +namespace System.Security.Cryptography.X509Certificates +{ + internal static class X500DictionaryStringHelper + { + internal static string ReadAnyAsnString(this AsnReader tavReader) + { + Asn1Tag tag = tavReader.PeekTag(); + + if (tag.TagClass != TagClass.Universal) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + switch ((UniversalTagNumber)tag.TagValue) + { + case UniversalTagNumber.BMPString: + case UniversalTagNumber.IA5String: + case UniversalTagNumber.NumericString: + case UniversalTagNumber.PrintableString: + case UniversalTagNumber.UTF8String: + case UniversalTagNumber.T61String: + // .NET's string comparisons start by checking the length, so a trailing + // NULL character which was literally embedded in the DER would cause a + // failure in .NET whereas it wouldn't have with strcmp. + return tavReader.ReadCharacterString((UniversalTagNumber)tag.TagValue).TrimEnd('\0'); + + default: + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs index cba36485d7a6d..0e8dc7efc9cab 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal; - namespace System.Security.Cryptography.X509Certificates { public sealed class X500DistinguishedName : AsnEncodedData diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedNameFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DistinguishedNameFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedNameFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500DistinguishedNameFlags.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.ManagedDecode.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.ManagedDecode.cs index 7a4086135052f..d91d1054ced1b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.ManagedDecode.cs @@ -1,13 +1,11 @@ // 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.Formats.Asn1; -using System.Security.Cryptography; using System.Text; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal static partial class X500NameEncoder { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs index d68964a48f541..ff7393c794b6d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs @@ -1,15 +1,12 @@ // 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.Formats.Asn1; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using System.Text; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal static partial class X500NameEncoder { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X501Attribute.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X501Attribute.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X501Attribute.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X501Attribute.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs similarity index 91% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs index 013c6cac85639..fd7d5373af68d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs @@ -1,16 +1,6 @@ // 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.IO; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; - -using Internal.Cryptography; -using Internal.Cryptography.Pal; - namespace System.Security.Cryptography.X509Certificates { public sealed class X509BasicConstraintsExtension : X509Extension @@ -73,7 +63,7 @@ public override void CopyFrom(AsnEncodedData asnEncodedData) private static byte[] EncodeExtension(bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint) { if (hasPathLengthConstraint && pathLengthConstraint < 0) - throw new ArgumentOutOfRangeException(nameof(pathLengthConstraint), SR.Arg_OutOfRange_NeedNonNegNum); + throw new ArgumentOutOfRangeException(nameof(pathLengthConstraint), SR.ArgumentOutOfRange_NeedNonNegNum); return X509Pal.Instance.EncodeX509BasicConstraints2Extension(certificateAuthority, hasPathLengthConstraint, pathLengthConstraint); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs index 1913afa2af230..a17dbf0f21dd8 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.Cryptography.Pal; using Microsoft.Win32.SafeHandles; -using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.Serialization; +using System.Runtime.Versioning; using System.Text; namespace System.Security.Cryptography.X509Certificates @@ -46,11 +45,13 @@ public virtual void Reset() } [Obsolete(Obsoletions.X509CertificateImmutableMessage, DiagnosticId = Obsoletions.X509CertificateImmutableDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [UnsupportedOSPlatform("browser")] public X509Certificate() { } // Null turns into the empty span here, which is correct for compat. + [UnsupportedOSPlatform("browser")] public X509Certificate(byte[] data) : this(new ReadOnlySpan(data)) { @@ -68,17 +69,20 @@ private protected X509Certificate(ReadOnlySpan data) } } + [UnsupportedOSPlatform("browser")] public X509Certificate(byte[] rawData, string? password) : this(rawData, password, X509KeyStorageFlags.DefaultKeySet) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate(byte[] rawData, SecureString? password) : this(rawData, password, X509KeyStorageFlags.DefaultKeySet) { } + [UnsupportedOSPlatform("browser")] public X509Certificate(byte[] rawData, string? password, X509KeyStorageFlags keyStorageFlags) { if (rawData == null || rawData.Length == 0) @@ -92,7 +96,8 @@ public X509Certificate(byte[] rawData, string? password, X509KeyStorageFlags key } } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate(byte[] rawData, SecureString? password, X509KeyStorageFlags keyStorageFlags) { if (rawData == null || rawData.Length == 0) @@ -119,6 +124,7 @@ private protected X509Certificate(ReadOnlySpan rawData, ReadOnlySpan } } + [UnsupportedOSPlatform("browser")] public X509Certificate(IntPtr handle) { Pal = CertificatePal.FromHandle(handle); @@ -130,22 +136,26 @@ internal X509Certificate(ICertificatePalCore pal) Pal = pal; } + [UnsupportedOSPlatform("browser")] public X509Certificate(string fileName) : this(fileName, (string?)null, X509KeyStorageFlags.DefaultKeySet) { } + [UnsupportedOSPlatform("browser")] public X509Certificate(string fileName, string? password) : this(fileName, password, X509KeyStorageFlags.DefaultKeySet) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate(string fileName, SecureString? password) : this(fileName, password, X509KeyStorageFlags.DefaultKeySet) { } + [UnsupportedOSPlatform("browser")] public X509Certificate(string fileName, string? password, X509KeyStorageFlags keyStorageFlags) { if (fileName == null) @@ -172,7 +182,8 @@ private protected X509Certificate(string fileName, ReadOnlySpan password, } } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] #pragma warning disable SYSLIB0026 public X509Certificate(string fileName, SecureString? password, X509KeyStorageFlags keyStorageFlags) : this() #pragma warning restore SYSLIB0026 @@ -188,6 +199,7 @@ public X509Certificate(string fileName, SecureString? password, X509KeyStorageFl } } + [UnsupportedOSPlatform("browser")] public X509Certificate(X509Certificate cert) { if (cert == null) @@ -206,11 +218,13 @@ public X509Certificate(SerializationInfo info, StreamingContext context) : this( throw new PlatformNotSupportedException(); } + [UnsupportedOSPlatform("browser")] public static X509Certificate CreateFromCertFile(string filename) { return new X509Certificate(filename); } + [UnsupportedOSPlatform("browser")] public static X509Certificate CreateFromSignedFile(string filename) { return new X509Certificate(filename); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs index f073ed7afb451..0de268a2d60c1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs @@ -1,17 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; -using Internal.Cryptography.Pal; -using System; using System.Diagnostics; using System.Formats.Asn1; using System.IO; using System.Runtime.Serialization; using System.Runtime.Versioning; -using System.Security; using System.Security.Cryptography.X509Certificates.Asn1; using System.Text; +using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { @@ -44,33 +41,39 @@ public override void Reset() } [Obsolete(Obsoletions.X509CertificateImmutableMessage, DiagnosticId = Obsoletions.X509CertificateImmutableDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [UnsupportedOSPlatform("browser")] public X509Certificate2() : base() { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(byte[] rawData) : base(rawData) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(byte[] rawData, string? password) : base(rawData, password) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate2(byte[] rawData, SecureString? password) : base(rawData, password) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(byte[] rawData, string? password, X509KeyStorageFlags keyStorageFlags) : base(rawData, password, keyStorageFlags) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate2(byte[] rawData, SecureString? password, X509KeyStorageFlags keyStorageFlags) : base(rawData, password, keyStorageFlags) { @@ -83,6 +86,7 @@ public X509Certificate2(byte[] rawData, SecureString? password, X509KeyStorageFl /// The certificate data to process. /// /// An error with the certificate occurs. + [UnsupportedOSPlatform("browser")] public X509Certificate2(ReadOnlySpan rawData) : base(rawData) { @@ -102,11 +106,13 @@ public X509Certificate2(ReadOnlySpan rawData) /// A bitwise combination of the enumeration values that control where and how to import the certificate. /// /// An error with the certificate occurs. + [UnsupportedOSPlatform("browser")] public X509Certificate2(ReadOnlySpan rawData, ReadOnlySpan password, X509KeyStorageFlags keyStorageFlags = 0) : base(rawData, password, keyStorageFlags) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(IntPtr handle) : base(handle) { @@ -117,39 +123,45 @@ internal X509Certificate2(ICertificatePal pal) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(string fileName) : base(fileName) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(string fileName, string? password) : base(fileName, password) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate2(string fileName, SecureString? password) : base(fileName, password) { } - + [UnsupportedOSPlatform("browser")] public X509Certificate2(string fileName, string? password, X509KeyStorageFlags keyStorageFlags) : base(fileName, password, keyStorageFlags) { } - [System.CLSCompliantAttribute(false)] + [UnsupportedOSPlatform("browser")] + [CLSCompliantAttribute(false)] public X509Certificate2(string fileName, SecureString? password, X509KeyStorageFlags keyStorageFlags) : base(fileName, password, keyStorageFlags) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(string fileName, ReadOnlySpan password, X509KeyStorageFlags keyStorageFlags = 0) : base(fileName, password, keyStorageFlags) { } + [UnsupportedOSPlatform("browser")] public X509Certificate2(X509Certificate certificate) : base(certificate) { @@ -389,6 +401,7 @@ public int Version } } + [UnsupportedOSPlatform("browser")] public static X509ContentType GetCertContentType(byte[] rawData) { if (rawData == null || rawData.Length == 0) @@ -406,6 +419,7 @@ public static X509ContentType GetCertContentType(byte[] rawData) /// /// One of the enumeration values that indicate the content type of the provided data. /// + [UnsupportedOSPlatform("browser")] public static X509ContentType GetCertContentType(ReadOnlySpan rawData) { if (rawData.Length == 0) @@ -414,6 +428,7 @@ public static X509ContentType GetCertContentType(ReadOnlySpan rawData) return X509Pal.Instance.GetCertContentType(rawData); } + [UnsupportedOSPlatform("browser")] public static X509ContentType GetCertContentType(string fileName) { if (fileName == null) @@ -833,6 +848,7 @@ public X509Certificate2 CopyWithPrivateKey(ECDiffieHellman privateKey) /// For password protected PEM-encoded keys, use to specify a password. /// /// + [UnsupportedOSPlatform("browser")] public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string? keyPemFilePath = default) { if (certPemFilePath is null) @@ -899,6 +915,7 @@ public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string? /// For PEM-encoded keys without a password, use . /// /// + [UnsupportedOSPlatform("browser")] public static X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath, ReadOnlySpan password, string? keyPemFilePath = default) { if (certPemFilePath is null) @@ -949,6 +966,7 @@ public static X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath /// For password protected PEM-encoded keys, use to specify a password. /// /// + [UnsupportedOSPlatform("browser")] public static X509Certificate2 CreateFromPem(ReadOnlySpan certPem, ReadOnlySpan keyPem) { using (X509Certificate2 certificate = CreateFromPem(certPem)) @@ -1019,6 +1037,7 @@ Oids.EcPublicKey when IsECDiffieHellman(certificate) => /// For PEM-encoded keys without a password, use . /// /// + [UnsupportedOSPlatform("browser")] public static X509Certificate2 CreateFromEncryptedPem(ReadOnlySpan certPem, ReadOnlySpan keyPem, ReadOnlySpan password) { using (X509Certificate2 certificate = CreateFromPem(certPem)) @@ -1083,6 +1102,7 @@ private static bool IsECDiffieHellman(X509Certificate2 certificate) /// For PEM-encoded certificates in a file, use . /// /// + [UnsupportedOSPlatform("browser")] public static X509Certificate2 CreateFromPem(ReadOnlySpan certPem) { foreach ((ReadOnlySpan contents, PemFields fields) in new PemEnumerator(certPem)) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs index 5520ea204eea9..314715e376460 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs @@ -1,14 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography; -using Internal.Cryptography.Pal; -using Microsoft.Win32.SafeHandles; using System.Diagnostics; using System.Formats.Asn1; using System.Runtime.Versioning; using System.Security.Cryptography.X509Certificates.Asn1; using System.Collections.Generic; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography.X509Certificates { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Chain.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Chain.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Chain.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Chain.cs index dbefadab57334..03cd945bd03cf 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Chain.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Chain.cs @@ -1,11 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using SafeX509ChainHandle = Microsoft.Win32.SafeHandles.SafeX509ChainHandle; -using Internal.Cryptography.Pal; using System.Diagnostics; using System.Runtime.Versioning; +using SafeX509ChainHandle = Microsoft.Win32.SafeHandles.SafeX509ChainHandle; + namespace System.Security.Cryptography.X509Certificates { public class X509Chain : IDisposable @@ -102,6 +102,7 @@ public SafeX509ChainHandle? SafeHandle } } + [UnsupportedOSPlatform("browser")] public bool Build(X509Certificate2 certificate) { return Build(certificate, true); @@ -117,13 +118,13 @@ internal bool Build(X509Certificate2 certificate, bool throwOnException) if (_chainPolicy != null && _chainPolicy.CustomTrustStore != null) { if (_chainPolicy.TrustMode == X509ChainTrustMode.System && _chainPolicy.CustomTrustStore.Count > 0) - throw new CryptographicException(SR.Cryptography_CustomTrustCertsInSystemMode, nameof(_chainPolicy.TrustMode)); + throw new CryptographicException(SR.Cryptography_CustomTrustCertsInSystemMode); foreach (X509Certificate2 customCertificate in _chainPolicy.CustomTrustStore) { if (customCertificate == null || customCertificate.Handle == IntPtr.Zero) { - throw new CryptographicException(SR.Cryptography_InvalidTrustCertificate, nameof(_chainPolicy.CustomTrustStore)); + throw new CryptographicException(SR.Cryptography_InvalidTrustCertificate); } } } @@ -139,7 +140,7 @@ internal bool Build(X509Certificate2 certificate, bool throwOnException) chainPolicy._certificatePolicy!, chainPolicy.RevocationMode, chainPolicy.RevocationFlag, - chainPolicy.CustomTrustStore, + chainPolicy._customTrustStore, chainPolicy.TrustMode, chainPolicy.VerificationTime, chainPolicy.UrlRetrievalTimeout, diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElementCollection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElementCollection.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElementCollection.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElementCollection.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElementEnumerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElementEnumerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainElementEnumerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElementEnumerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainPolicy.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainPolicy.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainPolicy.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainPolicy.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainStatus.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainStatus.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainStatus.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainStatus.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainStatusFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainStatusFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainStatusFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainStatusFlags.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainTrustMode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainTrustMode.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ChainTrustMode.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainTrustMode.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ContentType.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ContentType.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ContentType.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ContentType.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs index 70a802a013538..5f7de6941e23e 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509EnhancedKeyUsageExtension.cs @@ -1,16 +1,6 @@ // 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.IO; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; - -using Internal.Cryptography; -using Internal.Cryptography.Pal; - namespace System.Security.Cryptography.X509Certificates { public sealed class X509EnhancedKeyUsageExtension : X509Extension diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Extension.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Extension.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ExtensionCollection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ExtensionCollection.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ExtensionCollection.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ExtensionCollection.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ExtensionEnumerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ExtensionEnumerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509ExtensionEnumerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ExtensionEnumerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509FindType.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509FindType.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509FindType.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509FindType.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509IncludeOption.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509IncludeOption.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509IncludeOption.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509IncludeOption.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyStorageFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyStorageFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyStorageFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyStorageFlags.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs similarity index 86% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs index 6f844d21b86b8..631b55139a561 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyUsageExtension.cs @@ -1,16 +1,6 @@ // 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.IO; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; - -using Internal.Cryptography; -using Internal.Cryptography.Pal; - namespace System.Security.Cryptography.X509Certificates { public sealed class X509KeyUsageExtension : X509Extension diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyUsageFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyUsageFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509KeyUsageFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509KeyUsageFlags.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509NameType.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509NameType.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509NameType.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509NameType.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/X509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs similarity index 96% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/X509Pal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs index 370127735235b..e1cc094ff5c83 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/X509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs @@ -7,16 +7,14 @@ using System.IO; using System.Security.Cryptography; using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class X509Pal + internal static partial class X509Pal { - public static IX509Pal Instance = new AndroidX509Pal(); - - private X509Pal() + private static partial IX509Pal BuildSingleton() { + return new AndroidX509Pal(); } private sealed partial class AndroidX509Pal : ManagedX509ExtensionProcessor, IX509Pal diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.ECKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.ECKey.cs similarity index 88% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.ECKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.ECKey.cs index d4295ada4b50d..df21ef3ceaa58 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.ECKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.ECKey.cs @@ -1,19 +1,11 @@ // 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.Buffers; -using System.Diagnostics; -using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.Asn1; -using System.Security.Cryptography.Asn1.Pkcs12; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class X509Pal + internal partial class X509Pal { private sealed partial class AppleX509Pal : ManagedX509ExtensionProcessor, IX509Pal { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.X500Name.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.X500Name.cs similarity index 86% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.X500Name.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.X500Name.cs index 0bcaae2ab5fc5..b5fe1db657533 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.X500Name.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Apple.X500Name.cs @@ -1,13 +1,9 @@ // 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.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class X509Pal + internal partial class X509Pal { private sealed partial class AppleX509Pal : ManagedX509ExtensionProcessor, IX509Pal { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.NotSupported.cs new file mode 100644 index 0000000000000..fbaf9e13b57bf --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.NotSupported.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal static partial class X509Pal + { + private static partial IX509Pal BuildSingleton() + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.OpenSsl.cs similarity index 57% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Pal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.OpenSsl.cs index 74275401d68b8..28cbc90916ddf 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.OpenSsl.cs @@ -1,14 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal sealed partial class X509Pal { - public static IX509Pal Instance = new OpenSslX509Encoder(); - - private X509Pal() + private static partial IX509Pal BuildSingleton() { + return new OpenSslX509Encoder(); } } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.CustomExtensions.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.CustomExtensions.cs similarity index 97% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.CustomExtensions.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.CustomExtensions.cs index 677fb54ac35b1..c990d99400968 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.CustomExtensions.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.CustomExtensions.cs @@ -1,20 +1,11 @@ // 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.Text; using System.Diagnostics; -using System.Globalization; -using System.Collections.Generic; using System.Runtime.InteropServices; - using Internal.Cryptography; -using Internal.Cryptography.Pal.Native; - -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { /// /// A singleton class that encapsulates the native implementation of various X509 services. (Implementing this as a singleton makes it diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.GetCertContentType.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.GetCertContentType.cs similarity index 94% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.GetCertContentType.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.GetCertContentType.cs index ff26212b623a8..c60079458b713 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.GetCertContentType.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.GetCertContentType.cs @@ -1,19 +1,10 @@ // 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.Text; -using System.Diagnostics; -using System.Globalization; using System.Runtime.InteropServices; - using Internal.Cryptography; -using Internal.Cryptography.Pal.Native; - -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { /// /// A singleton class that encapsulates the native implementation of various X509 services. (Implementing this as a singleton makes it diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.PublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.PublicKey.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs index 13dcd63f4f91f..20ac22206124b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.PublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs @@ -1,20 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal.Native; -using Microsoft.Win32.SafeHandles; -using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; -using System.Security.Cryptography; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; using NTSTATUS = Interop.BCrypt.NTSTATUS; using SafeBCryptKeyHandle = Microsoft.Win32.SafeHandles.SafeBCryptKeyHandle; using static Interop.Crypt32; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { /// /// A singleton class that encapsulates the native implementation of various X509 services. (Implementing this as a singleton makes it diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.X500DistinguishedName.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.X500DistinguishedName.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.X500DistinguishedName.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.X500DistinguishedName.cs index 09341dca638bb..7339a32cf6930 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/X509Pal.X500DistinguishedName.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.X500DistinguishedName.cs @@ -1,13 +1,11 @@ // 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.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using Internal.Cryptography.Pal.Native; +using Internal.Cryptography; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { /// /// A singleton class that encapsulates the native implementation of various X509 services. (Implementing this as a singleton makes it diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.cs new file mode 100644 index 0000000000000..a2c9fb1636df2 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal partial class X509Pal : IX509Pal + { + private static partial IX509Pal BuildSingleton() + { + return new X509Pal(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.cs new file mode 100644 index 0000000000000..8060dc75972bc --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates +{ + internal partial class X509Pal + { + internal static IX509Pal Instance { get; } = BuildSingleton(); + + private static partial IX509Pal BuildSingleton(); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/X509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs similarity index 90% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/X509Pal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs index 283bd38c066dc..f9ff5f38b87af 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.iOS/X509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs @@ -1,22 +1,16 @@ // 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.Buffers; using System.Diagnostics; -using System.Text; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class X509Pal + internal static partial class X509Pal { - public static IX509Pal Instance = new AppleX509Pal(); - - private X509Pal() + private static partial IX509Pal BuildSingleton() { + return new AppleX509Pal(); } private sealed partial class AppleX509Pal : ManagedX509ExtensionProcessor, IX509Pal diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs similarity index 95% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs index 2b654b2b3b9c2..5d60633639064 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs @@ -1,24 +1,20 @@ // 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.Buffers; using System.Diagnostics; using System.Formats.Asn1; -using System.Security.Cryptography; using System.Security.Cryptography.Apple; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.Asn1.Pkcs12; -using System.Security.Cryptography.X509Certificates; -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { - internal sealed partial class X509Pal + internal static partial class X509Pal { - public static IX509Pal Instance = new AppleX509Pal(); - - private X509Pal() + private static partial IX509Pal BuildSingleton() { + return new AppleX509Pal(); } private sealed partial class AppleX509Pal : ManagedX509ExtensionProcessor, IX509Pal diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Persistence.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Persistence.cs similarity index 89% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Persistence.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Persistence.cs index 5eb56054ab11a..c8818105cc2f2 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X509Persistence.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Persistence.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Internal.Cryptography.Pal +namespace System.Security.Cryptography.X509Certificates { internal static class X509Persistence { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509RevocationFlag.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509RevocationFlag.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509RevocationFlag.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509RevocationFlag.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509RevocationMode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509RevocationMode.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509RevocationMode.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509RevocationMode.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Store.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs similarity index 99% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Store.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs index d16b59b325a9a..d97ead09424f1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Store.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.Cryptography.Pal; using System.Diagnostics; -using System.Globalization; namespace System.Security.Cryptography.X509Certificates { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs similarity index 98% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs index aaeefd3eeee46..1d239cf58fee5 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierExtension.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.Cryptography; -using Internal.Cryptography.Pal; namespace System.Security.Cryptography.X509Certificates { @@ -79,7 +78,7 @@ private static byte[] EncodeExtension(string subjectKeyIdentifier) if (subjectKeyIdentifier == null) throw new ArgumentNullException(nameof(subjectKeyIdentifier)); - byte[] subjectKeyIdentifiedBytes = subjectKeyIdentifier.DecodeHexString(); + byte[] subjectKeyIdentifiedBytes = subjectKeyIdentifier.LaxDecodeHexString(); return EncodeExtension(subjectKeyIdentifiedBytes); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierHashAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierHashAlgorithm.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierHashAlgorithm.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SubjectKeyIdentifierHashAlgorithm.cs diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509VerificationFlags.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509VerificationFlags.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509VerificationFlags.cs rename to src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509VerificationFlags.cs diff --git a/src/libraries/System.Security.Cryptography/tests/AsnEncodedDataTests.cs b/src/libraries/System.Security.Cryptography/tests/AsnEncodedDataTests.cs index a72d6814fea80..0e5ba9cb08806 100644 --- a/src/libraries/System.Security.Cryptography/tests/AsnEncodedDataTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/AsnEncodedDataTests.cs @@ -101,11 +101,12 @@ public static void TestSubjectAlternativeName_Unix() sanExtension); string s = asnData.Format(false); + bool isOpenSsl3 = PlatformDetection.IsOpenSsl3; string expected = string.Join( ", ", // Choice[0]: OtherName - "othername:", + isOpenSsl3 ? "othername: UPN::subjectupn1@example.org" : "othername:", // Choice[1]: Rfc822Name (EmailAddress) "email:sanemail1@example.org", // Choice[2]: DnsName @@ -123,7 +124,7 @@ public static void TestSubjectAlternativeName_Unix() // Choice[7]: IPAddress (IPv6) "IP Address:2001:DB8:AC10:FE01:0:0:0:0", // Choice[7]: IPAddress (unknown type) - "IP Address:", + isOpenSsl3 ? "IP Address:" : "IP Address:", // Choice[7]: IPAddress (IPv4, longer string) "IP Address:255.255.255.255", // Choice[7]: IPAddress (IPv4, medium string) diff --git a/src/libraries/System.Security.Cryptography/tests/DSATests.cs b/src/libraries/System.Security.Cryptography/tests/DSATests.cs index 66a25990bc2f8..2e3bdc2e5e768 100644 --- a/src/libraries/System.Security.Cryptography/tests/DSATests.cs +++ b/src/libraries/System.Security.Cryptography/tests/DSATests.cs @@ -55,9 +55,9 @@ public void SignData_InvalidArguments_Throws() AssertExtensions.Throws("offset", () => wrapperDsa.SignData(new byte[1], 2, 0, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => wrapperDsa.SignData(new byte[1], 0, -1, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => wrapperDsa.SignData(new byte[1], 0, 2, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new byte[1], new HashAlgorithmName(""))); - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(""))); } } @@ -74,7 +74,7 @@ public void TrySignData_UsesTryHashDataAndTryCreateSignature() byte[] initialSig = wrapperDsa.SignData(input, HashAlgorithmName.SHA1); byte[] actualSig = new byte[initialSig.Length]; - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(null), out int _)); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(null), out int _)); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(""), out int _)); Assert.False(wrapperDsa.TrySignData(input, new Span(actualSig, 0, 1), HashAlgorithmName.SHA1, out bytesWritten)); @@ -102,7 +102,7 @@ public void VerifyData_Array_UsesHashDataAndVerifySignature() AssertExtensions.Throws("count", () => wrapperDsa.VerifyData(new byte[1], 0, -1, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => wrapperDsa.VerifyData(new byte[1], 0, 2, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("signature", () => wrapperDsa.VerifyData(new byte[1], 0, 1, null, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new byte[1], new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new byte[1], new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new byte[1], new byte[1], new HashAlgorithmName(""))); byte[] signature = wrapperDsa.SignData(input, HashAlgorithmName.SHA1); @@ -121,7 +121,7 @@ public void VerifyData_Stream_UsesHashDataAndVerifySignature() { AssertExtensions.Throws("data", () => wrapperDsa.VerifyData((Stream)null, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("signature", () => wrapperDsa.VerifyData(new MemoryStream(new byte[1]), null, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(""))); byte[] signature = wrapperDsa.SignData(new MemoryStream(input), HashAlgorithmName.SHA1); @@ -138,7 +138,7 @@ public void VerifyData_Span_UsesTryHashDataAndVerifySignature() using (var wrapperDsa = new OverrideAbstractDSA(DSA.Create(1024))) { - AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData((Span)new byte[1], new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData((Span)new byte[1], new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => wrapperDsa.VerifyData((Span)new byte[1], new byte[1], new HashAlgorithmName(""))); byte[] signature = wrapperDsa.SignData(input, HashAlgorithmName.SHA1); diff --git a/src/libraries/System.Security.Cryptography/tests/ECDsaTests.cs b/src/libraries/System.Security.Cryptography/tests/ECDsaTests.cs index 0abd2570bd954..7851ef4f7b4fe 100644 --- a/src/libraries/System.Security.Cryptography/tests/ECDsaTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/ECDsaTests.cs @@ -64,7 +64,7 @@ public void Array_SignData_VerifyData_UsesHashDataAndSignHashAndVerifyHash() AssertExtensions.Throws("offset", () => ecdsa.SignData(new byte[1], 2, 0, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[1], 0, -1, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[1], 0, 2, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(""))); AssertExtensions.Throws("data", () => ecdsa.VerifyData((byte[])null, null, HashAlgorithmName.SHA1)); @@ -74,7 +74,7 @@ public void Array_SignData_VerifyData_UsesHashDataAndSignHashAndVerifyHash() AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[1], 0, -1, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[1], 0, 2, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("signature", () => ecdsa.VerifyData(new byte[1], 0, 1, null, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[1], 0, 1, new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[1], 0, 1, new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[1], 0, 1, new byte[1], new HashAlgorithmName(""))); var input = new byte[1024]; @@ -95,12 +95,12 @@ public void Stream_SignData_VerifyData_UsesHashDataAndSignHashAndVerifyHash() using (var ecdsa = new OverrideAbstractECDsa(ECDsaFactory.Create())) { AssertExtensions.Throws("data", () => ecdsa.SignData((Stream)null, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(new byte[1]), new HashAlgorithmName(""))); AssertExtensions.Throws("data", () => ecdsa.VerifyData((Stream)null, null, HashAlgorithmName.SHA1)); AssertExtensions.Throws("signature", () => ecdsa.VerifyData(new MemoryStream(new byte[1]), null, HashAlgorithmName.SHA1)); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(new byte[1]), new byte[1], new HashAlgorithmName(""))); var input = new byte[1024]; @@ -120,10 +120,10 @@ public void Span_TrySignData_VerifyData_UsesTryHashDataAndTrySignHashAndTryVerif { using (var ecdsa = new OverrideAbstractECDsa(ECDsaFactory.Create())) { - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(null), out int bytesWritten)); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(null), out int bytesWritten)); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(new byte[1], new byte[1], new HashAlgorithmName(""), out int bytesWritten)); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData((ReadOnlySpan)new byte[1], new byte[1], new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData((ReadOnlySpan)new byte[1], new byte[1], new HashAlgorithmName(""))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData((ReadOnlySpan)new byte[1], new byte[1], new HashAlgorithmName(null))); var input = new byte[1024]; Random.Shared.NextBytes(input); diff --git a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs index 9f940b3753a63..8890808c6a0cc 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs @@ -3,6 +3,8 @@ using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -15,6 +17,10 @@ public abstract class HashAlgorithmTestDriver protected abstract byte[] HashData(byte[] source); protected abstract byte[] HashData(ReadOnlySpan source); protected abstract int HashData(ReadOnlySpan source, Span destination); + protected abstract int HashData(Stream source, Span destination); + protected abstract byte[] HashData(Stream source); + protected abstract ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken); + protected abstract ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken); protected void Verify(string input, string output) { @@ -35,6 +41,54 @@ private void VerifyComputeHashStream(Stream input, string output) Assert.Equal(expected, actual); } + private async Task VerifyComputeHashStreamAsync(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + byte[] actual; + + using (HashAlgorithm hash = Create()) + { + Assert.True(hash.HashSize > 0); + actual = await hash.ComputeHashAsync(input); + } + + Assert.Equal(expected, actual); + } + + private void VerifyOneShotStream(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + Span buffer = stackalloc byte[512 / 8]; + + int written = HashData(input, buffer); + AssertExtensions.SequenceEqual(expected, buffer.Slice(0, written)); + } + + private async Task VerifyOneShotStreamAsync(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + Memory buffer = new byte[512 / 8]; + + int written = await HashDataAsync(input, buffer, cancellationToken: default); + AssertExtensions.SequenceEqual(expected, buffer.Slice(0, written).Span); + } + + private void VerifyOneShotAllocatingStream(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + + byte[] digest = HashData(input); + Assert.Equal(expected, digest); + } + + private async Task VerifyOneShotAllocatingStreamAsync(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + + byte[] digest = await HashDataAsync(input, cancellationToken: default); + Assert.Equal(expected, digest); + } + private void VerifyICryptoTransformStream(Stream input, string output) { byte[] expected = ByteUtils.HexToByteArray(output); @@ -140,13 +194,13 @@ private void VerifyTransformBlockComputeHashInteraction(byte[] block1, byte[] bl [Fact] public void HashData_ByteArray_Null() { - AssertExtensions.Throws("source", () => HashData(null)); + AssertExtensions.Throws("source", () => HashData((byte[])null)); } [Fact] public void HashData_BufferTooSmall() { - AssertExtensions.Throws("destination", () => HashData(default, default)); + AssertExtensions.Throws("destination", () => HashData(Span.Empty, default)); } [Fact] @@ -320,6 +374,85 @@ protected void VerifyRepeating(string input, int repeatCount, string output) { VerifyICryptoTransformStream(stream, output); } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyOneShotStream(stream, output); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyOneShotAllocatingStream(stream, output); + } + } + + protected async Task VerifyRepeatingAsync(string input, int repeatCount, string output) + { + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyComputeHashStreamAsync(stream, output); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyOneShotStreamAsync(stream, output); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyOneShotAllocatingStreamAsync(stream, output); + } + } + + [Fact] + public void HashData_Null_Stream_Throws() + { + AssertExtensions.Throws("source", () => HashData((Stream)null)); + AssertExtensions.Throws("source", () => HashData((Stream)null, Span.Empty)); + } + + [Fact] + public void HashData_ShortDestination_Throws() + { + AssertExtensions.Throws("destination", () => HashData(Stream.Null, Span.Empty)); + } + + [Fact] + public void HashDataAsync_Null_Stream_Throws() + { + AssertExtensions.Throws( + "source", + () => HashDataAsync((Stream)null, cancellationToken: default)); + + AssertExtensions.Throws( + "source", + () => HashDataAsync((Stream)null, Memory.Empty, cancellationToken: default)); + } + + [Fact] + public void HashDataAsync_ShortDestination_Throws() + { + AssertExtensions.Throws( + "destination", + () => HashDataAsync(Stream.Null, Memory.Empty, cancellationToken: default)); + } + + [Fact] + public void HashDataAsync_Buffer_CancelledToken() + { + Memory buffer = new byte[512 / 8]; + CancellationToken cancelledToken = new CancellationToken(canceled: true); + ValueTask waitable = HashDataAsync(Stream.Null, buffer, cancelledToken); + Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); + AssertExtensions.FilledWith(0, buffer.Span); + } + + [Fact] + public void HashDataAsync_Allocating_CancelledToken() + { + CancellationToken cancelledToken = new CancellationToken(canceled: true); + ValueTask waitable = HashDataAsync(Stream.Null, cancelledToken); + Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); } [Fact] @@ -511,91 +644,5 @@ public void Initialize_DoubleInitialize_Works() Assert.Equal(expectedDigest, hash.Hash); } } - - protected class DataRepeatingStream : Stream - { - private int _remaining; - private byte[] _data; - - public DataRepeatingStream(string data, int repeatCount) - { - _remaining = repeatCount; - _data = ByteUtils.AsciiBytes(data); - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (!CanRead) - { - throw new NotSupportedException(); - } - - if (_remaining == 0) - { - return 0; - } - - if (count < _data.Length) - { - throw new InvalidOperationException(); - } - - int multiple = count / _data.Length; - - if (multiple > _remaining) - { - multiple = _remaining; - } - - int localOffset = offset; - - for (int i = 0; i < multiple; i++) - { - Buffer.BlockCopy(_data, 0, buffer, localOffset, _data.Length); - localOffset += _data.Length; - } - - _remaining -= multiple; - return _data.Length * multiple; - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _data = null; - } - } - - public override void Flush() - { - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override bool CanRead { get { return _data != null; } } - public override bool CanSeek { get { return false; } } - public override bool CanWrite { get { return false; } } - public override long Length { get { throw new NotSupportedException(); } } - - public override long Position - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - } - } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs index 99ad3814d0a37..d658411811826 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -55,6 +58,31 @@ protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => HMACMD5.TryHashData(key, source, destination, out written); + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACMD5.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACMD5.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACMD5.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACMD5.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACMD5.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACMD5.HashDataAsync(key, source, cancellationToken); + [Fact] public void HmacMD5_Rfc2202_1() { @@ -108,5 +136,77 @@ public void HMacMD5_ThrowsArgumentNullForNullConstructorKey() { AssertExtensions.Throws("key", () => new HMACMD5(null)); } + + [Fact] + public void HmacMD5_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "1287EF250C2026A0C0CBA832C599AE50"); + } + + [Fact] + public void HmacMD5_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "D10B835D95FCC9EECDF1D4BCDAB81897"); + } + + [Fact] + public void HmacMD5_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "C91E40247251F39BDFE6A7B72A5857F9"); + } + + [Fact] + public async Task HmacMD5_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "1287EF250C2026A0C0CBA832C599AE50"); + } + + [Fact] + public async Task HmacMD5_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "D10B835D95FCC9EECDF1D4BCDAB81897"); + } + + [Fact] + public async Task HmacMD5_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl md5 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "C91E40247251F39BDFE6A7B72A5857F9"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs index 61b395d572535..d618b7122a32d 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -55,6 +58,31 @@ protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => HMACSHA1.TryHashData(key, source, destination, out written); + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA1.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA1.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA1.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA1.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA1.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA1.HashDataAsync(key, source, cancellationToken); + [Fact] public void HmacSha1_Byte_Constructors() { @@ -128,9 +156,81 @@ public void HmacSha1_Rfc2202_7() } [Fact] - public void HMacSha1_Rfc2104_2() + public void HmacSha1_Rfc2104_2() { VerifyHmacRfc2104_2(); } + + [Fact] + public void HmacSha1_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "3CE5AE476733905861F031DDC2DEDF8CBB1FAA0B"); + } + + [Fact] + public void HmacSha1_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "E18D7FB16A83CA17DB6CB0F1C083AA7A7094F627"); + } + + [Fact] + public void HmacSha1_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5433122F77BCF8A4D9B874B4149823EF5B7C207E"); + } + + [Fact] + public async Task HmacSha1_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "3CE5AE476733905861F031DDC2DEDF8CBB1FAA0B"); + } + + [Fact] + public async Task HmacSha1_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "E18D7FB16A83CA17DB6CB0F1C083AA7A7094F627"); + } + + [Fact] + public async Task HmacSha1_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha1 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5433122F77BCF8A4D9B874B4149823EF5B7C207E"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs index f2f1784404675..587711a920ad2 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -26,6 +29,31 @@ protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => HMACSHA256.TryHashData(key, source, destination, out written); + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA256.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA256.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA256.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA256.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA256.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA256.HashDataAsync(key, source, cancellationToken); + private static byte[][] s_testMacs4231 = { null, @@ -86,7 +114,7 @@ public void HmacSha256_Rfc4231_7() } [Fact] - public void HMacSha256_Rfc2104_2() + public void HmacSha256_Rfc2104_2() { VerifyHmacRfc2104_2(); } @@ -96,5 +124,77 @@ public void HmacSha256_ThrowsArgumentNullForNullConstructorKey() { AssertExtensions.Throws("key", () => new HMACSHA256(null)); } + + [Fact] + public void HmacSha256_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "A47B9F5BD5C2DEF403A0279D4C6C407A2D34561E7D1F006D7FE8BDC2C78227D5"); + } + + [Fact] + public void HmacSha256_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "1CF6661B6EFD25D8B6DE734AA39D5D3D44C9A56BB9377A6388EB0FC5E48A108B"); + } + + [Fact] + public void HmacSha256_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "07EFF8B326B7798C9CCFCBDBE579489AC785A7995A04618B1A2813C26744777D"); + } + + [Fact] + public async Task HmacSha256_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "A47B9F5BD5C2DEF403A0279D4C6C407A2D34561E7D1F006D7FE8BDC2C78227D5"); + } + + [Fact] + public async Task HmacSha256_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "1CF6661B6EFD25D8B6DE734AA39D5D3D44C9A56BB9377A6388EB0FC5E48A108B"); + } + + [Fact] + public async Task HmacSha256_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "07EFF8B326B7798C9CCFCBDBE579489AC785A7995A04618B1A2813C26744777D"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs index dbff8c26c50bc..eb3bbf5681e8b 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -26,6 +29,31 @@ protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => HMACSHA384.TryHashData(key, source, destination, out written); + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA384.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA384.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA384.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA384.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA384.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA384.HashDataAsync(key, source, cancellationToken); + private static byte[][] s_testMacs4231 = { null, @@ -99,7 +127,7 @@ public void HmacSha384_Rfc4231_7() } [Fact] - public void HMacSha384_Rfc2104_2() + public void HmacSha384_Rfc2104_2() { VerifyHmacRfc2104_2(); } @@ -109,5 +137,77 @@ public void HmacSha384_ThrowsArgumentNullForNullConstructorKey() { AssertExtensions.Throws("key", () => new HMACSHA384(null)); } + + [Fact] + public void HmacSha384_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "6C4977B00CCE179ADCC06EB35E48ABDE9B5604FC9E8B6B25F65E0234EE6394DE40F0C6C6B727B58B19ADFC1E5BB2E84D"); + } + + [Fact] + public void HmacSha384_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "45303A3B5F02C8462D6FA438893DAA05EFFA850B853DF614D45F343D20AFE6D6DBAC6D0656788C4398EDF0AEC01488D4"); + } + + [Fact] + public void HmacSha384_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "6A0FDC1C54C664AD91C7C157D2670C5D44E4D44EBAD2359A0206974C7088B1A867F76971E6C240C33B33A66BA295BB56"); + } + + [Fact] + public async Task HmacSha384_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "6C4977B00CCE179ADCC06EB35E48ABDE9B5604FC9E8B6B25F65E0234EE6394DE40F0C6C6B727B58B19ADFC1E5BB2E84D"); + } + + [Fact] + public async Task HmacSha384_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "45303A3B5F02C8462D6FA438893DAA05EFFA850B853DF614D45F343D20AFE6D6DBAC6D0656788C4398EDF0AEC01488D4"); + } + + [Fact] + public async Task HmacSha384_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "6A0FDC1C54C664AD91C7C157D2670C5D44E4D44EBAD2359A0206974C7088B1A867F76971E6C240C33B33A66BA295BB56"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs index 7bf5ed6652873..7172d68d43dfe 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -26,6 +29,31 @@ protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => HMACSHA512.TryHashData(key, source, destination, out written); + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA512.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA512.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA512.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA512.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA512.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA512.HashDataAsync(key, source, cancellationToken); + private static byte[][] s_testMacs4231 = { null, @@ -99,7 +127,7 @@ public void HmacSha512_Rfc4231_7() } [Fact] - public void HMacSha512_Rfc2104_2() + public void HmacSha512_Rfc2104_2() { VerifyHmacRfc2104_2(); } @@ -109,5 +137,77 @@ public void HmacSha512_ThrowsArgumentNullForNullConstructorKey() { AssertExtensions.Throws("key", () => new HMACSHA512(null)); } + + [Fact] + public void HmacSha512_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "05A7BB210D374B0CC36FFFA561045F1C1EB8E71905A50308B108D4677CCB0452A99B26EE41DD8E1D87D53A4F3E07B1231E5D3FFFCE7FD0C5C5A8B8F5E0206A11"); + } + + [Fact] + public void HmacSha512_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "9040E87E9CC546C507C3DEE90D278975B0C2049F28E71CC6FEEA0F3690EC9D0B736F885FFAA611156DA0C2904FC2EEEAA9562B53EB50F590902B2AE38056C874"); + } + + [Fact] + public void HmacSha512_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "2FEC800CA276C44985A35AEC92067E5E53A1BB80A6FDAB1D9C97D54068118F30AD4C33717466D372EA00BBF126E5B79C6F7143DD36C31F72028330E92AE3A359"); + } + + [Fact] + public async Task HmacSha512_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "05A7BB210D374B0CC36FFFA561045F1C1EB8E71905A50308B108D4677CCB0452A99B26EE41DD8E1D87D53A4F3E07B1231E5D3FFFCE7FD0C5C5A8B8F5E0206A11"); + } + + [Fact] + public async Task HmacSha512_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "9040E87E9CC546C507C3DEE90D278975B0C2049F28E71CC6FEEA0F3690EC9D0B736F885FFAA611156DA0C2904FC2EEEAA9562B53EB50F590902B2AE38056C874"); + } + + [Fact] + public async Task HmacSha512_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "2FEC800CA276C44985A35AEC92067E5E53A1BB80A6FDAB1D9C97D54068118F30AD4C33717466D372EA00BBF126E5B79C6F7143DD36C31F72028330E92AE3A359"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacTests.cs b/src/libraries/System.Security.Cryptography/tests/HmacTests.cs index ca266b43921fe..9083a9fd15e7b 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; +using System.Threading; +using System.Threading.Tasks; using Test.Cryptography; using Xunit; @@ -31,10 +33,123 @@ protected HmacTests(byte[][] testKeys, byte[][] testData, byte[][] testMacs) protected abstract byte[] HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source); protected abstract int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination); protected abstract bool TryHashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written); + protected abstract byte[] HashDataOneShot(ReadOnlySpan key, Stream source); + protected abstract byte[] HashDataOneShot(byte[] key, Stream source); + protected abstract int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination); + + protected abstract ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken); + + protected abstract ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken); + + protected abstract ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken); protected abstract int BlockSize { get; } protected abstract int MacSize { get; } + protected void VerifyRepeating(string input, int repeatCount, string hexKey, string output) + { + byte[] key = ByteUtils.HexToByteArray(hexKey); + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyHashDataStreamAllocating(key, stream, output, spanKey: true); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyHashDataStreamAllocating(key, stream, output, spanKey: false); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyHashDataStream(key, stream, output); + } + } + + protected async Task VerifyRepeatingAsync(string input, int repeatCount, string hexKey, string output) + { + byte[] key = ByteUtils.HexToByteArray(hexKey); + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyHashDataStreamAllocatingAsync(key, stream, output, memoryKey: true); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyHashDataStreamAllocatingAsync(key, stream, output, memoryKey: false); + } + + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + await VerifyHashDataStreamAsync(key, stream, output); + } + } + + protected void VerifyHashDataStream(ReadOnlySpan key, Stream stream, string output) + { + Span destination = stackalloc byte[MacSize]; + byte[] expected = ByteUtils.HexToByteArray(output); + int written = HashDataOneShot(key, stream, destination); + + Assert.Equal(MacSize, written); + AssertExtensions.SequenceEqual(expected, destination); + } + + protected async Task VerifyHashDataStreamAsync(ReadOnlyMemory key, Stream stream, string output) + { + Memory destination = new byte[MacSize]; + byte[] expected = ByteUtils.HexToByteArray(output); + int written = await HashDataOneShotAsync(key, stream, destination, cancellationToken: default); + + Assert.Equal(MacSize, written); + AssertExtensions.SequenceEqual(expected, destination.Span); + } + + protected void VerifyHashDataStreamAllocating(byte[] key, Stream stream, string output, bool spanKey) + { + byte[] expected = ByteUtils.HexToByteArray(output); + byte[] hmac; + + if (spanKey) + { + hmac = HashDataOneShot(key.AsSpan(), stream); + } + else + { + hmac = HashDataOneShot(key, stream); + } + + Assert.Equal(expected, hmac); + } + + protected async Task VerifyHashDataStreamAllocatingAsync(byte[] key, Stream stream, string output, bool memoryKey) + { + byte[] expected = ByteUtils.HexToByteArray(output); + byte[] hmac; + + if (memoryKey) + { + hmac = await HashDataOneShotAsync(new ReadOnlyMemory(key), stream, cancellationToken: default); + } + else + { + hmac = await HashDataOneShotAsync(key, stream, cancellationToken: default); + } + + Assert.Equal(expected, hmac); + } + protected void VerifyHmac(int testCaseId, byte[] digestBytes) { byte[] data = _testData[testCaseId]; @@ -386,5 +501,111 @@ public void OneShot_Empty_Matches_Instances(byte[] key, byte[] source) Assert.Equal(mac, oneShot); } } + + [Fact] + public void HashData_Stream_Source_Null() + { + AssertExtensions.Throws( + "source", + () => HashDataOneShot(ReadOnlySpan.Empty, (Stream)null)); + + AssertExtensions.Throws( + "source", + () => HashDataOneShot(Array.Empty(), (Stream)null)); + } + + [Fact] + public void HashData_Stream_Source_Null_Async() + { + AssertExtensions.Throws( + "source", + () => HashDataOneShotAsync(ReadOnlyMemory.Empty, (Stream)null, default)); + + AssertExtensions.Throws( + "source", + () => HashDataOneShotAsync(Array.Empty(), (Stream)null, default)); + } + + [Fact] + public void HashData_Stream_ByteKey_Null() + { + AssertExtensions.Throws( + "key", + () => HashDataOneShot((byte[])null, Stream.Null)); + } + + [Fact] + public void HashData_Stream_ByteKey_Null_Async() + { + AssertExtensions.Throws( + "key", + () => HashDataOneShotAsync((byte[])null, Stream.Null, default)); + } + + [Fact] + public void HashData_Stream_DestinationTooSmall() + { + byte[] destination = new byte[MacSize - 1]; + + AssertExtensions.Throws( + "destination", + () => HashDataOneShot(Array.Empty(), Stream.Null, destination)); + AssertExtensions.FilledWith(0, destination); + + AssertExtensions.Throws( + "destination", + () => HashDataOneShot(ReadOnlySpan.Empty, Stream.Null, destination)); + AssertExtensions.FilledWith(0, destination); + } + + [Fact] + public void HashData_Stream_DestinationTooSmall_Async() + { + byte[] destination = new byte[MacSize - 1]; + + AssertExtensions.Throws( + "destination", + () => HashDataOneShotAsync(Array.Empty(), Stream.Null, destination, default)); + AssertExtensions.FilledWith(0, destination); + + AssertExtensions.Throws( + "destination", + () => HashDataOneShotAsync(ReadOnlyMemory.Empty, Stream.Null, destination, default)); + AssertExtensions.FilledWith(0, destination); + } + + [Fact] + public void HashData_Stream_NotReadable() + { + AssertExtensions.Throws( + "source", + () => HashDataOneShot(Array.Empty(), UntouchableStream.Instance)); + + AssertExtensions.Throws( + "source", + () => HashDataOneShot(ReadOnlySpan.Empty, UntouchableStream.Instance)); + } + + [Fact] + public void HashData_Stream_Cancelled() + { + Memory buffer = new byte[512 / 8]; + CancellationToken cancelledToken = new CancellationToken(canceled: true); + ValueTask waitable = HashDataOneShotAsync(ReadOnlyMemory.Empty, Stream.Null, buffer, cancelledToken); + Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); + AssertExtensions.FilledWith(0, buffer.Span); + + waitable = HashDataOneShotAsync(Array.Empty(), Stream.Null, buffer, cancelledToken); + Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); + AssertExtensions.FilledWith(0, buffer.Span); + } + + [Fact] + public void HashData_Stream_Allocating_Cancelled() + { + CancellationToken cancelledToken = new CancellationToken(canceled: true); + ValueTask waitable = HashDataOneShotAsync(ReadOnlyMemory.Empty, Stream.Null, cancelledToken); + Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs index d5acc5b27aa43..e1a31bd49dc93 100644 --- a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs @@ -42,13 +42,13 @@ public static IEnumerable GetHMACs() [Fact] public static void InvalidArguments_Throw() { - AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHash(new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHash(new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHash(new HashAlgorithmName(""))); if (PlatformDetection.IsNotBrowser) { // HMAC is not supported on Browser - AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(null), new byte[1])); + AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(null), new byte[1])); AssertExtensions.Throws("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(""), new byte[1])); AssertExtensions.Throws("key", () => IncrementalHash.CreateHMAC(HashAlgorithmName.SHA512, null)); diff --git a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs index e301eae2fc300..26ab965bf4799 100644 --- a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Security.Cryptography.Tests @@ -25,6 +28,49 @@ protected override bool TryHashData(ReadOnlySpan source, Span destin protected override int HashData(ReadOnlySpan source, Span destination) => MD5.HashData(source, destination); + protected override int HashData(Stream source, Span destination) => + MD5.HashData(source, destination); + + protected override byte[] HashData(Stream source) => MD5.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + MD5.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + MD5.HashDataAsync(source, cancellationToken); + + [Fact] + public void MD5_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -md5 + VerifyRepeating("0102030405060708", 1024, "5fc6366852074da6e4795a014574282c"); + } + + [Fact] + public void MD5_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -md5 + VerifyRepeating("0102030405060708", 1025, "c5f6181a24446a583b14282f32786513"); + } + + [Fact] + public async Task MD5_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -md5 + await VerifyRepeatingAsync("0102030405060708", 1025, "c5f6181a24446a583b14282f32786513"); + } + + [Fact] + public async Task MD5_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -md5 + await VerifyRepeatingAsync("0102030405060708", 1024, "5fc6366852074da6e4795a014574282c"); + } + // Test cases are defined in RFC 1321, section A.5 [Fact] @@ -79,10 +125,28 @@ public void MD5_Rfc1321_7() Verify("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"); } + [Fact] + public void MD5_Rfc1321_1_AsStream() + { + VerifyRepeating(string.Empty, 0, "d41d8cd98f00b204e9800998ecf8427e"); + } + [Fact] public void MD5_Rfc1321_7_AsStream() { VerifyRepeating("1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"); } + + [Fact] + public async Task MD5_Rfc1321_1_AsStream_Async() + { + await VerifyRepeatingAsync(string.Empty, 0, "d41d8cd98f00b204e9800998ecf8427e"); + } + + [Fact] + public async Task MD5_Rfc1321_7_AsStream_Async() + { + await VerifyRepeatingAsync("1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/RSATests.cs b/src/libraries/System.Security.Cryptography/tests/RSATests.cs index 9decadbc179f7..17911da7f1b59 100644 --- a/src/libraries/System.Security.Cryptography/tests/RSATests.cs +++ b/src/libraries/System.Security.Cryptography/tests/RSATests.cs @@ -145,7 +145,7 @@ public void SignDataArray_UsesHashDataAndSignHash() AssertExtensions.Throws("count", () => rsa.SignData(new byte[1], 0, -1, HashAlgorithmName.SHA256, null)); AssertExtensions.Throws("count", () => rsa.SignData(new byte[1], 0, 2, HashAlgorithmName.SHA256, null)); - AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(null), null)); + AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(null), null)); AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(new byte[1], 0, 1, new HashAlgorithmName(""), null)); AssertExtensions.Throws("padding", () => rsa.SignData(new byte[1], 0, 1, new HashAlgorithmName("abc"), null)); @@ -163,7 +163,7 @@ public void SignDataStream_UsesHashDataAndSignHash() AssertExtensions.Throws("data", () => rsa.SignData((Stream)null, HashAlgorithmName.SHA256, null)); - AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(Stream.Null, new HashAlgorithmName(null), null)); + AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(Stream.Null, new HashAlgorithmName(null), null)); AssertExtensions.Throws("hashAlgorithm", () => rsa.SignData(Stream.Null, new HashAlgorithmName(""), null)); AssertExtensions.Throws("padding", () => rsa.SignData(Stream.Null, new HashAlgorithmName("abc"), null)); @@ -182,7 +182,7 @@ public void VerifyDataStream_UsesHashDataAndVerifyHash() AssertExtensions.Throws("signature", () => rsa.VerifyData(Stream.Null, null, HashAlgorithmName.SHA256, null)); - AssertExtensions.Throws("hashAlgorithm", () => rsa.VerifyData(Stream.Null, new byte[1], new HashAlgorithmName(null), null)); + AssertExtensions.Throws("hashAlgorithm", () => rsa.VerifyData(Stream.Null, new byte[1], new HashAlgorithmName(null), null)); AssertExtensions.Throws("hashAlgorithm", () => rsa.VerifyData(Stream.Null, new byte[1], new HashAlgorithmName(""), null)); AssertExtensions.Throws("padding", () => rsa.VerifyData(Stream.Null, new byte[1], new HashAlgorithmName("abc"), null)); diff --git a/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs b/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs index 3376d711779bf..cd92dc99b57ea 100644 --- a/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs @@ -75,10 +75,14 @@ public static void Pbkdf2_PasswordBytes_BogusHash() [Fact] public static void Pbkdf2_PasswordBytes_NullHashName() { - AssertExtensions.Throws("hashAlgorithm", () => + AssertExtensions.Throws("hashAlgorithm", () => Rfc2898DeriveBytes.Pbkdf2( s_passwordBytes, s_salt, iterations: 1, default(HashAlgorithmName), s_extractLength) ); + AssertExtensions.Throws("hashAlgorithm", () => + Rfc2898DeriveBytes.Pbkdf2( + s_passwordBytes, s_salt, iterations: 1, new HashAlgorithmName(""), s_extractLength) + ); } [Fact] @@ -147,10 +151,14 @@ public static void Pbkdf2_PasswordString_BogusHash() [Fact] public static void Pbkdf2_PasswordString_NullHashName() { - AssertExtensions.Throws("hashAlgorithm", () => + AssertExtensions.Throws("hashAlgorithm", () => Rfc2898DeriveBytes.Pbkdf2( Password, s_salt, iterations: 1, default(HashAlgorithmName), s_extractLength) ); + AssertExtensions.Throws("hashAlgorithm", () => + Rfc2898DeriveBytes.Pbkdf2( + Password, s_salt, iterations: 1, new HashAlgorithmName(""), s_extractLength) + ); } [Fact] diff --git a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs index 45d0315852cbe..46f0f24534348 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Security.Cryptography.Tests @@ -24,12 +27,67 @@ protected override bool TryHashData(ReadOnlySpan source, Span destin protected override int HashData(ReadOnlySpan source, Span destination) => SHA1.HashData(source, destination); + protected override int HashData(Stream source, Span destination) => + SHA1.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA1.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA1.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA1.HashDataAsync(source, cancellationToken); + [Fact] public void Sha1_Empty() { Verify(Array.Empty(), "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); } + [Fact] + public void Sha1_Empty_Stream() + { + VerifyRepeating("", 0, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + } + + [Fact] + public async Task Sha1_Empty_Stream_Async() + { + await VerifyRepeatingAsync("", 0, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + } + + [Fact] + public void Sha1_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha1 + VerifyRepeating("0102030405060708", 1024, "fc8053215c935a5e9cdc51b94bb40b3e66128d41"); + } + + [Fact] + public void Sha1_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha1 + VerifyRepeating("0102030405060708", 1025, "18c6aa8d255c47941958729faaae9614c9793bb2"); + } + + [Fact] + public async Task Sha1_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha1 + await VerifyRepeatingAsync("0102030405060708", 1025, "18c6aa8d255c47941958729faaae9614c9793bb2"); + } + + [Fact] + public async Task Sha1_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha1 + await VerifyRepeatingAsync("0102030405060708", 1024, "fc8053215c935a5e9cdc51b94bb40b3e66128d41"); + } + // SHA1 tests are defined somewhat obliquely within RFC 3174, section 7.3 // The same tests appear in http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf Appendix A [Fact] @@ -61,5 +119,17 @@ public void Sha1_Rfc3174_4() { VerifyRepeating("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); } + + [Fact] + public async Task Sha1_Rfc3174_3_Async() + { + await VerifyRepeatingAsync("a", 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"); + } + + [Fact] + public async Task Sha1_Rfc3174_4_Async() + { + await VerifyRepeatingAsync("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs index e85dddc08d797..4abad52b94094 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Security.Cryptography.Tests @@ -24,6 +27,17 @@ protected override bool TryHashData(ReadOnlySpan source, Span destin protected override int HashData(ReadOnlySpan source, Span destination) => SHA256.HashData(source, destination); + protected override int HashData(Stream source, Span destination) => + SHA256.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA256.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA256.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA256.HashDataAsync(source, cancellationToken); + [Fact] public void Sha256_Empty() { @@ -32,6 +46,62 @@ public void Sha256_Empty() "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); } + [Fact] + public void Sha256_Empty_Stream() + { + VerifyRepeating("", 0, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + } + + [Fact] + public async Task Sha256_Empty_Stream_Async() + { + await VerifyRepeatingAsync("", 0, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + } + + [Fact] + public void Sha256_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha256 + VerifyRepeating( + "0102030405060708", + 1024, + "cedca4ad2cce0d0b399931708684800cd16be396ffa5af51297a091650aa3610"); + } + + [Fact] + public void Sha256_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha256 + VerifyRepeating( + "0102030405060708", + 1025, + "9e2e99445f5349c379ceb4c995dde401f63012422183a411d02eb251b1e02e65"); + } + + [Fact] + public async Task Sha256_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha256 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "9e2e99445f5349c379ceb4c995dde401f63012422183a411d02eb251b1e02e65"); + } + + [Fact] + public async Task Sha256_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha256 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "cedca4ad2cce0d0b399931708684800cd16be396ffa5af51297a091650aa3610"); + } + // These test cases are from http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf Appendix B [Fact] public void Sha256_Fips180_1() @@ -67,5 +137,14 @@ public void Sha256_Fips180_3() 1000000, "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); } + + [Fact] + public async Task Sha256_Fips180_3_Async() + { + await VerifyRepeatingAsync( + "a", + 1000000, + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs index 5ef3ebcb4e039..c7cfea805683c 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Security.Cryptography.Tests @@ -24,6 +27,17 @@ protected override bool TryHashData(ReadOnlySpan source, Span destin protected override int HashData(ReadOnlySpan source, Span destination) => SHA384.HashData(source, destination); + protected override int HashData(Stream source, Span destination) => + SHA384.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA384.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA384.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA384.HashDataAsync(source, cancellationToken); + [Fact] public void Sha384_Empty() { @@ -32,6 +46,68 @@ public void Sha384_Empty() "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B"); } + [Fact] + public void Sha384_Empty_Stream() + { + VerifyRepeating( + "", + 0, + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B"); + } + + [Fact] + public async Task Sha384_Empty_Stream_Async() + { + await VerifyRepeatingAsync( + "", + 0, + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B"); + } + + [Fact] + public void Sha384_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha384 + VerifyRepeating( + "0102030405060708", + 1024, + "d9deec18b8ec0d31270eaeaaf3bcb1de55f1d81482a55d2c023bad873175f1694d8c28e8138d9147dc180e679cd79c58"); + } + + [Fact] + public void Sha384_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha384 + VerifyRepeating( + "0102030405060708", + 1025, + "35cf18493364379093c7def8477330f817f9045d2e311d721730b24d98c9d9e9761c7f27821742e0c236509627aea7fa"); + } + + [Fact] + public async Task Sha384_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha384 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "35cf18493364379093c7def8477330f817f9045d2e311d721730b24d98c9d9e9761c7f27821742e0c236509627aea7fa"); + } + + [Fact] + public async Task Sha384_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha384 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "d9deec18b8ec0d31270eaeaaf3bcb1de55f1d81482a55d2c023bad873175f1694d8c28e8138d9147dc180e679cd79c58"); + } + // These test cases are from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf [Fact] public void Sha384_NistShaAll_1() @@ -42,7 +118,7 @@ public void Sha384_NistShaAll_1() } [Fact] - public void Sha256_Fips180_MultiBlock() + public void Sha384_Fips180_MultiBlock() { VerifyMultiBlock( "a", diff --git a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs index 4586a08d846b0..465f41c15fdf6 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Security.Cryptography.Tests @@ -24,6 +27,17 @@ protected override bool TryHashData(ReadOnlySpan source, Span destin protected override int HashData(ReadOnlySpan source, Span destination) => SHA512.HashData(source, destination); + protected override int HashData(Stream source, Span destination) => + SHA512.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA512.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA512.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA512.HashDataAsync(source, cancellationToken); + [Fact] public void Sha512_Empty() { @@ -32,6 +46,68 @@ public void Sha512_Empty() "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); } + [Fact] + public void Sha512_Empty_Stream() + { + VerifyRepeating( + "", + 0, + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + [Fact] + public async Task Sha512_Empty_Stream_Async() + { + await VerifyRepeatingAsync( + "", + 0, + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + [Fact] + public void Sha512_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha512 + VerifyRepeating( + "0102030405060708", + 1024, + "da1bdf4632ea5ee0724a57a9bc6fd409d7f8f7417373356281ce36f82b510da95c7dff7d64a43b3cf4854894e124f56b349749a3f76b41611c01fee739f4d923"); + } + + [Fact] + public void Sha512_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha512 + VerifyRepeating( + "0102030405060708", + 1025, + "65de1e49167977ade93d12115d0f5915a988b7e0ab73f2b554bd6d87c17155e865ba434a88271fb2dbaf5f9b0cf71d627eaea6b0efce5ec95e4c6017bfbfb34b"); + } + + [Fact] + public async Task Sha512_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha512 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "65de1e49167977ade93d12115d0f5915a988b7e0ab73f2b554bd6d87c17155e865ba434a88271fb2dbaf5f9b0cf71d627eaea6b0efce5ec95e4c6017bfbfb34b"); + } + + [Fact] + public async Task Sha512_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha512 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "da1bdf4632ea5ee0724a57a9bc6fd409d7f8f7417373356281ce36f82b510da95c7dff7d64a43b3cf4854894e124f56b349749a3f76b41611c01fee739f4d923"); + } + // These test cases are from http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf Appendix C [Fact] public void Sha512_Fips180_1() @@ -67,5 +143,14 @@ public void Sha512_Fips180_3() 1000000, "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); } + + [Fact] + public async Task Sha512_Fips180_3_Async() + { + await VerifyRepeatingAsync( + "a", + 1000000, + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/StreamHelpers.cs b/src/libraries/System.Security.Cryptography/tests/StreamHelpers.cs new file mode 100644 index 0000000000000..022084779355c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/StreamHelpers.cs @@ -0,0 +1,147 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using Test.Cryptography; + +namespace System.Security.Cryptography.Tests +{ + internal class DataRepeatingStream : Stream + { + private int _remaining; + private byte[] _data; + + public DataRepeatingStream(string data, int repeatCount) + { + _remaining = repeatCount; + _data = ByteUtils.AsciiBytes(data); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (!CanRead) + { + throw new NotSupportedException(); + } + + if (_remaining == 0) + { + return 0; + } + + if (count < _data.Length) + { + throw new InvalidOperationException(); + } + + // For (about) half of the reads, we'll read one less byte + // than was asked for. This is to make sure stream readers + // conform to the expectation that Read MAY return less than + // was asked for. + if (count > 1 && Random.Shared.Next(2) == 0) + { + count--; + } + + int multiple = count / _data.Length; + + if (multiple > _remaining) + { + multiple = _remaining; + } + + int localOffset = offset; + + for (int i = 0; i < multiple; i++) + { + Buffer.BlockCopy(_data, 0, buffer, localOffset, _data.Length); + localOffset += _data.Length; + } + + _remaining -= multiple; + return _data.Length * multiple; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _data = null; + } + } + + public override void Flush() + { + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override bool CanRead { get { return _data != null; } } + public override bool CanSeek { get { return false; } } + public override bool CanWrite { get { return false; } } + public override long Length { get { throw new NotSupportedException(); } } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + } + + internal class UntouchableStream : Stream + { + public static Stream Instance { get; } = new UntouchableStream(); + + public override bool CanRead => false; + + public override bool CanSeek => false; + + public override bool CanWrite => false; + + public override long Length => throw new NotSupportedException(); + + public override long Position + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + + public override void Flush() + { + throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj index 8621f98748bd1..dafa4adb4bff2 100644 --- a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj +++ b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj @@ -265,6 +265,7 @@ + diff --git a/src/libraries/System.Security.Principal.Windows/src/Resources/Strings.resx b/src/libraries/System.Security.Principal.Windows/src/Resources/Strings.resx index adbd9d11a0a56..ac766cc5e7e88 100644 --- a/src/libraries/System.Security.Principal.Windows/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Principal.Windows/src/Resources/Strings.resx @@ -84,9 +84,6 @@ Non-negative number required. - - String cannot be of zero length. - Account name is too long. @@ -120,4 +117,4 @@ Windows Principal functionality is not supported on this platform. - \ No newline at end of file + diff --git a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/NTAccount.cs b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/NTAccount.cs index 82475e99b62fa..1513f00ceb642 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/NTAccount.cs +++ b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/NTAccount.cs @@ -33,15 +33,7 @@ public sealed class NTAccount : IdentityReference public NTAccount(string domainName, string accountName) { - if (accountName == null) - { - throw new ArgumentNullException(nameof(accountName)); - } - - if (accountName.Length == 0) - { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(accountName)); - } + ArgumentException.ThrowIfNullOrEmpty(accountName); if (accountName.Length > MaximumAccountNameLength) { @@ -65,15 +57,7 @@ public NTAccount(string domainName, string accountName) public NTAccount(string name) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); if (name.Length > (MaximumDomainNameLength + 1 /* '\' */ + MaximumAccountNameLength)) { diff --git a/src/libraries/System.ServiceModel.Syndication/src/Resources/Strings.resx b/src/libraries/System.ServiceModel.Syndication/src/Resources/Strings.resx index 6ac5b01d1c5a4..03d0e81ba8220 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/Resources/Strings.resx +++ b/src/libraries/System.ServiceModel.Syndication/src/Resources/Strings.resx @@ -188,9 +188,6 @@ The Rss20Serializer does not support RSS version '{0}'. - - The scheme parameter must not be empty. - The value of this argument must be non-negative. diff --git a/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs b/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs index 3fd806b0f5649..1298a7c23d690 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs @@ -10,4 +10,7 @@ public partial class ServiceController : System.ComponentModel.Component { public void Stop(bool stopDependentServices) { } } + public readonly partial struct SessionChangeDescription : System.IEquatable + { + } } diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj index 8fd0582994dd4..fac46aed04ba2 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj @@ -17,6 +17,8 @@ System.ServiceProcess.ServiceType true true SR.PlatformNotSupported_ServiceController + + $(NoWarn);CA1066 +#endif { internal SessionChangeDescription(SessionChangeReason reason, int id) { @@ -17,34 +20,20 @@ internal SessionChangeDescription(SessionChangeReason reason, int id) public int SessionId { get; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (!(obj is SessionChangeDescription)) - { - return false; - } + public override int GetHashCode() => + (int)Reason ^ SessionId; - return Equals((SessionChangeDescription)obj); - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is SessionChangeDescription other && Equals(other); - public override int GetHashCode() - { - return (int)Reason ^ SessionId; - } + public bool Equals(SessionChangeDescription changeDescription) => + (Reason == changeDescription.Reason) && + (SessionId == changeDescription.SessionId); - public bool Equals(SessionChangeDescription changeDescription) - { - return (Reason == changeDescription.Reason) && (SessionId == changeDescription.SessionId); - } + public static bool operator ==(SessionChangeDescription a, SessionChangeDescription b) => + a.Equals(b); - public static bool operator ==(SessionChangeDescription a, SessionChangeDescription b) - { - return a.Equals(b); - } - - public static bool operator !=(SessionChangeDescription a, SessionChangeDescription b) - { - return !a.Equals(b); - } + public static bool operator !=(SessionChangeDescription a, SessionChangeDescription b) => + !a.Equals(b); } } diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs index d6bf03a57d2f1..e44843b0c8193 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs @@ -176,8 +176,9 @@ internal interface ISpEngineSite void CompleteSkip(int skipped); void LoadResource([MarshalAs(UnmanagedType.LPWStr)] string resource, ref string mediaType, out IStream stream); } + [StructLayout(LayoutKind.Sequential)] - internal struct SpeechEventSapi + internal struct SpeechEventSapi : IEquatable { public short EventId; public short ParameterType; @@ -185,27 +186,22 @@ internal struct SpeechEventSapi public long AudioStreamOffset; public IntPtr Param1; // Always just a numeric type - contains no unmanaged resources so does not need special clean-up. public IntPtr Param2; // Can be a numeric type, or pointer to string or object. Use SafeSapiLParamHandle to cleanup. - public static bool operator ==(SpeechEventSapi event1, SpeechEventSapi event2) - { - return event1.EventId == event2.EventId && event1.ParameterType == event2.ParameterType && event1.StreamNumber == event2.StreamNumber && event1.AudioStreamOffset == event2.AudioStreamOffset && event1.Param1 == event2.Param1 && event1.Param2 == event2.Param2; - } - public static bool operator !=(SpeechEventSapi event1, SpeechEventSapi event2) - { - return !(event1 == event2); - } - public override bool Equals(object obj) - { - if (!(obj is SpeechEventSapi)) - { - return false; - } - return this == (SpeechEventSapi)obj; - } - public override int GetHashCode() - { - return base.GetHashCode(); - } + public static bool operator ==(SpeechEventSapi event1, SpeechEventSapi event2) => event1.Equals(event2); + public static bool operator !=(SpeechEventSapi event1, SpeechEventSapi event2) => !event1.Equals(event2); + + public override bool Equals(object obj) => + obj is SpeechEventSapi other && Equals(other); + + public bool Equals(SpeechEventSapi other) => + EventId == other.EventId && + ParameterType == other.ParameterType && + StreamNumber == other.StreamNumber && + AudioStreamOffset == other.AudioStreamOffset && + Param1 == other.Param1 && + Param2 == other.Param2; + + public override int GetHashCode() => base.GetHashCode(); } #endregion diff --git a/src/libraries/System.Text.Encoding/tests/Fallback/DecoderReplacementFallbackTests.cs b/src/libraries/System.Text.Encoding/tests/Fallback/DecoderReplacementFallbackTests.cs index 51d3f2d074e72..7bb51d8a22dd8 100644 --- a/src/libraries/System.Text.Encoding/tests/Fallback/DecoderReplacementFallbackTests.cs +++ b/src/libraries/System.Text.Encoding/tests/Fallback/DecoderReplacementFallbackTests.cs @@ -36,12 +36,12 @@ public void Ctor_Invalid() AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback(null)); // Invalid surrogate pair - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("\uD800")); - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("\uD800a")); - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("\uDC00")); - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("a\uDC00")); - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("\uDC00\uDC00")); - AssertExtensions.Throws(null, () => new DecoderReplacementFallback("\uD800\uD800")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("\uD800")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("\uD800a")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("\uDC00")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("a\uDC00")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("\uDC00\uDC00")); + AssertExtensions.Throws("replacement", () => new DecoderReplacementFallback("\uD800\uD800")); } public static IEnumerable Equals_TestData() diff --git a/src/libraries/System.Text.Encoding/tests/Fallback/EncoderReplacementFallbackTests.cs b/src/libraries/System.Text.Encoding/tests/Fallback/EncoderReplacementFallbackTests.cs index 45709bb693e22..1fe7b2499ab16 100644 --- a/src/libraries/System.Text.Encoding/tests/Fallback/EncoderReplacementFallbackTests.cs +++ b/src/libraries/System.Text.Encoding/tests/Fallback/EncoderReplacementFallbackTests.cs @@ -36,12 +36,12 @@ public void Ctor_Invalid() AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback(null)); // Invalid surrogate pair - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("\uD800")); - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("\uD800a")); - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("\uDC00")); - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("a\uDC00")); - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("\uDC00\uDC00")); - AssertExtensions.Throws(null, () => new EncoderReplacementFallback("\uD800\uD800")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("\uD800")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("\uD800a")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("\uDC00")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("a\uDC00")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("\uDC00\uDC00")); + AssertExtensions.Throws("replacement", () => new EncoderReplacementFallback("\uD800\uD800")); } public static IEnumerable Equals_TestData() diff --git a/src/libraries/System.Text.Encodings.Web/ref/System.Text.Encodings.Web.cs b/src/libraries/System.Text.Encodings.Web/ref/System.Text.Encodings.Web.cs index f38e07bfbb2a5..72e30ff774322 100644 --- a/src/libraries/System.Text.Encodings.Web/ref/System.Text.Encodings.Web.cs +++ b/src/libraries/System.Text.Encodings.Web/ref/System.Text.Encodings.Web.cs @@ -83,6 +83,7 @@ public static partial class UnicodeRanges public static System.Text.Unicode.UnicodeRange AlphabeticPresentationForms { get { throw null; } } public static System.Text.Unicode.UnicodeRange Arabic { get { throw null; } } public static System.Text.Unicode.UnicodeRange ArabicExtendedA { get { throw null; } } + public static System.Text.Unicode.UnicodeRange ArabicExtendedB { get { throw null; } } public static System.Text.Unicode.UnicodeRange ArabicPresentationFormsA { get { throw null; } } public static System.Text.Unicode.UnicodeRange ArabicPresentationFormsB { get { throw null; } } public static System.Text.Unicode.UnicodeRange ArabicSupplement { get { throw null; } } diff --git a/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs b/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs index 66c637eda2a2b..774ee9e426c7e 100644 --- a/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs +++ b/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs @@ -14,7 +14,7 @@ namespace System.Text { - internal readonly struct Rune + internal readonly struct Rune : IEquatable { private const int MaxUtf16CharsPerRune = 2; // supplementary plane code points are encoded as 2 UTF-16 code units diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRanges.generated.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRanges.generated.cs index c95e2ebc71bca..5ab03229dc03d 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRanges.generated.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRanges.generated.cs @@ -190,6 +190,15 @@ public static partial class UnicodeRanges public static UnicodeRange SyriacSupplement => _u0860 ?? CreateRange(ref _u0860, first: '\u0860', last: '\u086F'); private static UnicodeRange? _u0860; + /// + /// A corresponding to the 'Arabic Extended-B' Unicode block (U+0870..U+089F). + /// + /// + /// See https://www.unicode.org/charts/PDF/U0870.pdf for the full set of characters in this block. + /// + public static UnicodeRange ArabicExtendedB => _u0870 ?? CreateRange(ref _u0870, first: '\u0870', last: '\u089F'); + private static UnicodeRange? _u0870; + /// /// A corresponding to the 'Arabic Extended-A' Unicode block (U+08A0..U+08FF). /// diff --git a/src/libraries/System.Text.Encodings.Web/tests/UnicodeRangesTests.generated.cs b/src/libraries/System.Text.Encodings.Web/tests/UnicodeRangesTests.generated.cs index fcf41b771ff10..69479ad534768 100644 --- a/src/libraries/System.Text.Encodings.Web/tests/UnicodeRangesTests.generated.cs +++ b/src/libraries/System.Text.Encodings.Web/tests/UnicodeRangesTests.generated.cs @@ -32,6 +32,7 @@ public static partial class UnicodeRangesTests new object[] { '\u0800', '\u083F', nameof(UnicodeRanges.Samaritan) }, new object[] { '\u0840', '\u085F', nameof(UnicodeRanges.Mandaic) }, new object[] { '\u0860', '\u086F', nameof(UnicodeRanges.SyriacSupplement) }, + new object[] { '\u0870', '\u089F', nameof(UnicodeRanges.ArabicExtendedB) }, new object[] { '\u08A0', '\u08FF', nameof(UnicodeRanges.ArabicExtendedA) }, new object[] { '\u0900', '\u097F', nameof(UnicodeRanges.Devanagari) }, new object[] { '\u0980', '\u09FF', nameof(UnicodeRanges.Bengali) }, diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index f6b25cdcb23d4..2bae8025f0ca0 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -20,8 +20,8 @@ public void Dispose() { } public static System.Text.Json.JsonDocument Parse(System.Buffers.ReadOnlySequence utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.JsonDocument Parse(System.IO.Stream utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.JsonDocument Parse(System.ReadOnlyMemory utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.JsonDocument Parse(System.ReadOnlyMemory json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.JsonDocument Parse(string json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlyMemory json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Threading.Tasks.Task ParseAsync(System.IO.Stream utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Text.Json.JsonDocument ParseValue(ref System.Text.Json.Utf8JsonReader reader) { throw null; } public static bool TryParseValue(ref System.Text.Json.Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonDocument? document) { throw null; } @@ -193,11 +193,11 @@ public static partial class JsonSerializer public static object? Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static object? Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static object? Deserialize(System.ReadOnlySpan json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static object? Deserialize(System.ReadOnlySpan json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static object? Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static object? Deserialize(string json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] public static object? Deserialize(this System.Text.Json.JsonDocument document, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static object? Deserialize(this System.Text.Json.JsonDocument document, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } @@ -225,11 +225,11 @@ public static partial class JsonSerializer public static TValue? Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static TValue? Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static TValue? Deserialize(System.ReadOnlySpan json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static TValue? Deserialize(System.ReadOnlySpan json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static TValue? Deserialize(string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static TValue? Deserialize(string json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] public static TValue? Deserialize(this System.Text.Json.JsonDocument document, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static TValue? Deserialize(this System.Text.Json.JsonDocument document, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } @@ -511,9 +511,9 @@ public void WritePropertyName(System.ReadOnlySpan utf8PropertyName) { } public void WritePropertyName(System.ReadOnlySpan propertyName) { } public void WritePropertyName(string propertyName) { } public void WritePropertyName(System.Text.Json.JsonEncodedText propertyName) { } - public void WriteRawValue(string json, bool skipInputValidation = false) { } + public void WriteRawValue([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, bool skipInputValidation = false) { } public void WriteRawValue(System.ReadOnlySpan utf8Json, bool skipInputValidation = false) { } - public void WriteRawValue(System.ReadOnlySpan json, bool skipInputValidation = false) { } + public void WriteRawValue([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, bool skipInputValidation = false) { } public void WriteStartArray() { } public void WriteStartArray(System.ReadOnlySpan utf8PropertyName) { } public void WriteStartArray(System.ReadOnlySpan propertyName) { } @@ -682,7 +682,7 @@ internal JsonNode() { } public static implicit operator System.Text.Json.Nodes.JsonNode (ulong value) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(System.IO.Stream utf8Json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(System.ReadOnlySpan utf8Json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.Nodes.JsonNode? Parse(string json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.Nodes.JsonNode? Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?)) { throw null; } public string ToJsonString(System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public override string ToString() { throw null; } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj index 13c5c50fbc0e5..a468f99d4e1bc 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj @@ -20,6 +20,10 @@ + + + + diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 40cd01f21877b..c8759d3fe2710 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -539,9 +539,6 @@ The converter '{0}' cannot return an instance of JsonConverterFactory. - - The result type '{0}' of the dynamic binding produced by the object with type '{1}' for the binder '{2}' is not compatible with the result type '{3}' expected by the call site. - The element must be of type '{0}' @@ -575,9 +572,6 @@ "The specified 'JsonSerializerOptions' instance is already bound with a 'JsonSerializerContext' instance." - - The value must represent an object type. - The generic type of the converter for property '{0}.{1}' must match with the specified converter type '{2}'. The converter must not be 'null'. diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index d5975ec253668..d24617f74a3d3 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -228,7 +228,7 @@ System.Text.Json.Nodes.JsonValue - + @@ -322,6 +322,9 @@ System.Text.Json.Nodes.JsonValue + + + @@ -355,8 +358,7 @@ System.Text.Json.Nodes.JsonValue - + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index 0e7446601716c..6ceaa0af7dd95 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -247,7 +247,7 @@ private static async Task ParseAsyncCore( /// /// contains unsupported options. /// - public static JsonDocument Parse(ReadOnlyMemory json, JsonDocumentOptions options = default) + public static JsonDocument Parse([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlyMemory json, JsonDocumentOptions options = default) { ReadOnlySpan jsonChars = json.Span; int expectedByteCount = JsonReaderHelper.GetUtf8ByteCount(jsonChars); @@ -311,7 +311,7 @@ internal static JsonDocument ParseValue(ReadOnlyMemory json, JsonDocumentO /// /// contains unsupported options. /// - public static JsonDocument Parse(string json, JsonDocumentOptions options = default) + public static JsonDocument Parse([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonDocumentOptions options = default) { if (json == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs index e59eedb567b06..0d6f3a75263eb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs @@ -1,6 +1,7 @@ // 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.CodeAnalysis; using System.IO; using System.Text.Json.Serialization.Converters; @@ -65,7 +66,7 @@ public abstract partial class JsonNode /// does not represent a valid single JSON value. /// public static JsonNode? Parse( - string json, + [StringSyntax(StringSyntaxAttribute.Json)] string json, JsonNodeOptions? nodeOptions = null, JsonDocumentOptions documentOptions = default(JsonDocumentOptions)) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs index cfe4a1130db3a..dc34dcfba8276 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs @@ -140,8 +140,10 @@ public string GetPath() /// /// Gets the root . - /// If the current is a root, is returned. /// + /// + /// The current node is returned if it is a root. + /// public JsonNode Root { get diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs index 8606c9b1efc49..9056413479aca 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs @@ -42,7 +42,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static TValue? Deserialize(string json, JsonSerializerOptions? options = null) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonSerializerOptions? options = null) { if (json == null) { @@ -78,7 +78,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static TValue? Deserialize(ReadOnlySpan json, JsonSerializerOptions? options = null) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, JsonSerializerOptions? options = null) { // default/null span is treated as empty @@ -114,7 +114,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static object? Deserialize(string json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, Type returnType, JsonSerializerOptions? options = null) { if (json == null) { @@ -158,7 +158,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static object? Deserialize(ReadOnlySpan json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, Type returnType, JsonSerializerOptions? options = null) { // default/null span is treated as empty @@ -202,7 +202,7 @@ public static partial class JsonSerializer /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static TValue? Deserialize(string json, JsonTypeInfo jsonTypeInfo) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonTypeInfo jsonTypeInfo) { // default/null span is treated as empty @@ -250,7 +250,7 @@ public static partial class JsonSerializer /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static TValue? Deserialize(ReadOnlySpan json, JsonTypeInfo jsonTypeInfo) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, JsonTypeInfo jsonTypeInfo) { // default/null span is treated as empty @@ -297,7 +297,7 @@ public static partial class JsonSerializer /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static object? Deserialize(string json, Type returnType, JsonSerializerContext context) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, Type returnType, JsonSerializerContext context) { if (json == null) { @@ -353,7 +353,7 @@ public static partial class JsonSerializer /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static object? Deserialize(ReadOnlySpan json, Type returnType, JsonSerializerContext context) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, Type returnType, JsonSerializerContext context) { if (returnType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultValueHolder.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultValueHolder.cs new file mode 100644 index 0000000000000..224376d3859da --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultValueHolder.cs @@ -0,0 +1,42 @@ +// 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.CodeAnalysis; + +namespace System.Text.Json.Serialization.Metadata +{ + /// + /// Helper class used for calculating the default value for a given System.Type instance. + /// + internal sealed class DefaultValueHolder + { + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "GetUninitializedObject is only called on a struct. You can always create an instance of a struct.")] + private DefaultValueHolder(Type type) + { + if (type.IsValueType && Nullable.GetUnderlyingType(type) == null) + { +#if NETCOREAPP + DefaultValue = System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(type); +#else + DefaultValue = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type); +#endif + } + } + + /// + /// Returns the default value for the specified type. + /// + public object? DefaultValue { get; } + + /// + /// Returns true if contains only default values. + /// + public bool IsDefaultValue(object value) => DefaultValue is null ? value is null : DefaultValue.Equals(value); + + /// + /// Creates a holder instance representing a type. + /// + public static DefaultValueHolder CreateHolder(Type type) => new DefaultValueHolder(type); + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs deleted file mode 100644 index 2c143f95e59cc..0000000000000 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs +++ /dev/null @@ -1,52 +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.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text.Json.Reflection; - -namespace System.Text.Json.Serialization.Metadata -{ - /// - /// Allows virtual dispatch to GenericMethodHolder{T}. - /// - internal abstract class GenericMethodHolder - { - /// - /// Returns the default value for the specified type. - /// - public abstract object? DefaultValue { get; } - - /// - /// Returns true if contains only default values. - /// - public abstract bool IsDefaultValue(object value); - - /// - /// Creates a holder instance representing a type. - /// - public static GenericMethodHolder CreateHolder(Type type) - { - Type holderType = typeof(GenericMethodHolder<>).MakeGenericType(type); - return (GenericMethodHolder)Activator.CreateInstance(holderType)!; - } - } - - /// - /// Generic methods for {T}. - /// - internal sealed class GenericMethodHolder : GenericMethodHolder - { - public override object? DefaultValue => default(T); - - public override bool IsDefaultValue(object value) - { - // For performance, we only want to call this method for non-nullable value types. - // Nullable types should be checked againt 'null' before calling this method. - Debug.Assert(!value.GetType().CanBeNull()); - - return EqualityComparer.Default.Equals(default, (T)value); - } - } -} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs index 3905c70402024..9139a027c5ea4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs @@ -101,14 +101,14 @@ public static JsonParameterInfo CreateIgnoredParameterPlaceholder( // doesn't match the parameter type, use reflection to get the default value. Type parameterType = parameterInfo.ParameterType; - GenericMethodHolder holder; + DefaultValueHolder holder; if (matchingProperty.Options.TryGetClass(parameterType, out JsonTypeInfo? typeInfo)) { - holder = typeInfo.GenericMethods; + holder = typeInfo.DefaultValueHolder; } else { - holder = GenericMethodHolder.CreateHolder(parameterInfo.ParameterType); + holder = DefaultValueHolder.CreateHolder(parameterInfo.ParameterType); } jsonParameterInfo.DefaultValue = holder.DefaultValue; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index e98f08dd54cdc..a3670f2d8b362 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -287,7 +287,7 @@ value is not null && Debug.Assert(RuntimeTypeInfo.Type == DeclaredPropertyType); // Use a late-bound call to EqualityComparer. - if (RuntimeTypeInfo.GenericMethods.IsDefaultValue(value)) + if (RuntimeTypeInfo.DefaultValueHolder.IsDefaultValue(value)) { return true; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index 4bd852e447e2b..aea2e5a8e8c28 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -124,19 +124,12 @@ internal JsonTypeInfo? KeyTypeInfo internal bool IsObjectWithParameterizedCtor => PropertyInfoForTypeInfo.ConverterBase.ConstructorIsParameterized; - private GenericMethodHolder? _genericMethods; /// - /// Returns a helper class used when generic methods need to be invoked on Type. + /// Returns a helper class used for computing the default value. /// - internal GenericMethodHolder GenericMethods - { - get - { - _genericMethods ??= GenericMethodHolder.CreateHolder(Type); - return _genericMethods; - } - } + internal DefaultValueHolder DefaultValueHolder => _defaultValueHolder ??= DefaultValueHolder.CreateHolder(Type); + private DefaultValueHolder? _defaultValueHolder; internal JsonNumberHandling? NumberHandling { get; set; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index e5cd6d024ee1a..a164e71c13993 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -646,6 +646,12 @@ public static void ThrowInvalidOperationException_ExpectedChar(JsonTokenType tok { throw GetInvalidOperationException("char", tokenType); } + + [DoesNotReturn] + public static void ThrowObjectDisposedException_Utf8JsonWriter() + { + throw new ObjectDisposedException(nameof(Utf8JsonWriter)); + } } internal enum ExceptionResource diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs index 5ac9c8cebe315..d1a5c504993f8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -30,7 +31,7 @@ public sealed partial class Utf8JsonWriter /// /// The and values for the writer instance are not applied when using this method. /// - public void WriteRawValue(string json, bool skipInputValidation = false) + public void WriteRawValue([StringSyntax(StringSyntaxAttribute.Json)] string json, bool skipInputValidation = false) { if (!_options.SkipValidation) { @@ -66,7 +67,7 @@ public void WriteRawValue(string json, bool skipInputValidation = false) /// /// The and values for the writer instance are not applied when using this method. /// - public void WriteRawValue(ReadOnlySpan json, bool skipInputValidation = false) + public void WriteRawValue([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, bool skipInputValidation = false) { if (!_options.SkipValidation) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index 084b7c65c6350..9b22c33ac7d8f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -238,7 +238,7 @@ private void CheckNotDisposed() // The conditions are ordered with stream first as that would be the most common mode if (_output == null) { - throw new ObjectDisposedException(nameof(Utf8JsonWriter)); + ThrowHelper.ThrowObjectDisposedException_Utf8JsonWriter(); } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index 7bc91507d9ad5..a9fa26e3279f1 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs @@ -24,7 +24,7 @@ public static void VariousNestingAndVisibilityLevelsAreSupported() public static void Converters_AndTypeInfoCreator_NotRooted_WhenMetadataNotPresent() { RemoteExecutor.Invoke( - new Action(() => + () => { object[] objArr = new object[] { new MyStruct() }; @@ -56,8 +56,7 @@ static void AssertFieldNull(string fieldName, JsonSerializerOptions? optionsInst Assert.NotNull(fieldInfo); Assert.Null(fieldInfo.GetValue(optionsInstance)); } - }), - new RemoteInvokeOptions() { ExpectedExitCode = 0 }).Dispose(); + }).Dispose(); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/BitStackTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/BitStackTests.cs index 48d36677359df..08b47fc04cdce 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/BitStackTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/BitStackTests.cs @@ -128,7 +128,7 @@ public static void BitStackPushPopLarge(int bitLength) Assert.Equal(expectedDepth, bitStack.CurrentDepth); } - Assert.Equal(expectedDepth, IterationCapacity * 2); + Assert.Equal(IterationCapacity * 2, expectedDepth); // Loop backwards when popping. for (int i = bitLength - 1; i >= bitLength - IterationCapacity; i--) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonNodeOperatorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonNodeOperatorTests.cs index 0a3e130a317dc..27a565561c5e6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonNodeOperatorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonNodeOperatorTests.cs @@ -181,6 +181,7 @@ public static void ImplicitOperators_FromNullValues() [Fact] public static void ImplicitOperators_FromNullableValues() { + #pragma warning disable xUnit2002 Assert.NotNull((JsonValue?)(byte?)42); Assert.NotNull((JsonValue?)(short?)42); Assert.NotNull((JsonValue?)(int?)42); @@ -194,6 +195,7 @@ public static void ImplicitOperators_FromNullableValues() Assert.NotNull((JsonValue?)(float?)42); Assert.NotNull((JsonValue?)(double?)42); Assert.NotNull((JsonValue?)(decimal?)42); + #pragma warning restore xUnit2002 Assert.NotNull((JsonValue?)(DateTime?)new DateTime(2019, 1, 30, 12, 1, 2, DateTimeKind.Utc)); Assert.NotNull((JsonValue?)(DateTimeOffset?)new DateTimeOffset(2019, 1, 30, 12, 1, 2, new TimeSpan(1, 0, 0))); Assert.NotNull((JsonValue?)(Guid?)new Guid("1B33498A-7B7D-4DDA-9C13-F6AA4AB449A6")); diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 396cf1bef784b..1f2a5d7de00a0 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -392,68 +392,111 @@ private static RequiredHelperFunctions EmitFindFirstChar(IndentedTextWriter writ // searching is required; otherwise, false. bool EmitAnchors() { - // Generate anchor checks. - if ((code.FindOptimizations.LeadingAnchor & (RegexPrefixAnalyzer.Beginning | RegexPrefixAnalyzer.Start | RegexPrefixAnalyzer.EndZ | RegexPrefixAnalyzer.End | RegexPrefixAnalyzer.Bol)) != 0) + // Anchors that fully implement FindFirstChar, with a check that leads to immediate success or failure determination. + switch (code.FindOptimizations.FindMode) { - switch (code.FindOptimizations.LeadingAnchor) - { - case RegexPrefixAnalyzer.Beginning: - writer.WriteLine("// Beginning \\A anchor"); - additionalDeclarations.Add("int beginning = base.runtextbeg;"); - using (EmitBlock(writer, "if (pos > beginning)")) - { - writer.WriteLine($"goto {NoStartingPositionFound};"); - } - writer.WriteLine("return true;"); - return true; + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning: + writer.WriteLine("// Beginning \\A anchor"); + additionalDeclarations.Add("int beginning = base.runtextbeg;"); + using (EmitBlock(writer, "if (pos > beginning)")) + { + writer.WriteLine($"goto {NoStartingPositionFound};"); + } + writer.WriteLine("return true;"); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start: + writer.WriteLine("// Start \\G anchor"); + using (EmitBlock(writer, "if (pos > base.runtextstart)")) + { + writer.WriteLine($"goto {NoStartingPositionFound};"); + } + writer.WriteLine("return true;"); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ: + writer.WriteLine("// Leading end \\Z anchor"); + using (EmitBlock(writer, "if (pos < end - 1)")) + { + writer.WriteLine("base.runtextpos = end - 1;"); + } + writer.WriteLine("return true;"); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End: + writer.WriteLine("// Leading end \\z anchor"); + using (EmitBlock(writer, "if (pos < end)")) + { + writer.WriteLine("base.runtextpos = end;"); + } + writer.WriteLine("return true;"); + return true; - case RegexPrefixAnalyzer.Start: - writer.WriteLine("// Start \\G anchor"); - using (EmitBlock(writer, "if (pos > base.runtextstart)")) + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ: + // Jump to the end, minus the min required length, which in this case is actually the fixed length, minus 1 (for a possible ending \n). + writer.WriteLine("// Trailing end \\Z anchor with fixed-length match"); + using (EmitBlock(writer, $"if (pos < end - {code.Tree.MinRequiredLength + 1})")) + { + writer.WriteLine($"base.runtextpos = end - {code.Tree.MinRequiredLength + 1};"); + } + writer.WriteLine("return true;"); + return true; + + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End: + // Jump to the end, minus the min required length, which in this case is actually the fixed length. + writer.WriteLine("// Trailing end \\z anchor with fixed-length match"); + using (EmitBlock(writer, $"if (pos < end - {code.Tree.MinRequiredLength})")) + { + writer.WriteLine($"base.runtextpos = end - {code.Tree.MinRequiredLength};"); + } + writer.WriteLine("return true;"); + return true; + } + + // Now handle anchors that boost the position but may not determine immediate success or failure. + + switch (code.FindOptimizations.LeadingAnchor) + { + case RegexNodeKind.Bol: + // Optimize the handling of a Beginning-Of-Line (BOL) anchor. BOL is special, in that unlike + // other anchors like Beginning, there are potentially multiple places a BOL can match. So unlike + // the other anchors, which all skip all subsequent processing if found, with BOL we just use it + // to boost our position to the next line, and then continue normally with any searches. + writer.WriteLine("// Beginning-of-line anchor"); + additionalDeclarations.Add("global::System.ReadOnlySpan inputSpan = base.runtext;"); + additionalDeclarations.Add("int beginning = base.runtextbeg;"); + using (EmitBlock(writer, "if (pos > beginning && inputSpan[pos - 1] != '\\n')")) + { + writer.WriteLine("int newlinePos = global::System.MemoryExtensions.IndexOf(inputSpan.Slice(pos), '\\n');"); + using (EmitBlock(writer, "if (newlinePos < 0 || newlinePos + pos + 1 > end)")) { writer.WriteLine($"goto {NoStartingPositionFound};"); } - writer.WriteLine("return true;"); - return true; + writer.WriteLine("pos = newlinePos + pos + 1;"); + } + writer.WriteLine(); + break; + } - case RegexPrefixAnalyzer.EndZ: - writer.WriteLine("// End \\Z anchor"); - using (EmitBlock(writer, "if (pos < end - 1)")) - { - writer.WriteLine("base.runtextpos = end - 1;"); - } - writer.WriteLine("return true;"); - return true; + switch (code.FindOptimizations.TrailingAnchor) + { + case RegexNodeKind.End when code.FindOptimizations.MaxPossibleLength is int maxLength: + writer.WriteLine("// End \\z anchor with maximum-length match"); + using (EmitBlock(writer, $"if (pos < end - {maxLength})")) + { + writer.WriteLine($"pos = end - {maxLength};"); + } + writer.WriteLine(); + break; - case RegexPrefixAnalyzer.End: - writer.WriteLine("// End \\z anchor"); - using (EmitBlock(writer, "if (pos < end)")) - { - writer.WriteLine("base.runtextpos = end;"); - } - writer.WriteLine("return true;"); - return true; - - case RegexPrefixAnalyzer.Bol: - // Optimize the handling of a Beginning-Of-Line (BOL) anchor. BOL is special, in that unlike - // other anchors like Beginning, there are potentially multiple places a BOL can match. So unlike - // the other anchors, which all skip all subsequent processing if found, with BOL we just use it - // to boost our position to the next line, and then continue normally with any searches. - writer.WriteLine("// Beginning-of-line anchor"); - additionalDeclarations.Add("global::System.ReadOnlySpan inputSpan = base.runtext;"); - additionalDeclarations.Add("int beginning = base.runtextbeg;"); - using (EmitBlock(writer, "if (pos > beginning && inputSpan[pos - 1] != '\\n')")) - { - writer.WriteLine("int newlinePos = global::System.MemoryExtensions.IndexOf(inputSpan.Slice(pos), '\\n');"); - using (EmitBlock(writer, "if (newlinePos < 0 || newlinePos + pos + 1 > end)")) - { - writer.WriteLine($"goto {NoStartingPositionFound};"); - } - writer.WriteLine("pos = newlinePos + pos + 1;"); - } - writer.WriteLine(); - break; - } + case RegexNodeKind.EndZ when code.FindOptimizations.MaxPossibleLength is int maxLength: + writer.WriteLine("// End \\Z anchor with maximum-length match"); + using (EmitBlock(writer, $"if (pos < end - {maxLength + 1})")) + { + writer.WriteLine($"pos = end - {maxLength + 1};"); + } + writer.WriteLine(); + break; } return false; @@ -592,7 +635,7 @@ void EmitLiteralAfterAtomicLoop() Debug.Assert(code.FindOptimizations.LiteralAfterLoop is not null); (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Literal) target = code.FindOptimizations.LiteralAfterLoop.Value; - Debug.Assert(target.LoopNode.Type is RegexNode.Setloop or RegexNode.Setlazy or RegexNode.Setloopatomic); + Debug.Assert(target.LoopNode.Kind is RegexNodeKind.Setloop or RegexNodeKind.Setlazy or RegexNodeKind.Setloopatomic); Debug.Assert(target.LoopNode.N == int.MaxValue); using (EmitBlock(writer, "while (true)")) @@ -705,24 +748,24 @@ private static RequiredHelperFunctions EmitGo(IndentedTextWriter writer, RegexMe // Every RegexTree is rooted in the implicit Capture for the whole expression. // Skip the Capture node. We handle the implicit root capture specially. RegexNode node = code.Tree.Root; - Debug.Assert(node.Type == RegexNode.Capture, "Every generated tree should begin with a capture node"); + Debug.Assert(node.Kind == RegexNodeKind.Capture, "Every generated tree should begin with a capture node"); Debug.Assert(node.ChildCount() == 1, "Capture nodes should have one child"); node = node.Child(0); // In some limited cases, FindFirstChar will only return true if it successfully matched the whole expression. // We can special case these to do essentially nothing in Go other than emit the capture. - switch (node.Type) + switch (node.Kind) { - case RegexNode.Multi or RegexNode.Notone or RegexNode.One or RegexNode.Set when !IsCaseInsensitive(node): + case RegexNodeKind.Multi or RegexNodeKind.Notone or RegexNodeKind.One or RegexNodeKind.Set when !IsCaseInsensitive(node): // This is the case for single and multiple characters, though the whole thing is only guaranteed // to have been validated in FindFirstChar when doing case-sensitive comparison. writer.WriteLine($"int start = base.runtextpos;"); - writer.WriteLine($"int end = start + {(node.Type == RegexNode.Multi ? node.Str!.Length : 1)};"); + writer.WriteLine($"int end = start + {(node.Kind == RegexNodeKind.Multi ? node.Str!.Length : 1)};"); writer.WriteLine("base.Capture(0, start, end);"); writer.WriteLine("base.runtextpos = end;"); return requiredHelpers; - case RegexNode.Empty: + case RegexNodeKind.Empty: // This case isn't common in production, but it's very common when first getting started with the // source generator and seeing what happens as you add more to expressions. When approaching // it from a learning perspective, this is very common, as it's the empty string you start with. @@ -881,7 +924,7 @@ void TransferSliceStaticPosToPos() // Emits the code for an alternation. void EmitAlternation(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Alternate, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Alternate, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() >= 2, $"Expected at least 2 children, found {node.ChildCount()}"); int childCount = node.ChildCount(); @@ -892,7 +935,7 @@ void EmitAlternation(RegexNode node) // Both atomic and non-atomic are supported. While a parent RegexNode.Atomic node will itself // successfully prevent backtracking into this child node, we can emit better / cheaper code // for an Alternate when it is atomic, so we still take it into account here. - Debug.Assert(node.Next is not null); + Debug.Assert(node.Parent is not null); bool isAtomic = node.IsAtomicByParent(); // If no child branch overlaps with another child branch, we can emit more streamlined code @@ -916,24 +959,69 @@ void EmitAlternation(RegexNode node) } } + // Detect whether every branch begins with one or more unique characters. + const int SetCharsSize = 5; // arbitrary limit (for IgnoreCase, we want this to be at least 3 to handle the vast majority of values) + Span setChars = stackalloc char[SetCharsSize]; if (useSwitchedBranches) { + // Iterate through every branch, seeing if we can easily find a starting One, Multi, or small Set. + // If we can, extract its starting char (or multiple in the case of a set), validate that all such + // starting characters are unique relative to all the branches. var seenChars = new HashSet(); - for (int i = 0; i < childCount; i++) + for (int i = 0; i < childCount && useSwitchedBranches; i++) { - if (node.Child(i).FindBranchOneOrMultiStart() is not RegexNode oneOrMulti || - !seenChars.Add(oneOrMulti.FirstCharOfOneOrMulti())) + // If it's not a One, Multi, or Set, we can't apply this optimization. + // If it's IgnoreCase (and wasn't reduced to a non-IgnoreCase set), also ignore it to keep the logic simple. + if (node.Child(i).FindBranchOneMultiOrSetStart() is not RegexNode oneMultiOrSet || + (oneMultiOrSet.Options & RegexOptions.IgnoreCase) != 0) // TODO: https://github.com/dotnet/runtime/issues/61048 { useSwitchedBranches = false; break; } + + // If it's a One or a Multi, get the first character and add it to the set. + // If it was already in the set, we can't apply this optimization. + if (oneMultiOrSet.Kind is RegexNodeKind.One or RegexNodeKind.Multi) + { + if (!seenChars.Add(oneMultiOrSet.FirstCharOfOneOrMulti())) + { + useSwitchedBranches = false; + break; + } + } + else + { + // The branch begins with a set. Make sure it's a set of only a few characters + // and get them. If we can't, we can't apply this optimization. + Debug.Assert(oneMultiOrSet.Kind is RegexNodeKind.Set); + int numChars; + if (RegexCharClass.IsNegated(oneMultiOrSet.Str!) || + (numChars = RegexCharClass.GetSetChars(oneMultiOrSet.Str!, setChars)) == 0) + { + useSwitchedBranches = false; + break; + } + + // Check to make sure each of the chars is unique relative to all other branches examined. + foreach (char c in setChars.Slice(0, numChars)) + { + if (!seenChars.Add(c)) + { + useSwitchedBranches = false; + break; + } + } + } } } if (useSwitchedBranches) { // Note: This optimization does not exist with RegexOptions.Compiled. Here we rely on the - // C# compiler to lower the C# switch statement with appropriate optimizations. + // C# compiler to lower the C# switch statement with appropriate optimizations. In some + // cases there are enough branches that the compiler will emit a jump table. In others + // it'll optimize the order of checks in order to minimize the total number in the worst + // case. In any case, we get easier to read and reason about C#. EmitSwitchedBranches(); } else @@ -950,8 +1038,9 @@ void EmitSwitchedBranches() writer.WriteLine(); // Emit a switch statement on the first char of each branch. - using (EmitBlock(writer, $"switch ({ToLowerIfNeeded(hasTextInfo, options, $"{sliceSpan}[{sliceStaticPos++}]", IsCaseInsensitive(node))})")) + using (EmitBlock(writer, $"switch ({sliceSpan}[{sliceStaticPos++}])")) { + Span setChars = stackalloc char[SetCharsSize]; // needs to be same size as detection check in caller int startingSliceStaticPos = sliceStaticPos; // Emit a case for each branch. @@ -960,25 +1049,36 @@ void EmitSwitchedBranches() sliceStaticPos = startingSliceStaticPos; RegexNode child = node.Child(i); - Debug.Assert(child.Type is RegexNode.One or RegexNode.Multi or RegexNode.Concatenate, DescribeNode(child, rm.Code)); - Debug.Assert(child.Type is not RegexNode.Concatenate || (child.ChildCount() >= 2 && child.Child(0).Type is RegexNode.One or RegexNode.Multi)); + Debug.Assert(child.Kind is RegexNodeKind.One or RegexNodeKind.Multi or RegexNodeKind.Set or RegexNodeKind.Concatenate, DescribeNode(child, rm.Code)); + Debug.Assert(child.Kind is not RegexNodeKind.Concatenate || (child.ChildCount() >= 2 && child.Child(0).Kind is RegexNodeKind.One or RegexNodeKind.Multi or RegexNodeKind.Set)); - RegexNode? childStart = child.FindBranchOneOrMultiStart(); - Debug.Assert(childStart is not null, DescribeNode(child, rm.Code)); + RegexNode? childStart = child.FindBranchOneMultiOrSetStart(); + Debug.Assert(childStart is not null, "Unexpectedly couldn't find the branch starting node."); + Debug.Assert((childStart.Options & RegexOptions.IgnoreCase) == 0, "Expected only to find non-IgnoreCase branch starts"); - writer.WriteLine($"case {Literal(childStart.FirstCharOfOneOrMulti())}:"); + if (childStart.Kind is RegexNodeKind.Set) + { + int numChars = RegexCharClass.GetSetChars(childStart.Str!, setChars); + Debug.Assert(numChars != 0); + writer.WriteLine($"case {string.Join(" or ", setChars.Slice(0, numChars).ToArray().Select(c => Literal(c)))}:"); + } + else + { + writer.WriteLine($"case {Literal(childStart.FirstCharOfOneOrMulti())}:"); + } writer.Indent++; // Emit the code for the branch, without the first character that was already matched in the switch. - switch (child.Type) + switch (child.Kind) { - case RegexNode.Multi: + case RegexNodeKind.Multi: EmitNode(CloneMultiWithoutFirstChar(child)); + writer.WriteLine(); break; - case RegexNode.Concatenate: - var newConcat = new RegexNode(RegexNode.Concatenate, child.Options); - if (childStart.Type == RegexNode.Multi) + case RegexNodeKind.Concatenate: + var newConcat = new RegexNode(RegexNodeKind.Concatenate, child.Options); + if (childStart.Kind == RegexNodeKind.Multi) { newConcat.AddChild(CloneMultiWithoutFirstChar(childStart)); } @@ -988,16 +1088,17 @@ void EmitSwitchedBranches() newConcat.AddChild(child.Child(j)); } EmitNode(newConcat.Reduce()); + writer.WriteLine(); break; - static RegexNode CloneMultiWithoutFirstChar(RegexNode node) - { - Debug.Assert(node.Type is RegexNode.Multi); - Debug.Assert(node.Str!.Length >= 2); - return node.Str!.Length == 2 ? - new RegexNode(RegexNode.One, node.Options, node.Str![1]) : - new RegexNode(RegexNode.Multi, node.Options, node.Str!.Substring(1)); - } + static RegexNode CloneMultiWithoutFirstChar(RegexNode node) + { + Debug.Assert(node.Kind is RegexNodeKind.Multi); + Debug.Assert(node.Str!.Length >= 2); + return node.Str!.Length == 2 ? + new RegexNode(RegexNodeKind.One, node.Options, node.Str![1]) : + new RegexNode(RegexNodeKind.Multi, node.Options, node.Str!.Substring(1)); + } } // This is only ever used for atomic alternations, so we can simply reset the doneLabel @@ -1009,7 +1110,6 @@ static RegexNode CloneMultiWithoutFirstChar(RegexNode node) // Before jumping to the end, we need to zero out sliceStaticPos, so that no // matter what the value is after the branch, whatever follows the alternate // will see the same sliceStaticPos. - writer.WriteLine(); TransferSliceStaticPosToPos(); writer.WriteLine($"break;"); writer.WriteLine(); @@ -1183,7 +1283,7 @@ void EmitAllBranches() // Emits the code to handle a backreference. void EmitBackreference(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Ref, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Backreference, $"Unexpected type: {node.Kind}"); int capnum = RegexParser.MapCaptureNumber(node.M, rm.Code.Caps); @@ -1260,7 +1360,7 @@ void EmitWhenHasCapture() // Emits the code for an if(backreference)-then-else conditional. void EmitBackreferenceConditional(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Testref, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.BackreferenceConditional, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 2, $"Expected 2 children, found {node.ChildCount()}"); // We're branching in a complicated fashion. Make sure sliceStaticPos is 0. @@ -1272,7 +1372,7 @@ void EmitBackreferenceConditional(RegexNode node) // Get the "yes" branch and the "no" branch. The "no" branch is optional in syntax and is thus // somewhat likely to be Empty. RegexNode yesBranch = node.Child(0); - RegexNode? noBranch = node.Child(1) is { Type: not RegexNode.Empty } childNo ? childNo : null; + RegexNode? noBranch = node.Child(1) is { Kind: not RegexNodeKind.Empty } childNo ? childNo : null; string originalDoneLabel = doneLabel; // If the child branches might backtrack, we can't emit the branches inside constructs that @@ -1417,7 +1517,7 @@ void EmitBackreferenceConditional(RegexNode node) // Emits the code for an if(expression)-then-else conditional. void EmitExpressionConditional(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Testgroup, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.ExpressionConditional, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 3, $"Expected 3 children, found {node.ChildCount()}"); bool isAtomic = node.IsAtomicByParent(); @@ -1433,7 +1533,7 @@ void EmitExpressionConditional(RegexNode node) // Get the "yes" branch and the "no" branch. The "no" branch is optional in syntax and is thus // somewhat likely to be Empty. RegexNode yesBranch = node.Child(1); - RegexNode? noBranch = node.Child(2) is { Type: not RegexNode.Empty } childNo ? childNo : null; + RegexNode? noBranch = node.Child(2) is { Kind: not RegexNodeKind.Empty } childNo ? childNo : null; string originalDoneLabel = doneLabel; string expressionNotMatched = ReserveName("ConditionalExpressionNotMatched"); @@ -1575,7 +1675,7 @@ void EmitExpressionConditional(RegexNode node) // Emits the code for a Capture node. void EmitCapture(RegexNode node, RegexNode? subsequent = null) { - Debug.Assert(node.Type is RegexNode.Capture, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Capture, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); int capnum = RegexParser.MapCaptureNumber(node.M, rm.Code.Caps); @@ -1649,7 +1749,7 @@ void EmitCapture(RegexNode node, RegexNode? subsequent = null) // Emits the code to handle a positive lookahead assertion. void EmitPositiveLookaheadAssertion(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Require, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.PositiveLookaround, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Lookarounds are implicitly atomic. Store the original done label to reset at the end. @@ -1677,7 +1777,7 @@ void EmitPositiveLookaheadAssertion(RegexNode node) // Emits the code to handle a negative lookahead assertion. void EmitNegativeLookaheadAssertion(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Prevent, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.NegativeLookaround, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Lookarounds are implicitly atomic. Store the original done label to reset at the end. @@ -1713,15 +1813,15 @@ void EmitNegativeLookaheadAssertion(RegexNode node) static bool PossiblyBacktracks(RegexNode node) => !( // Certain nodes will never backtrack out of them - node.Type is RegexNode.Atomic or // atomic nodes by definition don't give up anything - RegexNode.Oneloopatomic or RegexNode.Notoneloopatomic or RegexNode.Setloopatomic or // same for atomic loops - RegexNode.One or RegexNode.Notone or RegexNode.Set or // individual characters don't backtrack - RegexNode.Multi or // multiple characters don't backtrack - RegexNode.Ref or // backreferences don't backtrack - RegexNode.Beginning or RegexNode.Bol or RegexNode.Start or RegexNode.End or RegexNode.EndZ or RegexNode.Eol or RegexNode.Boundary or RegexNode.NonBoundary or RegexNode.ECMABoundary or RegexNode.NonECMABoundary or // anchors don't backtrack - RegexNode.Nothing or RegexNode.Empty or RegexNode.UpdateBumpalong // empty/nothing don't do anything + node.Kind is RegexNodeKind.Atomic or // atomic nodes by definition don't give up anything + RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloopatomic or // same for atomic loops + RegexNodeKind.One or RegexNodeKind.Notone or RegexNodeKind.Set or // individual characters don't backtrack + RegexNodeKind.Multi or // multiple characters don't backtrack + RegexNodeKind.Backreference or // backreferences don't backtrack + RegexNodeKind.Beginning or RegexNodeKind.Bol or RegexNodeKind.Start or RegexNodeKind.End or RegexNodeKind.EndZ or RegexNodeKind.Eol or RegexNodeKind.Boundary or RegexNodeKind.NonBoundary or RegexNodeKind.ECMABoundary or RegexNodeKind.NonECMABoundary or // anchors don't backtrack + RegexNodeKind.Nothing or RegexNodeKind.Empty or RegexNodeKind.UpdateBumpalong // empty/nothing don't do anything // Fixed-size repeaters of single characters or atomic don't backtrack - || node.Type is RegexNode.Oneloop or RegexNode.Notoneloop or RegexNode.Setloop or RegexNode.Onelazy or RegexNode.Notonelazy or RegexNode.Setlazy && node.M == node.N + || node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop or RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy && node.M == node.N ); // Emits the code for the node. @@ -1734,25 +1834,25 @@ void EmitNode(RegexNode node, RegexNode? subsequent = null, bool emitLengthCheck } // Separate out several node types that, for conciseness, don't need a header and scope written into the source. - switch (node.Type) + switch (node.Kind) { // Nothing is written for an empty - case RegexNode.Empty: + case RegexNodeKind.Empty: return; // A match failure doesn't need a scope. - case RegexNode.Nothing: + case RegexNodeKind.Nothing: writer.WriteLine($"goto {doneLabel};"); return; // Atomic is invisible in the generated source, other than its impact on the targets of jumps - case RegexNode.Atomic: + case RegexNodeKind.Atomic: EmitAtomic(node, subsequent); return; // Concatenate is a simplification in the node tree so that a series of children can be represented as one. // We don't need its presence visible in the source. - case RegexNode.Concatenate: + case RegexNodeKind.Concatenate: EmitConcatenation(node, subsequent, emitLengthChecksIfRequired); return; } @@ -1761,94 +1861,94 @@ void EmitNode(RegexNode node, RegexNode? subsequent = null, bool emitLengthCheck // be visible outside of its scope, the scope is still emitted for clarity but is commented out. using (EmitScope(writer, DescribeNode(node, rm.Code), faux: PossiblyBacktracks(node) && !node.IsAtomicByParent())) { - switch (node.Type) + switch (node.Kind) { - case RegexNode.Beginning: - case RegexNode.Start: - case RegexNode.Bol: - case RegexNode.Eol: - case RegexNode.End: - case RegexNode.EndZ: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: EmitAnchors(node); break; - case RegexNode.Boundary: - case RegexNode.NonBoundary: - case RegexNode.ECMABoundary: - case RegexNode.NonECMABoundary: + case RegexNodeKind.Boundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.NonECMABoundary: EmitBoundary(node); break; - case RegexNode.Multi: + case RegexNodeKind.Multi: EmitMultiChar(node, emitLengthChecksIfRequired); break; - case RegexNode.One: - case RegexNode.Notone: - case RegexNode.Set: + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: EmitSingleChar(node, emitLengthChecksIfRequired); break; - case RegexNode.Oneloop: - case RegexNode.Notoneloop: - case RegexNode.Setloop: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Setloop: EmitSingleCharLoop(node, subsequent, emitLengthChecksIfRequired); break; - case RegexNode.Onelazy: - case RegexNode.Notonelazy: - case RegexNode.Setlazy: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Setlazy: EmitSingleCharLazy(node, subsequent, emitLengthChecksIfRequired); break; - case RegexNode.Oneloopatomic: - case RegexNode.Notoneloopatomic: - case RegexNode.Setloopatomic: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Setloopatomic: EmitSingleCharAtomicLoop(node, emitLengthChecksIfRequired); break; - case RegexNode.Loop: + case RegexNodeKind.Loop: EmitLoop(node); break; - case RegexNode.Lazyloop: + case RegexNodeKind.Lazyloop: EmitLazy(node); break; - case RegexNode.Alternate: + case RegexNodeKind.Alternate: EmitAlternation(node); break; - case RegexNode.Ref: + case RegexNodeKind.Backreference: EmitBackreference(node); break; - case RegexNode.Testref: + case RegexNodeKind.BackreferenceConditional: EmitBackreferenceConditional(node); break; - case RegexNode.Testgroup: + case RegexNodeKind.ExpressionConditional: EmitExpressionConditional(node); break; - case RegexNode.Capture: + case RegexNodeKind.Capture: EmitCapture(node, subsequent); break; - case RegexNode.Require: + case RegexNodeKind.PositiveLookaround: EmitPositiveLookaheadAssertion(node); break; - case RegexNode.Prevent: + case RegexNodeKind.NegativeLookaround: EmitNegativeLookaheadAssertion(node); break; - case RegexNode.UpdateBumpalong: + case RegexNodeKind.UpdateBumpalong: EmitUpdateBumpalong(node); break; default: - Debug.Fail($"Unexpected node type: {node.Type}"); + Debug.Fail($"Unexpected node type: {node.Kind}"); break; } } @@ -1857,7 +1957,7 @@ void EmitNode(RegexNode node, RegexNode? subsequent = null, bool emitLengthCheck // Emits the node for an atomic. void EmitAtomic(RegexNode node, RegexNode? subsequent) { - Debug.Assert(node.Type is RegexNode.Atomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Atomic, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Atomic simply outputs the code for the child, but it ensures that any done label left @@ -1873,7 +1973,7 @@ void EmitAtomic(RegexNode node, RegexNode? subsequent) // it should bump from this location rather than from the original location. void EmitUpdateBumpalong(RegexNode node) { - Debug.Assert(node.Type is RegexNode.UpdateBumpalong, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.UpdateBumpalong, $"Unexpected type: {node.Kind}"); TransferSliceStaticPosToPos(); using (EmitBlock(writer, "if (base.runtextpos < pos)")) @@ -1885,7 +1985,7 @@ void EmitUpdateBumpalong(RegexNode node) // Emits code for a concatenation void EmitConcatenation(RegexNode node, RegexNode? subsequent, bool emitLengthChecksIfRequired) { - Debug.Assert(node.Type is RegexNode.Concatenate, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Concatenate, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() >= 2, $"Expected at least 2 children, found {node.ChildCount()}"); // Emit the code for each child one after the other. @@ -1922,13 +2022,13 @@ void WriteSingleCharChild(RegexNode child, bool includeDescription = true) } RegexNode child = node.Child(i); - if (child.Type is RegexNode.One or RegexNode.Notone or RegexNode.Set) + if (child.Kind is RegexNodeKind.One or RegexNodeKind.Notone or RegexNodeKind.Set) { WriteSingleCharChild(child); } - else if (child.Type is RegexNode.Oneloop or RegexNode.Onelazy or RegexNode.Oneloopatomic or - RegexNode.Setloop or RegexNode.Setlazy or RegexNode.Setloopatomic or - RegexNode.Notoneloop or RegexNode.Notonelazy or RegexNode.Notoneloopatomic && + else if (child.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Onelazy or RegexNodeKind.Oneloopatomic or + RegexNodeKind.Setloop or RegexNodeKind.Setlazy or RegexNodeKind.Setloopatomic or + RegexNodeKind.Notoneloop or RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloopatomic && child.M == child.N && child.M <= MaxUnrollSize) { @@ -1989,7 +2089,7 @@ RegexNode.Notoneloop or RegexNode.Notonelazy or RegexNode.Notoneloopatomic && for (int i = index + 1; i < childCount; i++) { RegexNode next = node.Child(i); - if (next.Type is not RegexNode.UpdateBumpalong) // skip node types that don't have a semantic impact + if (next.Kind is not RegexNodeKind.UpdateBumpalong) // skip node types that don't have a semantic impact { return next; } @@ -2002,7 +2102,7 @@ RegexNode.Notoneloop or RegexNode.Notonelazy or RegexNode.Notoneloopatomic && // Emits the code to handle a single-character match. void EmitSingleChar(RegexNode node, bool emitLengthCheck = true, string? offset = null, bool clauseOnly = false) { - Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Type}"); + Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Kind}"); // This only emits a single check, but it's called from the looping constructs in a loop // to generate the code for a single check, so we map those looping constructs to the @@ -2038,13 +2138,13 @@ void EmitSingleChar(RegexNode node, bool emitLengthCheck = true, string? offset // Emits the code to handle a boundary check on a character. void EmitBoundary(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Boundary or RegexNode.NonBoundary or RegexNode.ECMABoundary or RegexNode.NonECMABoundary, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Boundary or RegexNodeKind.NonBoundary or RegexNodeKind.ECMABoundary or RegexNodeKind.NonECMABoundary, $"Unexpected type: {node.Kind}"); - string call = node.Type switch + string call = node.Kind switch { - RegexNode.Boundary => "!base.IsBoundary", - RegexNode.NonBoundary => "base.IsBoundary", - RegexNode.ECMABoundary => "!base.IsECMABoundary", + RegexNodeKind.Boundary => "!base.IsBoundary", + RegexNodeKind.NonBoundary => "base.IsBoundary", + RegexNodeKind.ECMABoundary => "!base.IsECMABoundary", _ => "base.IsECMABoundary", }; @@ -2057,13 +2157,13 @@ void EmitBoundary(RegexNode node) // Emits the code to handle various anchors. void EmitAnchors(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Beginning or RegexNode.Start or RegexNode.Bol or RegexNode.End or RegexNode.EndZ or RegexNode.Eol, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Beginning or RegexNodeKind.Start or RegexNodeKind.Bol or RegexNodeKind.End or RegexNodeKind.EndZ or RegexNodeKind.Eol, $"Unexpected type: {node.Kind}"); Debug.Assert(sliceStaticPos >= 0); - switch (node.Type) + switch (node.Kind) { - case RegexNode.Beginning: - case RegexNode.Start: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: if (sliceStaticPos > 0) { // If we statically know we've already matched part of the regex, there's no way we're at the @@ -2072,15 +2172,15 @@ void EmitAnchors(RegexNode node) } else { - additionalDeclarations.Add(node.Type == RegexNode.Beginning ? "int beginning = base.runtextbeg;" : "int start = base.runtextstart;"); - using (EmitBlock(writer, node.Type == RegexNode.Beginning ? "if (pos != beginning)" : "if (pos != start)")) + additionalDeclarations.Add(node.Kind == RegexNodeKind.Beginning ? "int beginning = base.runtextbeg;" : "int start = base.runtextstart;"); + using (EmitBlock(writer, node.Kind == RegexNodeKind.Beginning ? "if (pos != beginning)" : "if (pos != start)")) { writer.WriteLine($"goto {doneLabel};"); } } break; - case RegexNode.Bol: + case RegexNodeKind.Bol: if (sliceStaticPos > 0) { using (EmitBlock(writer, $"if ({sliceSpan}[{sliceStaticPos - 1}] != '\\n')")) @@ -2099,14 +2199,14 @@ void EmitAnchors(RegexNode node) } break; - case RegexNode.End: + case RegexNodeKind.End: using (EmitBlock(writer, $"if ({IsSliceLengthGreaterThanSliceStaticPos()})")) { writer.WriteLine($"goto {doneLabel};"); } break; - case RegexNode.EndZ: + case RegexNodeKind.EndZ: writer.WriteLine($"if ({sliceSpan}.Length > {sliceStaticPos + 1} || ({IsSliceLengthGreaterThanSliceStaticPos()} && {sliceSpan}[{sliceStaticPos}] != '\\n'))"); using (EmitBlock(writer, null)) { @@ -2114,7 +2214,7 @@ void EmitAnchors(RegexNode node) } break; - case RegexNode.Eol: + case RegexNodeKind.Eol: using (EmitBlock(writer, $"if ({IsSliceLengthGreaterThanSliceStaticPos()} && {sliceSpan}[{sliceStaticPos}] != '\\n')")) { writer.WriteLine($"goto {doneLabel};"); @@ -2130,7 +2230,7 @@ string IsSliceLengthGreaterThanSliceStaticPos() => // Emits the code to handle a multiple-character match. void EmitMultiChar(RegexNode node, bool emitLengthCheck = true) { - Debug.Assert(node.Type is RegexNode.Multi, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Multi, $"Unexpected type: {node.Kind}"); bool caseInsensitive = IsCaseInsensitive(node); @@ -2240,7 +2340,7 @@ void EmitOr() void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Notoneloop or RegexNode.Setloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop, $"Unexpected type: {node.Kind}"); // If this is actually a repeater, emit that instead; no backtracking necessary. if (node.M == node.N) @@ -2291,12 +2391,18 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL EmitStackPop(endingPos, startingPos); writer.WriteLine(); - if (subsequent?.FindStartingCharacterOrString() is ValueTuple literal) + if (subsequent?.FindStartingLiteral() is ValueTuple literal) { writer.WriteLine($"if ({startingPos} >= {endingPos} ||"); - using (EmitBlock(writer, literal.Item2 is not null ? - $" ({endingPos} = global::System.MemoryExtensions.LastIndexOf(inputSpan.Slice({startingPos}, global::System.Math.Min(inputSpan.Length, {endingPos} + {literal.Item2.Length - 1}) - {startingPos}), {Literal(literal.Item2)})) < 0)" : - $" ({endingPos} = global::System.MemoryExtensions.LastIndexOf(inputSpan.Slice({startingPos}, {endingPos} - {startingPos}), {Literal(literal.Item1)})) < 0)")) + using (EmitBlock(writer, + literal.Item2 is not null ? $" ({endingPos} = global::System.MemoryExtensions.LastIndexOf(inputSpan.Slice({startingPos}, global::System.Math.Min(inputSpan.Length, {endingPos} + {literal.Item2.Length - 1}) - {startingPos}), {Literal(literal.Item2)})) < 0)" : + literal.Item3 is null ? $" ({endingPos} = global::System.MemoryExtensions.LastIndexOf(inputSpan.Slice({startingPos}, {endingPos} - {startingPos}), {Literal(literal.Item1)})) < 0)" : + literal.Item3.Length switch + { + 2 => $" ({endingPos} = global::System.MemoryExtensions.LastIndexOfAny(inputSpan.Slice({startingPos}, {endingPos} - {startingPos}), {Literal(literal.Item3[0])}, {Literal(literal.Item3[1])})) < 0)", + 3 => $" ({endingPos} = global::System.MemoryExtensions.LastIndexOfAny(inputSpan.Slice({startingPos}, {endingPos} - {startingPos}), {Literal(literal.Item3[0])}, {Literal(literal.Item3[1])}, {Literal(literal.Item3[2])})) < 0)", + _ => $" ({endingPos} = global::System.MemoryExtensions.LastIndexOfAny(inputSpan.Slice({startingPos}, {endingPos} - {startingPos}), {Literal(literal.Item3)})) < 0)", + })) { writer.WriteLine($"goto {doneLabel};"); } @@ -2325,7 +2431,7 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL void EmitSingleCharLazy(RegexNode node, RegexNode? subsequent = null, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.Type is RegexNode.Onelazy or RegexNode.Notonelazy or RegexNode.Setlazy, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy, $"Unexpected type: {node.Kind}"); // Emit the min iterations as a repeater. Any failures here don't necessitate backtracking, // as the lazy itself failed to match, and there's no backtracking possible by the individual @@ -2414,16 +2520,23 @@ void EmitSingleCharLazy(RegexNode node, RegexNode? subsequent = null, bool emitL // Now that we've appropriately advanced by one character and are set for what comes after the loop, // see if we can skip ahead more iterations by doing a search for a following literal. if (iterationCount is null && - node.Type is RegexNode.Notonelazy && + node.Kind is RegexNodeKind.Notonelazy && !IsCaseInsensitive(node) && - subsequent?.FindStartingCharacterOrString() is ValueTuple literal && - (literal.Item2?[0] ?? literal.Item1) != node.Ch) + subsequent?.FindStartingLiteral(4) is ValueTuple literal && // 5 == max optimized by IndexOfAny, and we need to reserve 1 for node.Ch + (literal.Item3 is not null ? !literal.Item3.Contains(node.Ch) : (literal.Item2?[0] ?? literal.Item1) != node.Ch)) // no overlap between node.Ch and the start of the literal { // e.g. "<[^>]*?>" // This lazy loop will consume all characters other than node.Ch until the subsequent literal. // We can implement it to search for either that char or the literal, whichever comes first. // If it ends up being that node.Ch, the loop fails (we're only here if we're backtracking). - writer.WriteLine($"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(node.Ch)}, {Literal(literal.Item2?[0] ?? literal.Item1)});"); + writer.WriteLine( + literal.Item2 is not null ? $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(node.Ch)}, {Literal(literal.Item2[0])});" : + literal.Item3 is null ? $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(node.Ch)}, {Literal(literal.Item1)});" : + literal.Item3.Length switch + { + 2 => $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(node.Ch)}, {Literal(literal.Item3[0])}, {Literal(literal.Item3[1])});", + _ => $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(node.Ch + literal.Item3)});", + }); using (EmitBlock(writer, $"if ((uint){startingPos} >= (uint){sliceSpan}.Length || {sliceSpan}[{startingPos}] == {Literal(node.Ch)})")) { writer.WriteLine($"goto {doneLabel};"); @@ -2432,14 +2545,22 @@ node.Type is RegexNode.Notonelazy && SliceInputSpan(writer); } else if (iterationCount is null && - node.Type is RegexNode.Setlazy && + node.Kind is RegexNodeKind.Setlazy && node.Str == RegexCharClass.AnyClass && - subsequent?.FindStartingCharacterOrString() is ValueTuple literal2) + subsequent?.FindStartingLiteral() is ValueTuple literal2) { // e.g. ".*?string" with RegexOptions.Singleline // This lazy loop will consume all characters until the subsequent literal. If the subsequent literal // isn't found, the loop fails. We can implement it to just search for that literal. - writer.WriteLine($"{startingPos} = global::System.MemoryExtensions.IndexOf({sliceSpan}, {(literal2.Item2 is not null ? Literal(literal2.Item2) : Literal(literal2.Item1))});"); + writer.WriteLine( + literal2.Item2 is not null ? $"{startingPos} = global::System.MemoryExtensions.IndexOf({sliceSpan}, {Literal(literal2.Item2)});" : + literal2.Item3 is null ? $"{startingPos} = global::System.MemoryExtensions.IndexOf({sliceSpan}, {Literal(literal2.Item1)});" : + literal2.Item3.Length switch + { + 2 => $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(literal2.Item3[0])}, {Literal(literal2.Item3[1])});", + 3 => $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(literal2.Item3[0])}, {Literal(literal2.Item3[1])}, {Literal(literal2.Item3[2])});", + _ => $"{startingPos} = global::System.MemoryExtensions.IndexOfAny({sliceSpan}, {Literal(literal2.Item3)});", + }); using (EmitBlock(writer, $"if ({startingPos} < 0)")) { writer.WriteLine($"goto {doneLabel};"); @@ -2502,7 +2623,7 @@ node.Type is RegexNode.Setlazy && void EmitLazy(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Lazyloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Lazyloop, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M < int.MaxValue, $"Unexpected M={node.M}"); Debug.Assert(node.N >= node.M, $"Unexpected M={node.M}, N={node.N}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); @@ -2687,7 +2808,7 @@ void EmitLazy(RegexNode node) // RegexNode.M is used for the number of iterations; RegexNode.N is ignored. void EmitSingleCharFixedRepeater(RegexNode node, bool emitLengthCheck = true) { - Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Type}"); + Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Kind}"); int iterations = node.M; if (iterations == 0) @@ -2753,7 +2874,7 @@ void EmitSingleCharFixedRepeater(RegexNode node, bool emitLengthCheck = true) // Emits the code to handle a non-backtracking, variable-length loop around a single character comparison. void EmitSingleCharAtomicLoop(RegexNode node, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Notoneloop or RegexNode.Notoneloopatomic or RegexNode.Setloop or RegexNode.Setloopatomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic, $"Unexpected type: {node.Kind}"); // If this is actually a repeater, emit that instead. if (node.M == node.N) @@ -2896,7 +3017,7 @@ void EmitSingleCharAtomicLoop(RegexNode node, bool emitLengthChecksIfRequired = // Emits the code to handle a non-backtracking optional zero-or-one loop. void EmitAtomicSingleCharZeroOrOne(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Notoneloop or RegexNode.Notoneloopatomic or RegexNode.Setloop or RegexNode.Setloopatomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M == 0 && node.N == 1); string expr = $"{sliceSpan}[{sliceStaticPos}]"; @@ -2920,7 +3041,7 @@ void EmitAtomicSingleCharZeroOrOne(RegexNode node) void EmitLoop(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Loop or RegexNode.Lazyloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M < int.MaxValue, $"Unexpected M={node.M}"); Debug.Assert(node.N >= node.M, $"Unexpected M={node.M}, N={node.N}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); @@ -3232,9 +3353,9 @@ private static bool EmitInitializeCultureForGoIfNecessary(IndentedTextWriter wri if (!needsCulture) { int[] codes = rm.Code.Codes; - for (int codepos = 0; codepos < codes.Length; codepos += RegexCode.OpcodeSize(codes[codepos])) + for (int codepos = 0; codepos < codes.Length; codepos += RegexCode.OpcodeSize((RegexOpcode)codes[codepos])) { - if ((codes[codepos] & RegexCode.Ci) == RegexCode.Ci) + if (((RegexOpcode)codes[codepos] & RegexOpcode.CaseInsensitive) == RegexOpcode.CaseInsensitive) { needsCulture = true; break; @@ -3508,41 +3629,41 @@ private static string Literal(RegexOptions options) /// Gets a textual description of the node fit for rendering in a comment in source. private static string DescribeNode(RegexNode node, RegexCode regexCode) => - node.Type switch - { - RegexNode.Alternate => $"Match with {node.ChildCount()} alternative expressions{(node.IsAtomicByParent() ? ", atomically" : "")}.", - RegexNode.Atomic => $"Atomic group.", - RegexNode.Beginning => "Match if at the beginning of the string.", - RegexNode.Bol => "Match if at the beginning of a line.", - RegexNode.Boundary => $"Match if at a word boundary.", - RegexNode.Capture when node.M == -1 && node.N != -1 => $"Non-capturing balancing group. Uncaptures the {DescribeCapture(node.N, regexCode)}.", - RegexNode.Capture when node.N != -1 => $"Balancing group. Captures the {DescribeCapture(node.M, regexCode)} and uncaptures the {DescribeCapture(node.N, regexCode)}.", - RegexNode.Capture when node.N == -1 => $"{DescribeCapture(node.M, regexCode)}.", - RegexNode.Concatenate => "Match a sequence of expressions.", - RegexNode.ECMABoundary => $"Match if at a word boundary (according to ECMAScript rules).", - RegexNode.Empty => $"Match an empty string.", - RegexNode.End => "Match if at the end of the string.", - RegexNode.EndZ => "Match if at the end of the string or if before an ending newline.", - RegexNode.Eol => "Match if at the end of a line.", - RegexNode.Loop or RegexNode.Lazyloop => node.M == 0 && node.N == 1 ? $"Optional ({(node.Type is RegexNode.Loop ? "greedy" : "lazy")})." : $"Loop {DescribeLoop(node)}.", - RegexNode.Multi => $"Match the string {Literal(node.Str!)}.", - RegexNode.NonBoundary => $"Match if at anything other than a word boundary.", - RegexNode.NonECMABoundary => $"Match if at anything other than a word boundary (according to ECMAScript rules).", - RegexNode.Nothing => $"Fail to match.", - RegexNode.Notone => $"Match any character other than {Literal(node.Ch)}.", - RegexNode.Notoneloop or RegexNode.Notoneloopatomic or RegexNode.Notonelazy => $"Match a character other than {Literal(node.Ch)} {DescribeLoop(node)}.", - RegexNode.One => $"Match {Literal(node.Ch)}.", - RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Onelazy => $"Match {Literal(node.Ch)} {DescribeLoop(node)}.", - RegexNode.Prevent => $"Zero-width negative lookahead assertion.", - RegexNode.Ref => $"Match the same text as matched by the {DescribeCapture(node.M, regexCode)}.", - RegexNode.Require => $"Zero-width positive lookahead assertion.", - RegexNode.Set => $"Match {DescribeSet(node.Str!)}.", - RegexNode.Setloop or RegexNode.Setloopatomic or RegexNode.Setlazy => $"Match {DescribeSet(node.Str!)} {DescribeLoop(node)}.", - RegexNode.Start => "Match if at the start position.", - RegexNode.Testgroup => $"Conditionally match one of two expressions depending on whether an initial expression matches.", - RegexNode.Testref => $"Conditionally match one of two expressions depending on whether the {DescribeCapture(node.M, regexCode)} matched.", - RegexNode.UpdateBumpalong => $"Advance the next matching position.", - _ => $"Unknown node type {node.Type}", + node.Kind switch + { + RegexNodeKind.Alternate => $"Match with {node.ChildCount()} alternative expressions{(node.IsAtomicByParent() ? ", atomically" : "")}.", + RegexNodeKind.Atomic => $"Atomic group.", + RegexNodeKind.Beginning => "Match if at the beginning of the string.", + RegexNodeKind.Bol => "Match if at the beginning of a line.", + RegexNodeKind.Boundary => $"Match if at a word boundary.", + RegexNodeKind.Capture when node.M == -1 && node.N != -1 => $"Non-capturing balancing group. Uncaptures the {DescribeCapture(node.N, regexCode)}.", + RegexNodeKind.Capture when node.N != -1 => $"Balancing group. Captures the {DescribeCapture(node.M, regexCode)} and uncaptures the {DescribeCapture(node.N, regexCode)}.", + RegexNodeKind.Capture when node.N == -1 => $"{DescribeCapture(node.M, regexCode)}.", + RegexNodeKind.Concatenate => "Match a sequence of expressions.", + RegexNodeKind.ECMABoundary => $"Match if at a word boundary (according to ECMAScript rules).", + RegexNodeKind.Empty => $"Match an empty string.", + RegexNodeKind.End => "Match if at the end of the string.", + RegexNodeKind.EndZ => "Match if at the end of the string or if before an ending newline.", + RegexNodeKind.Eol => "Match if at the end of a line.", + RegexNodeKind.Loop or RegexNodeKind.Lazyloop => node.M == 0 && node.N == 1 ? $"Optional ({(node.Kind is RegexNodeKind.Loop ? "greedy" : "lazy")})." : $"Loop {DescribeLoop(node)}.", + RegexNodeKind.Multi => $"Match the string {Literal(node.Str!)}.", + RegexNodeKind.NonBoundary => $"Match if at anything other than a word boundary.", + RegexNodeKind.NonECMABoundary => $"Match if at anything other than a word boundary (according to ECMAScript rules).", + RegexNodeKind.Nothing => $"Fail to match.", + RegexNodeKind.Notone => $"Match any character other than {Literal(node.Ch)}.", + RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy => $"Match a character other than {Literal(node.Ch)} {DescribeLoop(node)}.", + RegexNodeKind.One => $"Match {Literal(node.Ch)}.", + RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy => $"Match {Literal(node.Ch)} {DescribeLoop(node)}.", + RegexNodeKind.NegativeLookaround => $"Zero-width negative lookahead assertion.", + RegexNodeKind.Backreference => $"Match the same text as matched by the {DescribeCapture(node.M, regexCode)}.", + RegexNodeKind.PositiveLookaround => $"Zero-width positive lookahead assertion.", + RegexNodeKind.Set => $"Match {DescribeSet(node.Str!)}.", + RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy => $"Match {DescribeSet(node.Str!)} {DescribeLoop(node)}.", + RegexNodeKind.Start => "Match if at the start position.", + RegexNodeKind.ExpressionConditional => $"Conditionally match one of two expressions depending on whether an initial expression matches.", + RegexNodeKind.BackreferenceConditional => $"Conditionally match one of two expressions depending on whether the {DescribeCapture(node.M, regexCode)} matched.", + RegexNodeKind.UpdateBumpalong => $"Advance the next matching position.", + _ => $"Unknown node type {node.Kind}", }; /// Gets an identifer to describe a capture group. @@ -3589,7 +3710,7 @@ private static string DescribeSet(string charClass) => RegexCharClass.NotWordClass => "any character other than a word character", RegexCharClass.SpaceClass => "a whitespace character", RegexCharClass.WordClass => "a word character", - _ => $"a character in the set {RegexCharClass.SetDescription(charClass)}", + _ => $"a character in the set {RegexCharClass.DescribeSet(charClass)}", }; /// Writes a textual description of the node tree fit for rending in source. @@ -3600,14 +3721,14 @@ private static string DescribeSet(string charClass) => /// The depth of the current node. private static void DescribeExpression(TextWriter writer, RegexNode node, string prefix, RegexCode regexCode, int depth = 0) { - bool skip = node.Type switch + bool skip = node.Kind switch { // For concatenations, flatten the contents into the parent, but only if the parent isn't a form of alternation, // where each branch is considered to be independent rather than a concatenation. - RegexNode.Concatenate when node.Next is not { Type: RegexNode.Alternate or RegexNode.Testref or RegexNode.Testgroup } => true, + RegexNodeKind.Concatenate when node.Parent is not { Kind: RegexNodeKind.Alternate or RegexNodeKind.BackreferenceConditional or RegexNodeKind.ExpressionConditional } => true, // For atomic, skip the node if we'll instead render the atomic label as part of rendering the child. - RegexNode.Atomic when node.Child(0).Type is RegexNode.Loop or RegexNode.Lazyloop or RegexNode.Alternate => true, + RegexNodeKind.Atomic when node.Child(0).Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop or RegexNodeKind.Alternate => true, // Don't skip anything else. _ => false, @@ -3615,14 +3736,14 @@ RegexNode.Atomic when node.Child(0).Type is RegexNode.Loop or RegexNode.Lazyloop if (!skip) { - string tag = node.Next?.Type switch + string tag = node.Parent?.Kind switch { - RegexNode.Testgroup when node.Next.Child(0) == node => "Condition: ", - RegexNode.Testgroup when node.Next.Child(1) == node => "Matched: ", - RegexNode.Testgroup when node.Next.Child(2) == node => "Not Matched: ", + RegexNodeKind.ExpressionConditional when node.Parent.Child(0) == node => "Condition: ", + RegexNodeKind.ExpressionConditional when node.Parent.Child(1) == node => "Matched: ", + RegexNodeKind.ExpressionConditional when node.Parent.Child(2) == node => "Not Matched: ", - RegexNode.Testref when node.Next.Child(0) == node => "Matched: ", - RegexNode.Testref when node.Next.Child(1) == node => "Not Matched: ", + RegexNodeKind.BackreferenceConditional when node.Parent.Child(0) == node => "Matched: ", + RegexNodeKind.BackreferenceConditional when node.Parent.Child(1) == node => "Not Matched: ", _ => "", }; @@ -3644,13 +3765,13 @@ RegexNode.Testref when node.Next.Child(1) == node => "Not Matched: ", /// Gets a textual description of a loop's style and bounds. private static string DescribeLoop(RegexNode node) { - string style = node.Type switch + string style = node.Kind switch { _ when node.M == node.N => "exactly", - RegexNode.Oneloopatomic or RegexNode.Notoneloopatomic or RegexNode.Setloopatomic => "atomically", - RegexNode.Oneloop or RegexNode.Notoneloop or RegexNode.Setloop => "greedily", - RegexNode.Onelazy or RegexNode.Notonelazy or RegexNode.Setlazy => "lazily", - RegexNode.Loop => node.IsAtomicByParent() ? "greedily and atomically" : "greedily", + RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloopatomic => "atomically", + RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop => "greedily", + RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy => "lazily", + RegexNodeKind.Loop => node.IsAtomicByParent() ? "greedily and atomically" : "greedily", _ /* RegexNode.Lazy */ => node.IsAtomicByParent() ? "lazily and atomically" : "lazily", }; diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs index f5651fdf169c1..a7ba253ee2c92 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs @@ -150,19 +150,16 @@ private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => // Validate the options const RegexOptions SupportedOptions = - RegexOptions.IgnoreCase | - RegexOptions.Multiline | - RegexOptions.ExplicitCapture | RegexOptions.Compiled | - RegexOptions.Singleline | + RegexOptions.CultureInvariant | + RegexOptions.ECMAScript | + RegexOptions.ExplicitCapture | + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | + RegexOptions.Multiline | + RegexOptions.NonBacktracking | RegexOptions.RightToLeft | -#if DEBUG - RegexOptions.Debug | -#endif - RegexOptions.ECMAScript | - RegexOptions.CultureInvariant | - RegexOptions.NonBacktracking; + RegexOptions.Singleline; if ((regexOptions & ~SupportedOptions) != 0) { return Diagnostic.Create(DiagnosticDescriptors.InvalidRegexArguments, methodSyntax.GetLocation(), "options"); diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/Strings.resx b/src/libraries/System.Text.RegularExpressions/gen/Resources/Strings.resx index 2ce09c60fb6e5..e55d4cc47ba30 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/Strings.resx +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/Strings.resx @@ -155,9 +155,6 @@ Destination array is not long enough to copy all the items in the collection. Check array index and length. - - The array cannot contain null elements. - Cannot include class \\{0} in character range. @@ -241,9 +238,6 @@ Collection is read-only. - - This operation is only allowed once per object. - This platform does not support writing compiled regular expressions to an assembly. @@ -289,9 +283,6 @@ Alternation has a reference to undefined group. - - Unexpected opcode in regular expression generation: {0}. - Unknown property '{0}'. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.cs.xlf index 3907e73e7ca2b..c2968a5143106 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.cs.xlf @@ -47,11 +47,6 @@ Cílové pole není dostatečně dlouhé, aby bylo možné zkopírovat všechny položky v kolekci. Zkontrolujte index a délku pole. - - The array cannot contain null elements. - Pole nemůže obsahovat elementy null. - - Start index cannot be less than 0 or greater than input length. Počáteční index nemůže být menší než nula nebo větší než délka vstupu. @@ -212,11 +207,6 @@ Kolekce je jen pro čtení. - - This operation is only allowed once per object. - Tuto operaci lze na objektu provést pouze jednou. - - This platform does not support writing compiled regular expressions to an assembly. Tato platforma nepodporuje zápis zkompilovaných regulárních výrazů do sestavení. @@ -292,11 +282,6 @@ Znak \\ na konci vzorku je neplatný. - - Unexpected opcode in regular expression generation: {0}. - Při generování regulárního výrazu byl nalezen neočekávaný operační kód: {0}. - - Unrecognized control character. Nerozpoznaný řídicí znak. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.de.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.de.xlf index 67beed526576d..9f5482f421bcc 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.de.xlf @@ -47,11 +47,6 @@ Das Zielarray ist nicht lang genug, um alle Elemente in der Sammlung zu kopieren. Prüfen Sie den Index und die Länge des Arrays. - - The array cannot contain null elements. - Das Array kann keine NULL-Elemente enthalten. - - Start index cannot be less than 0 or greater than input length. Der Startindex darf nicht kleiner als 0 oder größer als die Eingabelänge sein. @@ -212,11 +207,6 @@ Die Sammlung ist schreibgeschützt. - - This operation is only allowed once per object. - Dieser Vorgang ist pro Objekt nur einmal zulässig. - - This platform does not support writing compiled regular expressions to an assembly. Diese Plattform unterstützt das Schreiben kompilierter regulärer Ausdrücke in eine Assembly nicht. @@ -292,11 +282,6 @@ Unzulässiger \\ am Ende des Musters. - - Unexpected opcode in regular expression generation: {0}. - Unerwarteter "opcode" bei Generierung von regulärem Ausdruck: {0}. - - Unrecognized control character. Unbekanntes Steuerzeichen. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.es.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.es.xlf index e97ec8feaf1b2..1f47b5de7d226 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.es.xlf @@ -47,11 +47,6 @@ La matriz de destino no es lo suficientemente larga para copiar todos los elementos de la colección. Compruebe el índice y la longitud de la matriz. - - The array cannot contain null elements. - La matriz no puede contener elementos null. - - Start index cannot be less than 0 or greater than input length. El índice inicial no puede ser inferior a 0 ni superior a la longitud de entrada. @@ -212,11 +207,6 @@ La colección es de sólo lectura. - - This operation is only allowed once per object. - Esta operación sólo se permite una vez por cada objeto. - - This platform does not support writing compiled regular expressions to an assembly. Esta plataforma no admite la escritura de expresiones regulares compiladas en un ensamblado. @@ -292,11 +282,6 @@ \\ no válido al final del patrón. - - Unexpected opcode in regular expression generation: {0}. - Código de operación inesperado en la generación de expresión regular: {0}. - - Unrecognized control character. Carácter de control no reconocido. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.fr.xlf index 16efb2d977b0e..aa03be1e1cd02 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.fr.xlf @@ -47,11 +47,6 @@ La taille du tableau de destination ne permet pas de copier tous les éléments de la collection. Vérifiez l'index et la longueur du tableau. - - The array cannot contain null elements. - Le tableau ne peut pas contenir d'éléments null. - - Start index cannot be less than 0 or greater than input length. L'index de début ne peut pas être inférieur à 0 ou supérieur à la longueur d'entrée. @@ -212,11 +207,6 @@ La collection est en lecture seule. - - This operation is only allowed once per object. - Cette opération n'est autorisée qu'une fois par objet. - - This platform does not support writing compiled regular expressions to an assembly. Cette plateforme ne prend pas en charge l’écriture d’expressions régulières compilées dans un assembly. @@ -292,11 +282,6 @@ \\ non conforme à la fin du modèle. - - Unexpected opcode in regular expression generation: {0}. - opcode inattendu dans la génération d'expressions régulières : {0}. - - Unrecognized control character. Caractère de contrôle non reconnu. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.it.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.it.xlf index f7d730755b846..b92ba1bea7564 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.it.xlf @@ -47,11 +47,6 @@ La lunghezza della matrice di destinazione non è sufficiente per copiare tutti gli elementi della raccolta. Controllare l'indice e la lunghezza della matrice. - - The array cannot contain null elements. - La matrice non può contenere elementi Null. - - Start index cannot be less than 0 or greater than input length. L'indirizzo di inizio non può essere minore di zero o maggiore della lunghezza di input. @@ -212,11 +207,6 @@ La raccolta è di sola lettura. - - This operation is only allowed once per object. - Questa operazione può essere eseguita una sola volta per oggetto. - - This platform does not support writing compiled regular expressions to an assembly. Questa piattaforma non supporta la scrittura di espressioni regolari compilate in un assembly. @@ -292,11 +282,6 @@ Carattere \\ non valido alla fine del criterio. - - Unexpected opcode in regular expression generation: {0}. - Codice operativo imprevisto nella generazione dell'espressione regolare: {0}. - - Unrecognized control character. Carattere di controllo non riconosciuto. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ja.xlf index f14f085a8f42c..91c211945afbe 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ja.xlf @@ -47,11 +47,6 @@ ターゲット配列の長さが不足しているため、コレクション内のすべての項目をコピーできません。配列のインデックスと長さをご確認ください。 - - The array cannot contain null elements. - 配列に null 要素を含めることはできません。 - - Start index cannot be less than 0 or greater than input length. 開始インデックスに 0 より小さい値または入力長より大きい値を指定することはできません。 @@ -212,11 +207,6 @@ コレクションは読み取り専用です。 - - This operation is only allowed once per object. - この操作は、オブジェクトに付き 1 回のみ実行できます。 - - This platform does not support writing compiled regular expressions to an assembly. このプラットフォームでは、コンパイルされた正規表現をアセンブリに書き込むことはサポートされていません。 @@ -292,11 +282,6 @@ パターンの末尾に無効な \\ があります。 - - Unexpected opcode in regular expression generation: {0}. - 正規表現の生成中に予期しない Opcode: {0} が発生しました。 - - Unrecognized control character. 認識されない制御文字です。 diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ko.xlf index 618b1067b0eba..1c8f8666d267a 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ko.xlf @@ -47,11 +47,6 @@ 대상 배열이 컬렉션의 모든 항목을 복사하기에 충분히 길지 않습니다. 배열 인덱스와 길이를 확인하세요. - - The array cannot contain null elements. - 배열에는 null 요소가 포함될 수 없습니다. - - Start index cannot be less than 0 or greater than input length. 시작 인덱스는 0보다 작거나 입력 길이보다 클 수 없습니다. @@ -212,11 +207,6 @@ 읽기 전용 컬렉션입니다. - - This operation is only allowed once per object. - 이 작업은 개체 당 한 번만 사용할 수 있습니다. - - This platform does not support writing compiled regular expressions to an assembly. 이 플랫폼은 컴파일된 정규식을 어셈블리에 쓰는 것을 지원하지 않습니다. @@ -292,11 +282,6 @@ 패턴 끝에 잘못된 \\가 있습니다. - - Unexpected opcode in regular expression generation: {0}. - 정규식 생성에 예기치 않은 opcode가 있습니다. {0} - - Unrecognized control character. 인식할 수 없는 제어 문자입니다. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pl.xlf index f8cde42177c71..e92384e78130c 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pl.xlf @@ -47,11 +47,6 @@ Tablica docelowa ma zbyt małą długość, aby móc skopiować wszystkie elementy kolekcji. Sprawdź indeks tablicy i jej długość. - - The array cannot contain null elements. - Tablica nie może zawierać elementów zerowych. - - Start index cannot be less than 0 or greater than input length. Indeks początkowy nie może być mniejszy od 0 ani większy od długości danych wejściowych. @@ -212,11 +207,6 @@ Kolekcja jest tylko do odczytu. - - This operation is only allowed once per object. - Ta operacja jest dozwolona tylko raz dla każdego obiektu. - - This platform does not support writing compiled regular expressions to an assembly. Ta platforma nie obsługuje pisania skompilowanych wyrażeń regularnych do zestawu. @@ -292,11 +282,6 @@ Niedozwolony znak \\ na końcu wzorca. - - Unexpected opcode in regular expression generation: {0}. - Nieoczekiwany kod operacji podczas generowania wyrażenia regularnego: {0}. - - Unrecognized control character. Nierozpoznany znak kontrolny. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pt-BR.xlf index 6991eccb5b9cf..373012b191601 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.pt-BR.xlf @@ -47,11 +47,6 @@ A matriz de destino não é longa o suficiente para copiar todos os itens da coleção. Verifique o índice e o tamanho da matriz. - - The array cannot contain null elements. - A matriz não pode conter elementos nulos. - - Start index cannot be less than 0 or greater than input length. Índice inicial não pode ser menor que 0 ou maior que o comprimento de entrada. @@ -212,11 +207,6 @@ A coleção é somente leitura. - - This operation is only allowed once per object. - Esta operação só é permitida uma vez por objeto. - - This platform does not support writing compiled regular expressions to an assembly. Essa plataforma não suporta a escrita de expressões regulares compiladas em um assembly. @@ -292,11 +282,6 @@ \\ incorreto no final do padrão. - - Unexpected opcode in regular expression generation: {0}. - Opcode inesperado na geração de expressão regular: {0}. - - Unrecognized control character. Caractere de controle não reconhecido. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ru.xlf index 4f777ba7d0ccd..cf5dd334da348 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.ru.xlf @@ -47,11 +47,6 @@ Длина конечного массива недостаточна для копирования всех элементов коллекции. Проверьте индекс и длину массива. - - The array cannot contain null elements. - Массив не может содержать null-элементы. - - Start index cannot be less than 0 or greater than input length. Начальный индекс не может быть меньше 0 или больше длины ввода. @@ -212,11 +207,6 @@ Данная коллекция предназначена только для чтения. - - This operation is only allowed once per object. - Для каждого объекта допускается только однократное выполнение этой операции. - - This platform does not support writing compiled regular expressions to an assembly. Эта платформа не поддерживает запись скомпилированных регулярных выражений в сборку. @@ -292,11 +282,6 @@ Недопустимая обратная косая черта \\ в конце образца. - - Unexpected opcode in regular expression generation: {0}. - Неожиданный код операции при создании регулярного выражения: {0}. - - Unrecognized control character. Нераспознанный управляющий знак. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.tr.xlf index c1492d873c5f5..3ef9a801e79a7 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.tr.xlf @@ -47,11 +47,6 @@ Hedef dizi, koleksiyondaki tüm öğeleri kopyalamak için yeterince uzun değil. Dizi dizinini ve uzunluğunu denetleyin. - - The array cannot contain null elements. - Dizi null öğeler içeremez. - - Start index cannot be less than 0 or greater than input length. Başlangıç dizini sıfırdan küçük veya giriş uzunluğundan büyük olamaz. @@ -212,11 +207,6 @@ Koleksiyon salt okunur. - - This operation is only allowed once per object. - Bu işleme her nesne için yalnızca bir kez izin verilir. - - This platform does not support writing compiled regular expressions to an assembly. Bu platform, bütünleştirilmiş koda derlenmiş normal ifadeler yazılmasını desteklemiyor. @@ -292,11 +282,6 @@ Desenin sonunda geçersiz \\. - - Unexpected opcode in regular expression generation: {0}. - Normal ifade oluşturmada beklenmeyen işlem kodu: {0}. - - Unrecognized control character. Tanınmayan denetim karakteri. diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hans.xlf index 8bc7e9656e5be..a9909ca0f357b 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -47,11 +47,6 @@ 目标数组不够长,无法复制集合中的所有项。请检查数组索引和长度。 - - The array cannot contain null elements. - 数组不能包含 null 元素。 - - Start index cannot be less than 0 or greater than input length. 起始索引不能小于 0 或大于输入长度。 @@ -212,11 +207,6 @@ 集合是只读的。 - - This operation is only allowed once per object. - 对每个对象只能执行一次此操作。 - - This platform does not support writing compiled regular expressions to an assembly. 此平台不支持将已编译的正则表达式写入程序集。 @@ -292,11 +282,6 @@ \\ 在模式末尾非法。 - - Unexpected opcode in regular expression generation: {0}. - 生成正则表达式时出现意外的操作码: {0}。 - - Unrecognized control character. 无法识别的控制字符。 diff --git a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hant.xlf index 4e598383d8266..81971ed58e209 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Text.RegularExpressions/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -47,11 +47,6 @@ 目的地陣列的長度不足以複製集合中的所有項目。請檢查陣列索引以及長度。 - - The array cannot contain null elements. - 陣列不可包含 null 元素。 - - Start index cannot be less than 0 or greater than input length. 起始索引不能小於 0 或大於輸入長度。 @@ -212,11 +207,6 @@ 集合是唯讀的。 - - This operation is only allowed once per object. - 每一個物件只允許執行此項作業一次。 - - This platform does not support writing compiled regular expressions to an assembly. 此平台不支援將已編譯的規則運算式寫入組件。 @@ -292,11 +282,6 @@ 模式結尾有不合法的 \\。 - - Unexpected opcode in regular expression generation: {0}. - 在規則運算式產生中發生未預期的作業碼: {0}。 - - Unrecognized control character. 無法識別的控制字元。 diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index 56f7899f081db..e6982a3b83ce0 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -35,6 +35,8 @@ + + diff --git a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs index 9c0062d5b810c..251d595081072 100644 --- a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs +++ b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs @@ -142,9 +142,9 @@ public partial class Regex : System.Runtime.Serialization.ISerializable protected internal System.Text.RegularExpressions.RegexOptions roptions; protected Regex() { } protected Regex(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public Regex(string pattern) { } - public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options) { } - public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { } + public Regex([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { } + public Regex([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { } + public Regex([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { } public static int CacheSize { get { throw null; } set { } } [System.CLSCompliantAttribute(false)] [System.Diagnostics.CodeAnalysis.DisallowNullAttribute] @@ -161,6 +161,10 @@ public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompila public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompilationInfo[] regexinfos, System.Reflection.AssemblyName assemblyname, System.Reflection.Emit.CustomAttributeBuilder[]? attributes) { } [System.ObsoleteAttribute("Regex.CompileToAssembly is obsolete and not supported. Use the RegexGeneratorAttribute with the regular expression source generator instead.", DiagnosticId = "SYSLIB0036", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompilationInfo[] regexinfos, System.Reflection.AssemblyName assemblyname, System.Reflection.Emit.CustomAttributeBuilder[]? attributes, string? resourceFile) { } + public int Count(string input) { throw null; } + public static int Count(string input, [System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { throw null; } + public static int Count(string input, [System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static int Count(string input, [System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } public static string Escape(string str) { throw null; } public string[] GetGroupNames() { throw null; } public int[] GetGroupNumbers() { throw null; } @@ -169,38 +173,38 @@ public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompila protected void InitializeReferences() { } public bool IsMatch(string input) { throw null; } public bool IsMatch(string input, int startat) { throw null; } - public static bool IsMatch(string input, string pattern) { throw null; } - public static bool IsMatch(string input, string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static bool IsMatch(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static bool IsMatch(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { throw null; } + public static bool IsMatch(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static bool IsMatch(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } public System.Text.RegularExpressions.Match Match(string input) { throw null; } public System.Text.RegularExpressions.Match Match(string input, int startat) { throw null; } public System.Text.RegularExpressions.Match Match(string input, int beginning, int length) { throw null; } - public static System.Text.RegularExpressions.Match Match(string input, string pattern) { throw null; } - public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static System.Text.RegularExpressions.Match Match(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { throw null; } + public static System.Text.RegularExpressions.Match Match(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static System.Text.RegularExpressions.Match Match(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } public System.Text.RegularExpressions.MatchCollection Matches(string input) { throw null; } public System.Text.RegularExpressions.MatchCollection Matches(string input, int startat) { throw null; } - public static System.Text.RegularExpressions.MatchCollection Matches(string input, string pattern) { throw null; } - public static System.Text.RegularExpressions.MatchCollection Matches(string input, string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static System.Text.RegularExpressions.MatchCollection Matches(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static System.Text.RegularExpressions.MatchCollection Matches(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { throw null; } + public static System.Text.RegularExpressions.MatchCollection Matches(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static System.Text.RegularExpressions.MatchCollection Matches(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } public string Replace(string input, string replacement) { throw null; } public string Replace(string input, string replacement, int count) { throw null; } public string Replace(string input, string replacement, int count, int startat) { throw null; } - public static string Replace(string input, string pattern, string replacement) { throw null; } - public static string Replace(string input, string pattern, string replacement, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static string Replace(string input, string pattern, string replacement, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } - public static string Replace(string input, string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator) { throw null; } - public static string Replace(string input, string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static string Replace(string input, string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern, string replacement) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, string replacement, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, string replacement, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static string Replace(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.MatchEvaluator evaluator, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } public string Replace(string input, System.Text.RegularExpressions.MatchEvaluator evaluator) { throw null; } public string Replace(string input, System.Text.RegularExpressions.MatchEvaluator evaluator, int count) { throw null; } public string Replace(string input, System.Text.RegularExpressions.MatchEvaluator evaluator, int count, int startat) { throw null; } public string[] Split(string input) { throw null; } public string[] Split(string input, int count) { throw null; } public string[] Split(string input, int count, int startat) { throw null; } - public static string[] Split(string input, string pattern) { throw null; } - public static string[] Split(string input, string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } - public static string[] Split(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } + public static string[] Split(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { throw null; } + public static string[] Split(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { throw null; } + public static string[] Split(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) { throw null; } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) { } public override string ToString() { throw null; } public static string Unescape(string str) { throw null; } @@ -223,9 +227,9 @@ public RegexCompilationInfo(string pattern, System.Text.RegularExpressions.Regex [System.AttributeUsageAttribute(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed partial class RegexGeneratorAttribute : System.Attribute { - public RegexGeneratorAttribute(string pattern) { } - public RegexGeneratorAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options) { } - public RegexGeneratorAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds) { } + public RegexGeneratorAttribute([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex)] string pattern) { } + public RegexGeneratorAttribute([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options) { } + public RegexGeneratorAttribute([System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex, "options")] string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds) { } public string Pattern { get; } public System.Text.RegularExpressions.RegexOptions Options { get; } public int MatchTimeoutMilliseconds { get; } diff --git a/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx b/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx index ba430db54c5a3..154f34512ed1e 100644 --- a/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx +++ b/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx @@ -70,9 +70,6 @@ Destination array is not long enough to copy all the items in the collection. Check array index and length. - - The array cannot contain null elements. - Cannot include class \\{0} in character range. @@ -200,9 +197,6 @@ Alternation has a reference to undefined group. - - Unexpected opcode in regular expression generation: {0}. - Unknown property '{0}'. diff --git a/src/libraries/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj b/src/libraries/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj index 8537fd70de527..0034d373563a9 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj +++ b/src/libraries/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj @@ -18,6 +18,7 @@ + @@ -32,6 +33,8 @@ + + diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Match.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Match.cs index b7f2f032e78a8..3c67526b40e18 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Match.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Match.cs @@ -61,9 +61,6 @@ internal Match(Regex? regex, int capcount, string text, int begpos, int len, int _textend = begpos + len; _textstart = startpos; _balancing = false; - - Debug.Assert(!(_textbeg < 0 || _textstart < _textbeg || _textend < _textstart || Text.Length < _textend), - "The parameters are out of range."); } /// Returns an empty Match object. @@ -332,31 +329,6 @@ private void TidyBalancing() _balancing = false; } - -#if DEBUG - [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal bool IsDebug => _regex != null && _regex.IsDebug; - - internal virtual void Dump() - { - for (int i = 0; i < _matchcount.Length; i++) - { - Debug.WriteLine($"Capnum {i}:"); - - for (int j = 0; j < _matchcount[i]; j++) - { - string text = ""; - - if (_matches[i][j * 2] >= 0) - { - text = Text.Substring(_matches[i][j * 2], _matches[i][j * 2 + 1]); - } - - Debug.WriteLine($" ({_matches[i][j * 2]},{_matches[i][j * 2 + 1]}) {text}"); - } - } - } -#endif } /// @@ -364,8 +336,7 @@ internal virtual void Dump() /// internal sealed class MatchSparse : Match { - // the lookup hashtable - internal new readonly Hashtable _caps; + private new readonly Hashtable _caps; internal MatchSparse(Regex regex, Hashtable caps, int capcount, string text, int begpos, int len, int startpos) : base(regex, capcount, text, begpos, len, startpos) @@ -374,22 +345,5 @@ internal MatchSparse(Regex regex, Hashtable caps, int capcount, string text, int } public override GroupCollection Groups => _groupcoll ??= new GroupCollection(this, _caps); - -#if DEBUG - [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal override void Dump() - { - if (_caps != null) - { - foreach (object? entry in _caps) - { - DictionaryEntry kvp = (DictionaryEntry)entry!; - Debug.WriteLine($"Slot {kvp.Key} -> {kvp.Value}"); - } - } - - base.Dump(); - } -#endif } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Count.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Count.cs new file mode 100644 index 0000000000000..18c08ee3242e2 --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Count.cs @@ -0,0 +1,64 @@ +// 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.CodeAnalysis; + +namespace System.Text.RegularExpressions +{ + public partial class Regex + { + /// Searches an input string for all occurrences of a regular expression and returns the number of matches. + /// The string to search for a match. + /// The number of matches. + /// is null. + public int Count(string input) + { + if (input is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); + } + + int count = 0; + + Run(input, 0, ref count, static (ref int count, Match match) => + { + count++; + return true; + }, reuseMatchObject: true); + + return count; + } + + /// Searches an input string for all occurrences of a regular expression and returns the number of matches. + /// The string to search for a match. + /// The regular expression pattern to match. + /// The number of matches. + /// or is null. + /// A regular expression parsing error occurred. + public static int Count(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) => + RegexCache.GetOrAdd(pattern).Count(input); + + /// Searches an input string for all occurrences of a regular expression and returns the number of matches. + /// The string to search for a match. + /// The regular expression pattern to match. + /// A bitwise combination of the enumeration values that specify options for matching. + /// The number of matches. + /// or is null. + /// is not a valid bitwise combination of RegexOptions values. + /// A regular expression parsing error occurred. + public static int Count(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) => + RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Count(input); + + /// Searches an input string for all occurrences of a regular expression and returns the number of matches. + /// The string to search for a match. + /// The regular expression pattern to match. + /// A bitwise combination of the enumeration values that specify options for matching. + /// A time-out interval, or to indicate that the method should not time out. + /// The number of matches. + /// or is null. + /// is not a valid bitwise combination of RegexOptions values, or is negative, zero, or greater than approximately 24 days. + /// A regular expression parsing error occurred. + public static int Count(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) => + RegexCache.GetOrAdd(pattern, options, matchTimeout).Count(input); + } +} diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Debug.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Debug.cs index 862af1731d324..ee124fdf205c1 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Debug.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Debug.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #if DEBUG +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.RegularExpressions.Symbolic; @@ -11,16 +12,17 @@ namespace System.Text.RegularExpressions { public partial class Regex { - /// True if the regex has debugging enabled. + /// True if debug tracing should be enabled, only in debug builds. [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal bool IsDebug + internal static bool EnableDebugTracing { // These members aren't used from IsDebug, but we want to keep them in debug builds for now, - // so this is a convient place to include them rather than needing a debug-only illink file. + // so this is a convenient place to include them rather than needing a debug-only illink file. [DynamicDependency(nameof(SaveDGML))] [DynamicDependency(nameof(GenerateUnicodeTables))] [DynamicDependency(nameof(GenerateRandomMembers))] - get => (roptions & RegexOptions.Debug) != 0; + get; + set; } /// Unwind the regex and save the resulting state graph in DGML @@ -62,7 +64,7 @@ internal static void GenerateUnicodeTables(string path) /// if true then generate inputs that do not match /// [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal Collections.Generic.IEnumerable GenerateRandomMembers(int k, int randomseed, bool negative) + internal IEnumerable GenerateRandomMembers(int k, int randomseed, bool negative) { if (factory is not SymbolicRegexRunnerFactory srmFactory) { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Match.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Match.cs index 0770ba90cd216..cd0494c3dc009 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Match.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Match.cs @@ -1,6 +1,8 @@ // 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.CodeAnalysis; + namespace System.Text.RegularExpressions { public partial class Regex @@ -8,7 +10,7 @@ public partial class Regex /// /// Searches the input string for one or more occurrences of the text supplied in the given pattern. /// - public static bool IsMatch(string input, string pattern) => + public static bool IsMatch(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) => RegexCache.GetOrAdd(pattern).IsMatch(input); /// @@ -16,10 +18,10 @@ public static bool IsMatch(string input, string pattern) => /// supplied in the pattern parameter with matching options supplied in the options /// parameter. /// - public static bool IsMatch(string input, string pattern, RegexOptions options) => + public static bool IsMatch(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).IsMatch(input); - public static bool IsMatch(string input, string pattern, RegexOptions options, TimeSpan matchTimeout) => + public static bool IsMatch(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).IsMatch(input); /// @@ -54,7 +56,7 @@ public bool IsMatch(string input, int startat) /// Searches the input string for one or more occurrences of the text /// supplied in the pattern parameter. /// - public static Match Match(string input, string pattern) => + public static Match Match(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) => RegexCache.GetOrAdd(pattern).Match(input); /// @@ -62,10 +64,10 @@ public static Match Match(string input, string pattern) => /// supplied in the pattern parameter. Matching is modified with an option /// string. /// - public static Match Match(string input, string pattern, RegexOptions options) => + public static Match Match(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Match(input); - public static Match Match(string input, string pattern, RegexOptions options, TimeSpan matchTimeout) => + public static Match Match(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).Match(input); /// @@ -112,16 +114,16 @@ public Match Match(string input, int beginning, int length) /// /// Returns all the successful matches as if Match were called iteratively numerous times. /// - public static MatchCollection Matches(string input, string pattern) => + public static MatchCollection Matches(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) => RegexCache.GetOrAdd(pattern).Matches(input); /// /// Returns all the successful matches as if Match were called iteratively numerous times. /// - public static MatchCollection Matches(string input, string pattern, RegexOptions options) => + public static MatchCollection Matches(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Matches(input); - public static MatchCollection Matches(string input, string pattern, RegexOptions options, TimeSpan matchTimeout) => + public static MatchCollection Matches(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).Matches(input); /// diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs index 1b048fc687506..ba1f9a91e4449 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs @@ -1,6 +1,8 @@ // 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.CodeAnalysis; + namespace System.Text.RegularExpressions { // Callback class @@ -14,7 +16,7 @@ public partial class Regex /// Replaces all occurrences of the pattern with the pattern, starting at /// the first character in the input string. /// - public static string Replace(string input, string pattern, string replacement) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern, string replacement) => RegexCache.GetOrAdd(pattern).Replace(input, replacement); /// @@ -22,10 +24,10 @@ public static string Replace(string input, string pattern, string replacement) = /// the with the /// pattern, starting at the first character in the input string. /// - public static string Replace(string input, string pattern, string replacement, RegexOptions options) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, string replacement, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Replace(input, replacement); - public static string Replace(string input, string pattern, string replacement, RegexOptions options, TimeSpan matchTimeout) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, string replacement, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).Replace(input, replacement); /// @@ -85,17 +87,17 @@ public string Replace(string input, string replacement, int count, int startat) /// Replaces all occurrences of the with the recent /// replacement pattern. /// - public static string Replace(string input, string pattern, MatchEvaluator evaluator) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern, MatchEvaluator evaluator) => RegexCache.GetOrAdd(pattern).Replace(input, evaluator); /// /// Replaces all occurrences of the with the recent /// replacement pattern, starting at the first character. /// - public static string Replace(string input, string pattern, MatchEvaluator evaluator, RegexOptions options) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, MatchEvaluator evaluator, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Replace(input, evaluator); - public static string Replace(string input, string pattern, MatchEvaluator evaluator, RegexOptions options, TimeSpan matchTimeout) => + public static string Replace(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, MatchEvaluator evaluator, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).Replace(input, evaluator); /// diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Split.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Split.cs index f223c4e6ed97d..454aeacfa6df6 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Split.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Split.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Text.RegularExpressions { @@ -11,16 +12,16 @@ public partial class Regex /// Splits the string at the position defined /// by . /// - public static string[] Split(string input, string pattern) => + public static string[] Split(string input, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) => RegexCache.GetOrAdd(pattern).Split(input); /// /// Splits the string at the position defined by . /// - public static string[] Split(string input, string pattern, RegexOptions options) => + public static string[] Split(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) => RegexCache.GetOrAdd(pattern, options, s_defaultMatchTimeout).Split(input); - public static string[] Split(string input, string pattern, RegexOptions options, TimeSpan matchTimeout) => + public static string[] Split(string input, [StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) => RegexCache.GetOrAdd(pattern, options, matchTimeout).Split(input); /// diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs index 9d108abfb8f02..d07f3440de4b8 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs @@ -22,6 +22,7 @@ public partial class Regex : ISerializable { internal const int MaxOptionShift = 11; + [StringSyntax(StringSyntaxAttribute.Regex)] protected internal string? pattern; // The string pattern provided protected internal RegexOptions roptions; // the top-level options from the options string protected internal RegexRunnerFactory? factory; // Factory used to create runner instances for executing the regex @@ -42,7 +43,7 @@ protected Regex() /// /// Creates a regular expression object for the specified regular expression. /// - public Regex(string pattern) : + public Regex([StringSyntax(StringSyntaxAttribute.Regex)] string pattern) : this(pattern, culture: null) { } @@ -50,12 +51,12 @@ public Regex(string pattern) : /// /// Creates a regular expression object for the specified regular expression, with options that modify the pattern. /// - public Regex(string pattern, RegexOptions options) : + public Regex([StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) : this(pattern, options, s_defaultMatchTimeout, culture: null) { } - public Regex(string pattern, RegexOptions options, TimeSpan matchTimeout) : + public Regex([StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, TimeSpan matchTimeout) : this(pattern, options, matchTimeout, culture: null) { } @@ -109,13 +110,6 @@ private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, C internalMatchTimeout = matchTimeout; roptions = options; -#if DEBUG - if (IsDebug) - { - Debug.WriteLine($"Pattern: {pattern} Options: {options & ~RegexOptions.Debug} Timeout: {(matchTimeout == InfiniteMatchTimeout ? "infinite" : matchTimeout.ToString())}"); - } -#endif - // Parse the input RegexTree tree = RegexParser.Parse(pattern, roptions, culture); @@ -152,11 +146,7 @@ internal static void ValidateOptions(RegexOptions options) { if (((((uint)options) >> MaxOptionShift) != 0) || ((options & RegexOptions.ECMAScript) != 0 && - (options & ~(RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.NonBacktracking | -#if DEBUG - RegexOptions.Debug | -#endif - RegexOptions.CultureInvariant)) != 0)) + (options & ~(RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.NonBacktracking | RegexOptions.CultureInvariant)) != 0)) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.options); } @@ -393,12 +383,7 @@ protected void InitializeReferences() RegexRunner runner = Interlocked.Exchange(ref _runner, null) ?? CreateRunner(); try { - // Do the scan starting at the requested position - Match? match = runner.Scan(this, input, beginning, beginning + length, startat, prevlen, quick, internalMatchTimeout); -#if DEBUG - if (IsDebug) match?.Dump(); -#endif - return match; + return runner.Scan(this, input, beginning, beginning + length, startat, prevlen, quick, internalMatchTimeout); } finally { @@ -409,6 +394,7 @@ protected void InitializeReferences() internal void Run(string input, int startat, ref TState state, MatchCallback callback, bool reuseMatchObject) { Debug.Assert((uint)startat <= (uint)input.Length); + RegexRunner runner = Interlocked.Exchange(ref _runner, null) ?? CreateRunner(); try { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs index 98957dfb408df..d4a8fb4f3b232 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs @@ -716,9 +716,8 @@ public static bool TryGetSingleRange(string set, out char lowInclusive, out char /// public static int GetSetChars(string set, Span chars) { - // If the set is negated, it's likely to contain a large number of characters, - // so we don't even try. We also get the characters by enumerating the set - // portion, so we validate that it's set up to enable that, e.g. no categories. + // We get the characters by enumerating the set portion, so we validate that it's + // set up to enable that, e.g. no categories. if (!CanEasilyEnumerateSetContents(set)) { return 0; @@ -1816,7 +1815,7 @@ private static string[] PopulateCategoryIdToName() /// Produces a human-readable description for a set string. /// [ExcludeFromCodeCoverage] - public static string SetDescription(string set) + public static string DescribeSet(string set) { int setLength = set[SetLengthIndex]; int categoryLength = set[CategoryLengthIndex]; @@ -1842,7 +1841,7 @@ public static string SetDescription(string set) (char)(set[index + 1] - 1) : LastChar; - desc.Append(CharDescription(ch1)); + desc.Append(DescribeChar(ch1)); if (ch2 != ch1) { @@ -1851,7 +1850,7 @@ public static string SetDescription(string set) desc.Append('-'); } - desc.Append(CharDescription(ch2)); + desc.Append(DescribeChar(ch2)); } index += 2; } @@ -1900,7 +1899,7 @@ public static string SetDescription(string set) } else { - desc.Append(CategoryDescription(ch1)); + desc.Append(DescribeCategory(ch1)); } index++; @@ -1908,7 +1907,7 @@ public static string SetDescription(string set) if (set.Length > endPosition) { - desc.Append('-').Append(SetDescription(set.Substring(endPosition))); + desc.Append('-').Append(DescribeSet(set.Substring(endPosition))); } return desc.Append(']').ToString(); @@ -1916,7 +1915,7 @@ public static string SetDescription(string set) /// Produces a human-readable description for a single character. [ExcludeFromCodeCoverage] - public static string CharDescription(char ch) => + public static string DescribeChar(char ch) => ch switch { '\a' => "\\a", @@ -1932,7 +1931,7 @@ public static string CharDescription(char ch) => }; [ExcludeFromCodeCoverage] - private static string CategoryDescription(char ch) => + private static string DescribeCategory(char ch) => (short)ch switch { SpaceConst => @"\s", diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCode.cs index 6f6c8cd8f8852..f31d9301c47f1 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCode.cs @@ -1,18 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// This RegexCode class is internal to the regular expression package. - -// Implementation notes: -// -// Regexps are built into RegexCodes, which contain an operation array, -// a string table, and some constants. -// -// Each operation is one of the codes below, followed by the integer -// operands specified for each op. -// -// Strings and sets are indices into a string table. - using System.Collections; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -20,92 +8,30 @@ namespace System.Text.RegularExpressions { + /// Representation of a regular expression, written by and containing the code evaluated by . + /// It currently stores some data used by engines other than the interpreter; that can be refactored out in the future. internal sealed class RegexCode { - // The following primitive operations come directly from the parser - - // lef/back operands description - public const int Onerep = 0; // lef,back char,min,max a {n} - public const int Notonerep = 1; // lef,back char,min,max .{n} - public const int Setrep = 2; // lef,back set,min,max [\d]{n} - - public const int Oneloop = 3; // lef,back char,min,max a {,n} - public const int Notoneloop = 4; // lef,back char,min,max .{,n} - public const int Setloop = 5; // lef,back set,min,max [\d]{,n} - - public const int Onelazy = 6; // lef,back char,min,max a {,n}? - public const int Notonelazy = 7; // lef,back char,min,max .{,n}? - public const int Setlazy = 8; // lef,back set,min,max [\d]{,n}? - - public const int One = 9; // lef char a - public const int Notone = 10; // lef char [^a] - public const int Set = 11; // lef set [a-z\s] \w \s \d - - public const int Multi = 12; // lef string abcd - public const int Ref = 13; // lef group \# - - public const int Bol = 14; // ^ - public const int Eol = 15; // $ - public const int Boundary = 16; // \b - public const int NonBoundary = 17; // \B - public const int Beginning = 18; // \A - public const int Start = 19; // \G - public const int EndZ = 20; // \Z - public const int End = 21; // \Z - - public const int Nothing = 22; // Reject! - - // Primitive control structures - - public const int Lazybranch = 23; // back jump straight first - public const int Branchmark = 24; // back jump branch first for loop - public const int Lazybranchmark = 25; // back jump straight first for loop - public const int Nullcount = 26; // back val set counter, null mark - public const int Setcount = 27; // back val set counter, make mark - public const int Branchcount = 28; // back jump,limit branch++ if zero<=c a {,n} ) - public const int Notoneloopatomic = 44; // lef,back set,min,max (?> . {,n} ) - public const int Setloopatomic = 45; // lef,back set,min,max (?> [\d]{,n} ) - public const int UpdateBumpalong = 46; // updates the bumpalong position to the current position - - // Modifiers for alternate modes - public const int Mask = 63; // Mask to get unmodified ordinary operator - public const int Rtl = 64; // bit to indicate that we're reverse scanning. - public const int Back = 128; // bit to indicate that we're backtracking. - public const int Back2 = 256; // bit to indicate that we're backtracking on a second branch. - public const int Ci = 512; // bit to indicate that we're case-insensitive. - - public readonly RegexTree Tree; // the optimized parse tree - public readonly int[] Codes; // the code - public readonly string[] Strings; // the string/set table - public readonly uint[]?[] StringsAsciiLookup; // the ASCII lookup table optimization for the sets in Strings - public readonly int TrackCount; // how many instructions use backtracking - public readonly Hashtable? Caps; // mapping of user group numbers -> impl group slots - public readonly int CapSize; // number of impl group slots - public readonly bool RightToLeft; // true if right to left + /// The optimized parse tree. + public readonly RegexTree Tree; + /// RegexOpcodes and arguments written by . + public readonly int[] Codes; + /// The string / set table. includes offsets into this table, for string and set arguments. + public readonly string[] Strings; + /// ASCII lookup table optimization for sets in . + public readonly uint[]?[] StringsAsciiLookup; + /// How many instructions in use backtracking. + public readonly int TrackCount; + /// Mapping of user group numbers to impl group slots. + public readonly Hashtable? Caps; + /// Number of impl group slots. + public readonly int CapSize; + /// True if right to left. + public readonly bool RightToLeft; + /// Optimization mode and supporting data to enable quickly finding the next possible match location. public readonly RegexFindOptimizations FindOptimizations; - public RegexCode(RegexTree tree, CultureInfo culture, int[] codes, string[] strings, int trackcount, - Hashtable? caps, int capsize) + public RegexCode(RegexTree tree, CultureInfo culture, int[] codes, string[] strings, int trackcount, Hashtable? caps, int capsize) { Tree = tree; Codes = codes; @@ -118,32 +44,33 @@ public RegexCode(RegexTree tree, CultureInfo culture, int[] codes, string[] stri FindOptimizations = new RegexFindOptimizations(tree, culture); } - public static bool OpcodeBacktracks(int Op) + /// Gets whether the specified opcode may incur backtracking. + public static bool OpcodeBacktracks(RegexOpcode opcode) { - Op &= Mask; + opcode &= RegexOpcode.OperatorMask; - switch (Op) + switch (opcode) { - case Oneloop: - case Notoneloop: - case Setloop: - case Onelazy: - case Notonelazy: - case Setlazy: - case Lazybranch: - case Branchmark: - case Lazybranchmark: - case Nullcount: - case Setcount: - case Branchcount: - case Lazybranchcount: - case Setmark: - case Capturemark: - case Getmark: - case Setjump: - case Backjump: - case Forejump: - case Goto: + case RegexOpcode.Oneloop: + case RegexOpcode.Onelazy: + case RegexOpcode.Notoneloop: + case RegexOpcode.Notonelazy: + case RegexOpcode.Setloop: + case RegexOpcode.Setlazy: + case RegexOpcode.Lazybranch: + case RegexOpcode.Branchmark: + case RegexOpcode.Lazybranchmark: + case RegexOpcode.Nullcount: + case RegexOpcode.Setcount: + case RegexOpcode.Branchcount: + case RegexOpcode.Lazybranchcount: + case RegexOpcode.Setmark: + case RegexOpcode.Capturemark: + case RegexOpcode.Getmark: + case RegexOpcode.Setjump: + case RegexOpcode.Backjump: + case RegexOpcode.Forejump: + case RegexOpcode.Goto: return true; default: @@ -151,264 +78,188 @@ public static bool OpcodeBacktracks(int Op) } } - public static int OpcodeSize(int opcode) + /// Gets the number of integers required to store an operation represented by the specified opcode (including the opcode). + /// Values range from 1 (just the opcode) to 3 (the opcode plus up to two operands). + public static int OpcodeSize(RegexOpcode opcode) { - opcode &= Mask; - + opcode &= RegexOpcode.OperatorMask; switch (opcode) { - case Nothing: - case Bol: - case Eol: - case Boundary: - case NonBoundary: - case ECMABoundary: - case NonECMABoundary: - case Beginning: - case Start: - case EndZ: - case End: - case Nullmark: - case Setmark: - case Getmark: - case Setjump: - case Backjump: - case Forejump: - case Stop: - case UpdateBumpalong: + case RegexOpcode.Nothing: + case RegexOpcode.Bol: + case RegexOpcode.Eol: + case RegexOpcode.Boundary: + case RegexOpcode.NonBoundary: + case RegexOpcode.ECMABoundary: + case RegexOpcode.NonECMABoundary: + case RegexOpcode.Beginning: + case RegexOpcode.Start: + case RegexOpcode.EndZ: + case RegexOpcode.End: + case RegexOpcode.Nullmark: + case RegexOpcode.Setmark: + case RegexOpcode.Getmark: + case RegexOpcode.Setjump: + case RegexOpcode.Backjump: + case RegexOpcode.Forejump: + case RegexOpcode.Stop: + case RegexOpcode.UpdateBumpalong: + // The opcode has no operands. return 1; - case One: - case Notone: - case Multi: - case Ref: - case Testref: - case Goto: - case Nullcount: - case Setcount: - case Lazybranch: - case Branchmark: - case Lazybranchmark: - case Set: + case RegexOpcode.One: + case RegexOpcode.Notone: + case RegexOpcode.Multi: + case RegexOpcode.Backreference: + case RegexOpcode.TestBackreference: + case RegexOpcode.Goto: + case RegexOpcode.Nullcount: + case RegexOpcode.Setcount: + case RegexOpcode.Lazybranch: + case RegexOpcode.Branchmark: + case RegexOpcode.Lazybranchmark: + case RegexOpcode.Set: + // The opcode has one operand. return 2; - case Capturemark: - case Branchcount: - case Lazybranchcount: - case Onerep: - case Notonerep: - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Notonelazy: - case Setlazy: - case Setrep: - case Setloop: - case Setloopatomic: + case RegexOpcode.Capturemark: + case RegexOpcode.Branchcount: + case RegexOpcode.Lazybranchcount: + case RegexOpcode.Onerep: + case RegexOpcode.Notonerep: + case RegexOpcode.Oneloop: + case RegexOpcode.Oneloopatomic: + case RegexOpcode.Notoneloop: + case RegexOpcode.Notoneloopatomic: + case RegexOpcode.Onelazy: + case RegexOpcode.Notonelazy: + case RegexOpcode.Setlazy: + case RegexOpcode.Setrep: + case RegexOpcode.Setloop: + case RegexOpcode.Setloopatomic: + // The opcode has two operands. return 3; default: - throw new ArgumentException(SR.Format(SR.UnexpectedOpcode, opcode.ToString())); + Debug.Fail($"Unknown opcode: {opcode}"); + goto case RegexOpcode.Stop; } } +#if DEBUG [ExcludeFromCodeCoverage] - private static string OperatorDescription(int Opcode) + public override string ToString() { - string codeStr = (Opcode & Mask) switch + var sb = new StringBuilder(); + + sb.AppendLine($"Direction: {(RightToLeft ? "right-to-left" : "left-to-right")}"); + sb.AppendLine($"Anchor: {FindOptimizations.LeadingAnchor}"); + sb.AppendLine(); + for (int i = 0; i < Codes.Length; i += OpcodeSize((RegexOpcode)Codes[i])) { - Onerep => nameof(Onerep), - Notonerep => nameof(Notonerep), - Setrep => nameof(Setrep), - Oneloop => nameof(Oneloop), - Notoneloop => nameof(Notoneloop), - Setloop => nameof(Setloop), - Onelazy => nameof(Onelazy), - Notonelazy => nameof(Notonelazy), - Setlazy => nameof(Setlazy), - One => nameof(One), - Notone => nameof(Notone), - Set => nameof(Set), - Multi => nameof(Multi), - Ref => nameof(Ref), - Bol => nameof(Bol), - Eol => nameof(Eol), - Boundary => nameof(Boundary), - NonBoundary => nameof(NonBoundary), - Beginning => nameof(Beginning), - Start => nameof(Start), - EndZ => nameof(EndZ), - End => nameof(End), - Nothing => nameof(Nothing), - Lazybranch => nameof(Lazybranch), - Branchmark => nameof(Branchmark), - Lazybranchmark => nameof(Lazybranchmark), - Nullcount => nameof(Nullcount), - Setcount => nameof(Setcount), - Branchcount => nameof(Branchcount), - Lazybranchcount => nameof(Lazybranchcount), - Nullmark => nameof(Nullmark), - Setmark => nameof(Setmark), - Capturemark => nameof(Capturemark), - Getmark => nameof(Getmark), - Setjump => nameof(Setjump), - Backjump => nameof(Backjump), - Forejump => nameof(Forejump), - Testref => nameof(Testref), - Goto => nameof(Goto), - Stop => nameof(Stop), - ECMABoundary => nameof(ECMABoundary), - NonECMABoundary => nameof(NonECMABoundary), - Oneloopatomic => nameof(Oneloopatomic), - Notoneloopatomic => nameof(Notoneloopatomic), - Setloopatomic => nameof(Setloopatomic), - UpdateBumpalong => nameof(UpdateBumpalong), - _ => "(unknown)" - }; + sb.AppendLine(DescribeInstruction(i)); + } - return - codeStr + - ((Opcode & Ci) != 0 ? "-Ci" : "") + - ((Opcode & Rtl) != 0 ? "-Rtl" : "") + - ((Opcode & Back) != 0 ? "-Back" : "") + - ((Opcode & Back2) != 0 ? "-Back2" : ""); + return sb.ToString(); } [ExcludeFromCodeCoverage] - internal string OpcodeDescription(int offset) => OpcodeDescription(offset, Codes, Strings); - - [ExcludeFromCodeCoverage] - internal static string OpcodeDescription(int offset, int[] codes, string[] strings) + internal string DescribeInstruction(int opcodeOffset) { - var sb = new StringBuilder(); - int opcode = codes[offset]; + RegexOpcode opcode = (RegexOpcode)Codes[opcodeOffset]; - sb.Append($"{offset:D6} "); - sb.Append(OpcodeBacktracks(opcode & Mask) ? '*' : ' '); - sb.Append(OperatorDescription(opcode)); + var sb = new StringBuilder(); + sb.Append($"{opcodeOffset:D6} "); + sb.Append(OpcodeBacktracks(opcode & RegexOpcode.OperatorMask) ? '~' : ' '); + sb.Append(opcode & RegexOpcode.OperatorMask); + if ((opcode & RegexOpcode.CaseInsensitive) != 0) sb.Append("-Ci"); + if ((opcode & RegexOpcode.RightToLeft) != 0) sb.Append("-Rtl"); + if ((opcode & RegexOpcode.Backtracking) != 0) sb.Append("-Back"); + if ((opcode & RegexOpcode.BacktrackingSecond) != 0) sb.Append("-Back2"); - opcode &= Mask; + opcode &= RegexOpcode.OperatorMask; switch (opcode) { - case One: - case Notone: - case Onerep: - case Notonerep: - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Notonelazy: - sb.Append(Indent()).Append('\'').Append(RegexCharClass.CharDescription((char)codes[offset + 1])).Append('\''); + case RegexOpcode.One: + case RegexOpcode.Onerep: + case RegexOpcode.Oneloop: + case RegexOpcode.Oneloopatomic: + case RegexOpcode.Onelazy: + case RegexOpcode.Notone: + case RegexOpcode.Notonerep: + case RegexOpcode.Notoneloop: + case RegexOpcode.Notoneloopatomic: + case RegexOpcode.Notonelazy: + sb.Append(Indent()).Append('\'').Append(RegexCharClass.DescribeChar((char)Codes[opcodeOffset + 1])).Append('\''); break; - case Set: - case Setrep: - case Setloop: - case Setloopatomic: - case Setlazy: - sb.Append(Indent()).Append(RegexCharClass.SetDescription(strings[codes[offset + 1]])); + case RegexOpcode.Set: + case RegexOpcode.Setrep: + case RegexOpcode.Setloop: + case RegexOpcode.Setloopatomic: + case RegexOpcode.Setlazy: + sb.Append(Indent()).Append(RegexCharClass.DescribeSet(Strings[Codes[opcodeOffset + 1]])); break; - case Multi: - sb.Append(Indent()).Append('"').Append(strings[codes[offset + 1]]).Append('"'); + case RegexOpcode.Multi: + sb.Append(Indent()).Append('"').Append(Strings[Codes[opcodeOffset + 1]]).Append('"'); break; - case Ref: - case Testref: - sb.Append(Indent()).Append("index = ").Append(codes[offset + 1]); + case RegexOpcode.Backreference: + case RegexOpcode.TestBackreference: + sb.Append(Indent()).Append("index = ").Append(Codes[opcodeOffset + 1]); break; - case Capturemark: - sb.Append(Indent()).Append("index = ").Append(codes[offset + 1]); - if (codes[offset + 2] != -1) + case RegexOpcode.Capturemark: + sb.Append(Indent()).Append("index = ").Append(Codes[opcodeOffset + 1]); + if (Codes[opcodeOffset + 2] != -1) { - sb.Append(", unindex = ").Append(codes[offset + 2]); + sb.Append(", unindex = ").Append(Codes[opcodeOffset + 2]); } break; - case Nullcount: - case Setcount: - sb.Append(Indent()).Append("value = ").Append(codes[offset + 1]); + case RegexOpcode.Nullcount: + case RegexOpcode.Setcount: + sb.Append(Indent()).Append("value = ").Append(Codes[opcodeOffset + 1]); break; - case Goto: - case Lazybranch: - case Branchmark: - case Lazybranchmark: - case Branchcount: - case Lazybranchcount: - sb.Append(Indent()).Append("addr = ").Append(codes[offset + 1]); + case RegexOpcode.Goto: + case RegexOpcode.Lazybranch: + case RegexOpcode.Branchmark: + case RegexOpcode.Lazybranchmark: + case RegexOpcode.Branchcount: + case RegexOpcode.Lazybranchcount: + sb.Append(Indent()).Append("addr = ").Append(Codes[opcodeOffset + 1]); break; } switch (opcode) { - case Onerep: - case Notonerep: - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Notonelazy: - case Setrep: - case Setloop: - case Setloopatomic: - case Setlazy: - sb.Append(", rep = "); - if (codes[offset + 2] == int.MaxValue) - { - sb.Append("inf"); - } - else - { - sb.Append(codes[offset + 2]); - } + case RegexOpcode.Onerep: + case RegexOpcode.Oneloop: + case RegexOpcode.Oneloopatomic: + case RegexOpcode.Onelazy: + case RegexOpcode.Notonerep: + case RegexOpcode.Notoneloop: + case RegexOpcode.Notoneloopatomic: + case RegexOpcode.Notonelazy: + case RegexOpcode.Setrep: + case RegexOpcode.Setloop: + case RegexOpcode.Setloopatomic: + case RegexOpcode.Setlazy: + sb.Append(", rep = ").Append(Codes[opcodeOffset + 2] == int.MaxValue ? "inf" : Codes[opcodeOffset + 2]); break; - case Branchcount: - case Lazybranchcount: - sb.Append(", limit = "); - if (codes[offset + 2] == int.MaxValue) - { - sb.Append("inf"); - } - else - { - sb.Append(codes[offset + 2]); - } + case RegexOpcode.Branchcount: + case RegexOpcode.Lazybranchcount: + sb.Append(", limit = ").Append(Codes[opcodeOffset + 2] == int.MaxValue ? "inf" : Codes[opcodeOffset + 2]); break; } - string Indent() => new string(' ', Math.Max(1, 25 - sb.Length)); - return sb.ToString(); - } - -#if DEBUG - [ExcludeFromCodeCoverage] - public void Dump() => Debug.WriteLine(ToString()); - - [ExcludeFromCodeCoverage] - public override string ToString() - { - var sb = new StringBuilder(); - sb.AppendLine($"Direction: {(RightToLeft ? "right-to-left" : "left-to-right")}"); - sb.AppendLine($"Anchor: {RegexPrefixAnalyzer.AnchorDescription(FindOptimizations.LeadingAnchor)}"); - sb.AppendLine(); - for (int i = 0; i < Codes.Length; i += OpcodeSize(Codes[i])) - { - sb.AppendLine(OpcodeDescription(i)); - } - sb.AppendLine(); - - return sb.ToString(); + string Indent() => new string(' ', Math.Max(1, 25 - sb.Length)); } #endif } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompilationInfo.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompilationInfo.cs index 850846cf288d3..dba088035ce8b 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompilationInfo.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompilationInfo.cs @@ -47,16 +47,7 @@ public string Name [MemberNotNull(nameof(_name))] set { - if (value == null) - { - throw new ArgumentNullException(nameof(Name)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.Format(SR.InvalidEmptyArgument, nameof(Name)), nameof(Name)); - } - + ArgumentException.ThrowIfNullOrEmpty(value, nameof(Name)); _name = value; } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs index 07a3d1b927cd3..96ca051263462 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs @@ -51,6 +51,9 @@ internal abstract class RegexCompiler private static readonly MethodInfo s_spanIndexOfAnyCharCharChar = typeof(MemoryExtensions).GetMethod("IndexOfAny", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(0) })!.MakeGenericMethod(typeof(char)); private static readonly MethodInfo s_spanIndexOfAnySpan = typeof(MemoryExtensions).GetMethod("IndexOfAny", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) })!.MakeGenericMethod(typeof(char)); private static readonly MethodInfo s_spanLastIndexOfChar = typeof(MemoryExtensions).GetMethod("LastIndexOf", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), Type.MakeGenericMethodParameter(0) })!.MakeGenericMethod(typeof(char)); + private static readonly MethodInfo s_spanLastIndexOfAnyCharChar = typeof(MemoryExtensions).GetMethod("LastIndexOfAny", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(0) })!.MakeGenericMethod(typeof(char)); + private static readonly MethodInfo s_spanLastIndexOfAnyCharCharChar = typeof(MemoryExtensions).GetMethod("LastIndexOfAny", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(0) })!.MakeGenericMethod(typeof(char)); + private static readonly MethodInfo s_spanLastIndexOfAnySpan = typeof(MemoryExtensions).GetMethod("LastIndexOfAny", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) })!.MakeGenericMethod(typeof(char)); private static readonly MethodInfo s_spanLastIndexOfSpan = typeof(MemoryExtensions).GetMethod("LastIndexOf", new Type[] { typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)), typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) })!.MakeGenericMethod(typeof(char)); private static readonly MethodInfo s_spanSliceIntMethod = typeof(ReadOnlySpan).GetMethod("Slice", new Type[] { typeof(int) })!; private static readonly MethodInfo s_spanSliceIntIntMethod = typeof(ReadOnlySpan).GetMethod("Slice", new Type[] { typeof(int), typeof(int) })!; @@ -300,8 +303,8 @@ private void Mvfldloc(FieldInfo ft, LocalBuilder lt) /// Returned a rented local to the pool. private struct RentedLocalBuilder : IDisposable { - private Stack _pool; - private LocalBuilder _local; + private readonly Stack _pool; + private readonly LocalBuilder _local; internal RentedLocalBuilder(Stack pool, LocalBuilder local) { @@ -465,134 +468,173 @@ FindNextStartingPositionMode.FixedSets_LeftToRight_CaseInsensitive or // searching is required; otherwise, false. bool GenerateAnchors() { - // Generate anchor checks. - if ((_code.FindOptimizations.LeadingAnchor & (RegexPrefixAnalyzer.Beginning | RegexPrefixAnalyzer.Start | RegexPrefixAnalyzer.EndZ | RegexPrefixAnalyzer.End | RegexPrefixAnalyzer.Bol)) != 0) + Label label; + + // Anchors that fully implement FindFirstChar, with a check that leads to immediate success or failure determination. + switch (_code.FindOptimizations.FindMode) { - switch (_code.FindOptimizations.LeadingAnchor) - { - case RegexPrefixAnalyzer.Beginning: - { - Label l1 = DefineLabel(); - Ldloc(pos); - Ldthisfld(s_runtextbegField); - Ble(l1); - Br(returnFalse); - MarkLabel(l1); - } + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning: + label = DefineLabel(); + Ldloc(pos); + Ldthisfld(s_runtextbegField); + Ble(label); + Br(returnFalse); + MarkLabel(label); + Ldc(1); + Ret(); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start: + label = DefineLabel(); + Ldloc(pos); + Ldthisfld(s_runtextstartField); + Ble(label); + Br(returnFalse); + MarkLabel(label); + Ldc(1); + Ret(); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ: + label = DefineLabel(); + Ldloc(pos); + Ldloc(end); + Ldc(1); + Sub(); + Bge(label); + Ldthis(); + Ldloc(end); + Ldc(1); + Sub(); + Stfld(s_runtextposField); + MarkLabel(label); + Ldc(1); + Ret(); + return true; + + case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End: + label = DefineLabel(); + Ldloc(pos); + Ldloc(end); + Bge(label); + Ldthis(); + Ldloc(end); + Stfld(s_runtextposField); + MarkLabel(label); + Ldc(1); + Ret(); + return true; + + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End: + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ: + // Jump to the end, minus the min required length, which in this case is actually the fixed length. + { + int extraNewlineBump = _code.FindOptimizations.FindMode == FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ ? 1 : 0; + label = DefineLabel(); + Ldloc(pos); + Ldloc(end); + Ldc(_code.Tree.MinRequiredLength + extraNewlineBump); + Sub(); + Bge(label); + Ldthis(); + Ldloc(end); + Ldc(_code.Tree.MinRequiredLength + extraNewlineBump); + Sub(); + Stfld(s_runtextposField); + MarkLabel(label); Ldc(1); Ret(); return true; + } + } - case RegexPrefixAnalyzer.Start: - { - Label l1 = DefineLabel(); - Ldloc(pos); - Ldthisfld(s_runtextstartField); - Ble(l1); - Br(returnFalse); - MarkLabel(l1); - } + // Now handle anchors that boost the position but don't determine immediate success or failure. + + switch (_code.FindOptimizations.LeadingAnchor) + { + case RegexNodeKind.Bol: + { + // Optimize the handling of a Beginning-Of-Line (BOL) anchor. BOL is special, in that unlike + // other anchors like Beginning, there are potentially multiple places a BOL can match. So unlike + // the other anchors, which all skip all subsequent processing if found, with BOL we just use it + // to boost our position to the next line, and then continue normally with any prefix or char class searches. + + label = DefineLabel(); + + // if (pos > runtextbeg... + Ldloc(pos!); + Ldthisfld(s_runtextbegField); + Ble(label); + + // ... && inputSpan[pos - 1] != '\n') { ... } + Ldloca(inputSpan); + Ldloc(pos); Ldc(1); - Ret(); - return true; + Sub(); + Call(s_spanGetItemMethod); + LdindU2(); + Ldc('\n'); + Beq(label); - case RegexPrefixAnalyzer.EndZ: + // int tmp = inputSpan.Slice(pos).IndexOf('\n'); + Ldloca(inputSpan); + Ldloc(pos); + Call(s_spanSliceIntMethod); + Ldc('\n'); + Call(s_spanIndexOfChar); + using (RentedLocalBuilder newlinePos = RentInt32Local()) { - Label l1 = DefineLabel(); + Stloc(newlinePos); + + // if (newlinePos < 0 || newlinePos + pos + 1 > end) + // { + // base.runtextpos = end; + // return false; + // } + Ldloc(newlinePos); + Ldc(0); + Blt(returnFalse); + Ldloc(newlinePos); Ldloc(pos); - Ldloc(end); + Add(); Ldc(1); - Sub(); - Bge(l1); - Ldthis(); + Add(); Ldloc(end); - Ldc(1); - Sub(); - Stfld(s_runtextposField); - MarkLabel(l1); - } - Ldc(1); - Ret(); - return true; + Bgt(returnFalse); - case RegexPrefixAnalyzer.End: - { - Label l1 = DefineLabel(); + // pos += newlinePos + 1; Ldloc(pos); - Ldloc(end); - Bge(l1); - Ldthis(); - Ldloc(end); - Stfld(s_runtextposField); - MarkLabel(l1); + Ldloc(newlinePos); + Add(); + Ldc(1); + Add(); + Stloc(pos); } - Ldc(1); - Ret(); - return true; - case RegexPrefixAnalyzer.Bol: - { - // Optimize the handling of a Beginning-Of-Line (BOL) anchor. BOL is special, in that unlike - // other anchors like Beginning, there are potentially multiple places a BOL can match. So unlike - // the other anchors, which all skip all subsequent processing if found, with BOL we just use it - // to boost our position to the next line, and then continue normally with any prefix or char class searches. - - Label atBeginningOfLine = DefineLabel(); - - // if (pos > runtextbeg... - Ldloc(pos!); - Ldthisfld(s_runtextbegField); - Ble(atBeginningOfLine); + MarkLabel(label); + } + break; + } - // ... && inputSpan[pos - 1] != '\n') { ... } - Ldloca(inputSpan); - Ldloc(pos); - Ldc(1); - Sub(); - Call(s_spanGetItemMethod); - LdindU2(); - Ldc('\n'); - Beq(atBeginningOfLine); - - // int tmp = inputSpan.Slice(pos).IndexOf('\n'); - Ldloca(inputSpan); - Ldloc(pos); - Call(s_spanSliceIntMethod); - Ldc('\n'); - Call(s_spanIndexOfChar); - using (RentedLocalBuilder newlinePos = RentInt32Local()) - { - Stloc(newlinePos); - - // if (newlinePos < 0 || newlinePos + pos + 1 > end) - // { - // base.runtextpos = end; - // return false; - // } - Ldloc(newlinePos); - Ldc(0); - Blt(returnFalse); - Ldloc(newlinePos); - Ldloc(pos); - Add(); - Ldc(1); - Add(); - Ldloc(end); - Bgt(returnFalse); - - // pos += newlinePos + 1; - Ldloc(pos); - Ldloc(newlinePos); - Add(); - Ldc(1); - Add(); - Stloc(pos); - } - - MarkLabel(atBeginningOfLine); - } + switch (_code.FindOptimizations.TrailingAnchor) + { + case RegexNodeKind.End or RegexNodeKind.EndZ when _code.FindOptimizations.MaxPossibleLength is int maxLength: + // Jump to the end, minus the max allowed length. + { + int extraNewlineBump = _code.FindOptimizations.FindMode == FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ ? 1 : 0; + label = DefineLabel(); + Ldloc(pos); + Ldloc(end); + Ldc(maxLength + extraNewlineBump); + Sub(); + Bge(label); + Ldloc(end); + Ldc(maxLength + extraNewlineBump); + Sub(); + Stloc(pos); + MarkLabel(label); break; - } + } } return false; @@ -773,7 +815,7 @@ void EmitFixedSet_LeftToRight() // if (!CharInClass(slice[i + 1], prefix[1], "...")) continue; // if (!CharInClass(slice[i + 2], prefix[2], "...")) continue; // ... - Debug.Assert(setIndex == 0 || setIndex == 1); + Debug.Assert(setIndex is 0 or 1); for ( ; setIndex < sets.Count; setIndex++) { Debug.Assert(needLoop); @@ -834,7 +876,7 @@ void EmitLiteralAfterAtomicLoop() Debug.Assert(_code.FindOptimizations.LiteralAfterLoop is not null); (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Literal) target = _code.FindOptimizations.LiteralAfterLoop.Value; - Debug.Assert(target.LoopNode.Type is RegexNode.Setloop or RegexNode.Setlazy or RegexNode.Setloopatomic); + Debug.Assert(target.LoopNode.Kind is RegexNodeKind.Setloop or RegexNodeKind.Setlazy or RegexNodeKind.Setloopatomic); Debug.Assert(target.LoopNode.N == int.MaxValue); // while (true) @@ -1003,7 +1045,7 @@ protected void EmitGo() // Get the root Capture node of the tree. RegexNode node = _code.Tree.Root; - Debug.Assert(node.Type == RegexNode.Capture, "Every generated tree should begin with a capture node"); + Debug.Assert(node.Kind == RegexNodeKind.Capture, "Every generated tree should begin with a capture node"); Debug.Assert(node.ChildCount() == 1, "Capture nodes should have one child"); // Skip the Capture node. We handle the implicit root capture specially. @@ -1012,9 +1054,9 @@ protected void EmitGo() // In some limited cases, FindFirstChar will only return true if it successfully matched the whole expression. // We can special case these to do essentially nothing in Go other than emit the capture. - switch (node.Type) + switch (node.Kind) { - case RegexNode.Multi or RegexNode.Notone or RegexNode.One or RegexNode.Set when !IsCaseInsensitive(node): + case RegexNodeKind.Multi or RegexNodeKind.Notone or RegexNodeKind.One or RegexNodeKind.Set when !IsCaseInsensitive(node): // This is the case for single and multiple characters, though the whole thing is only guaranteed // to have been validated in FindFirstChar when doing case-sensitive comparison. // base.Capture(0, base.runtextpos, base.runtextpos + node.Str.Length); @@ -1025,11 +1067,11 @@ protected void EmitGo() Ldc(0); Ldthisfld(s_runtextposField); Dup(); - Ldc(node.Type == RegexNode.Multi ? node.Str!.Length : 1); + Ldc(node.Kind == RegexNodeKind.Multi ? node.Str!.Length : 1); Add(); Call(s_captureMethod); Ldthisfld(s_runtextposField); - Ldc(node.Type == RegexNode.Multi ? node.Str!.Length : 1); + Ldc(node.Kind == RegexNodeKind.Multi ? node.Str!.Length : 1); Add(); Stfld(s_runtextposField); Ret(); @@ -1227,7 +1269,7 @@ void TransferSliceStaticPosToPos() // Emits the code for an alternation. void EmitAlternation(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Alternate, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Alternate, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() >= 2, $"Expected at least 2 children, found {node.ChildCount()}"); int childCount = node.ChildCount(); @@ -1238,7 +1280,7 @@ void EmitAlternation(RegexNode node) // Both atomic and non-atomic are supported. While a parent RegexNode.Atomic node will itself // successfully prevent backtracking into this child node, we can emit better / cheaper code // for an Alternate when it is atomic, so we still take it into account here. - Debug.Assert(node.Next is not null); + Debug.Assert(node.Parent is not null); bool isAtomic = node.IsAtomicByParent(); // Label to jump to when any branch completes successfully. @@ -1404,7 +1446,7 @@ void EmitAlternation(RegexNode node) // Emits the code to handle a backreference. void EmitBackreference(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Ref, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Backreference, $"Unexpected type: {node.Kind}"); int capnum = RegexParser.MapCaptureNumber(node.M, _code!.Caps); @@ -1496,7 +1538,7 @@ void EmitBackreference(RegexNode node) // Emits the code for an if(backreference)-then-else conditional. void EmitBackreferenceConditional(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Testref, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.BackreferenceConditional, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 2, $"Expected 2 children, found {node.ChildCount()}"); bool isAtomic = node.IsAtomicByParent(); @@ -1510,7 +1552,7 @@ void EmitBackreferenceConditional(RegexNode node) // Get the "yes" branch and the "no" branch. The "no" branch is optional in syntax and is thus // somewhat likely to be Empty. RegexNode yesBranch = node.Child(0); - RegexNode? noBranch = node.Child(1) is { Type: not RegexNode.Empty } childNo ? childNo : null; + RegexNode? noBranch = node.Child(1) is { Kind: not RegexNodeKind.Empty } childNo ? childNo : null; Label originalDoneLabel = doneLabel; Label refNotMatched = DefineLabel(); @@ -1642,7 +1684,7 @@ void EmitBackreferenceConditional(RegexNode node) // Emits the code for an if(expression)-then-else conditional. void EmitExpressionConditional(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Testgroup, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.ExpressionConditional, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 3, $"Expected 3 children, found {node.ChildCount()}"); bool isAtomic = node.IsAtomicByParent(); @@ -1658,7 +1700,7 @@ void EmitExpressionConditional(RegexNode node) // Get the "yes" branch and the "no" branch. The "no" branch is optional in syntax and is thus // somewhat likely to be Empty. RegexNode yesBranch = node.Child(1); - RegexNode? noBranch = node.Child(2) is { Type: not RegexNode.Empty } childNo ? childNo : null; + RegexNode? noBranch = node.Child(2) is { Kind: not RegexNodeKind.Empty } childNo ? childNo : null; Label originalDoneLabel = doneLabel; Label expressionNotMatched = DefineLabel(); @@ -1822,7 +1864,7 @@ void EmitExpressionConditional(RegexNode node) // Emits the code for a Capture node. void EmitCapture(RegexNode node, RegexNode? subsequent = null) { - Debug.Assert(node.Type is RegexNode.Capture, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Capture, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); int capnum = RegexParser.MapCaptureNumber(node.M, _code!.Caps); @@ -1939,7 +1981,7 @@ void EmitUncaptureUntil(LocalBuilder startingCapturePos) // Emits the code to handle a positive lookahead assertion. void EmitPositiveLookaheadAssertion(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Require, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.PositiveLookaround, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Lookarounds are implicitly atomic. Store the original done label to reset at the end. @@ -1970,7 +2012,7 @@ void EmitPositiveLookaheadAssertion(RegexNode node) // Emits the code to handle a negative lookahead assertion. void EmitNegativeLookaheadAssertion(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Prevent, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.NegativeLookaround, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Lookarounds are implicitly atomic. Store the original done label to reset at the end. @@ -2020,110 +2062,110 @@ void EmitNode(RegexNode node, RegexNode? subsequent = null, bool emitLengthCheck return; } - switch (node.Type) + switch (node.Kind) { - case RegexNode.Beginning: - case RegexNode.Start: - case RegexNode.Bol: - case RegexNode.Eol: - case RegexNode.End: - case RegexNode.EndZ: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: EmitAnchors(node); break; - case RegexNode.Boundary: - case RegexNode.NonBoundary: - case RegexNode.ECMABoundary: - case RegexNode.NonECMABoundary: + case RegexNodeKind.Boundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.NonECMABoundary: EmitBoundary(node); break; - case RegexNode.Multi: + case RegexNodeKind.Multi: EmitMultiChar(node, emitLengthChecksIfRequired); break; - case RegexNode.One: - case RegexNode.Notone: - case RegexNode.Set: + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: EmitSingleChar(node, emitLengthChecksIfRequired); break; - case RegexNode.Oneloop: - case RegexNode.Notoneloop: - case RegexNode.Setloop: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Setloop: EmitSingleCharLoop(node, subsequent, emitLengthChecksIfRequired); break; - case RegexNode.Onelazy: - case RegexNode.Notonelazy: - case RegexNode.Setlazy: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Setlazy: EmitSingleCharLazy(node, subsequent, emitLengthChecksIfRequired); break; - case RegexNode.Oneloopatomic: - case RegexNode.Notoneloopatomic: - case RegexNode.Setloopatomic: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Setloopatomic: EmitSingleCharAtomicLoop(node); break; - case RegexNode.Loop: + case RegexNodeKind.Loop: EmitLoop(node); break; - case RegexNode.Lazyloop: + case RegexNodeKind.Lazyloop: EmitLazy(node); break; - case RegexNode.Alternate: + case RegexNodeKind.Alternate: EmitAlternation(node); break; - case RegexNode.Concatenate: + case RegexNodeKind.Concatenate: EmitConcatenation(node, subsequent, emitLengthChecksIfRequired); break; - case RegexNode.Atomic: + case RegexNodeKind.Atomic: EmitAtomic(node, subsequent); break; - case RegexNode.Ref: + case RegexNodeKind.Backreference: EmitBackreference(node); break; - case RegexNode.Testref: + case RegexNodeKind.BackreferenceConditional: EmitBackreferenceConditional(node); break; - case RegexNode.Testgroup: + case RegexNodeKind.ExpressionConditional: EmitExpressionConditional(node); break; - case RegexNode.Capture: + case RegexNodeKind.Capture: EmitCapture(node, subsequent); break; - case RegexNode.Require: + case RegexNodeKind.PositiveLookaround: EmitPositiveLookaheadAssertion(node); break; - case RegexNode.Prevent: + case RegexNodeKind.NegativeLookaround: EmitNegativeLookaheadAssertion(node); break; - case RegexNode.Nothing: + case RegexNodeKind.Nothing: BrFar(doneLabel); break; - case RegexNode.Empty: + case RegexNodeKind.Empty: // Emit nothing. break; - case RegexNode.UpdateBumpalong: + case RegexNodeKind.UpdateBumpalong: EmitUpdateBumpalong(node); break; default: - Debug.Fail($"Unexpected node type: {node.Type}"); + Debug.Fail($"Unexpected node type: {node.Kind}"); break; } } @@ -2131,7 +2173,7 @@ void EmitNode(RegexNode node, RegexNode? subsequent = null, bool emitLengthCheck // Emits the node for an atomic. void EmitAtomic(RegexNode node, RegexNode? subsequent) { - Debug.Assert(node.Type is RegexNode.Atomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Atomic, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); // Atomic simply outputs the code for the child, but it ensures that any done label left @@ -2147,7 +2189,7 @@ void EmitAtomic(RegexNode node, RegexNode? subsequent) // it should bump from this location rather than from the original location. void EmitUpdateBumpalong(RegexNode node) { - Debug.Assert(node.Type is RegexNode.UpdateBumpalong, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.UpdateBumpalong, $"Unexpected type: {node.Kind}"); // if (base.runtextpos < pos) // { @@ -2167,7 +2209,7 @@ void EmitUpdateBumpalong(RegexNode node) // Emits code for a concatenation void EmitConcatenation(RegexNode node, RegexNode? subsequent, bool emitLengthChecksIfRequired) { - Debug.Assert(node.Type is RegexNode.Concatenate, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Concatenate, $"Unexpected type: {node.Kind}"); Debug.Assert(node.ChildCount() >= 2, $"Expected at least 2 children, found {node.ChildCount()}"); // Emit the code for each child one after the other. @@ -2198,7 +2240,7 @@ void EmitConcatenation(RegexNode node, RegexNode? subsequent, bool emitLengthChe for (int i = index + 1; i < childCount; i++) { RegexNode next = node.Child(i); - if (next.Type is not RegexNode.UpdateBumpalong) // skip node types that don't have a semantic impact + if (next.Kind is not RegexNodeKind.UpdateBumpalong) // skip node types that don't have a semantic impact { return next; } @@ -2211,7 +2253,7 @@ void EmitConcatenation(RegexNode node, RegexNode? subsequent, bool emitLengthChe // Emits the code to handle a single-character match. void EmitSingleChar(RegexNode node, bool emitLengthCheck = true, LocalBuilder? offset = null) { - Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Type}"); + Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Kind}"); // This only emits a single check, but it's called from the looping constructs in a loop // to generate the code for a single check, so we check for each "family" (one, notone, set) @@ -2254,7 +2296,7 @@ void EmitSingleChar(RegexNode node, bool emitLengthCheck = true, LocalBuilder? o // Emits the code to handle a boundary check on a character. void EmitBoundary(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Boundary or RegexNode.NonBoundary or RegexNode.ECMABoundary or RegexNode.NonECMABoundary, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Boundary or RegexNodeKind.NonBoundary or RegexNodeKind.ECMABoundary or RegexNodeKind.NonECMABoundary, $"Unexpected type: {node.Kind}"); // if (!IsBoundary(pos + sliceStaticPos, base.runtextbeg, end)) goto doneLabel; Ldthis(); @@ -2266,25 +2308,25 @@ void EmitBoundary(RegexNode node) } Ldthisfld(s_runtextbegField); Ldloc(end); - switch (node.Type) + switch (node.Kind) { - case RegexNode.Boundary: + case RegexNodeKind.Boundary: Call(s_isBoundaryMethod); BrfalseFar(doneLabel); break; - case RegexNode.NonBoundary: + case RegexNodeKind.NonBoundary: Call(s_isBoundaryMethod); BrtrueFar(doneLabel); break; - case RegexNode.ECMABoundary: + case RegexNodeKind.ECMABoundary: Call(s_isECMABoundaryMethod); BrfalseFar(doneLabel); break; default: - Debug.Assert(node.Type == RegexNode.NonECMABoundary); + Debug.Assert(node.Kind == RegexNodeKind.NonECMABoundary); Call(s_isECMABoundaryMethod); BrtrueFar(doneLabel); break; @@ -2294,13 +2336,13 @@ void EmitBoundary(RegexNode node) // Emits the code to handle various anchors. void EmitAnchors(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Beginning or RegexNode.Start or RegexNode.Bol or RegexNode.End or RegexNode.EndZ or RegexNode.Eol, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Beginning or RegexNodeKind.Start or RegexNodeKind.Bol or RegexNodeKind.End or RegexNodeKind.EndZ or RegexNodeKind.Eol, $"Unexpected type: {node.Kind}"); Debug.Assert(sliceStaticPos >= 0); - switch (node.Type) + switch (node.Kind) { - case RegexNode.Beginning: - case RegexNode.Start: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: if (sliceStaticPos > 0) { // If we statically know we've already matched part of the regex, there's no way we're at the @@ -2311,12 +2353,12 @@ void EmitAnchors(RegexNode node) { // if (pos > base.runtextbeg/start) goto doneLabel; Ldloc(pos); - Ldthisfld(node.Type == RegexNode.Beginning ? s_runtextbegField : s_runtextstartField); + Ldthisfld(node.Kind == RegexNodeKind.Beginning ? s_runtextbegField : s_runtextstartField); BneFar(doneLabel); } break; - case RegexNode.Bol: + case RegexNodeKind.Bol: if (sliceStaticPos > 0) { // if (slice[sliceStaticPos - 1] != '\n') goto doneLabel; @@ -2347,7 +2389,7 @@ void EmitAnchors(RegexNode node) } break; - case RegexNode.End: + case RegexNodeKind.End: // if (sliceStaticPos < slice.Length) goto doneLabel; Ldc(sliceStaticPos); Ldloca(slice); @@ -2355,7 +2397,7 @@ void EmitAnchors(RegexNode node) BltUnFar(doneLabel); break; - case RegexNode.EndZ: + case RegexNodeKind.EndZ: // if (sliceStaticPos < slice.Length - 1) goto doneLabel; Ldc(sliceStaticPos); Ldloca(slice); @@ -2363,9 +2405,9 @@ void EmitAnchors(RegexNode node) Ldc(1); Sub(); BltFar(doneLabel); - goto case RegexNode.Eol; + goto case RegexNodeKind.Eol; - case RegexNode.Eol: + case RegexNodeKind.Eol: // if (sliceStaticPos < slice.Length && slice[sliceStaticPos] != '\n') goto doneLabel; { Label success = DefineLabel(); @@ -2388,7 +2430,7 @@ void EmitAnchors(RegexNode node) // Emits the code to handle a multiple-character match. void EmitMultiChar(RegexNode node, bool emitLengthCheck = true) { - Debug.Assert(node.Type is RegexNode.Multi, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Multi, $"Unexpected type: {node.Kind}"); bool caseInsensitive = IsCaseInsensitive(node); @@ -2485,7 +2527,7 @@ void EmitMultiChar(RegexNode node, bool emitLengthCheck = true) // Emits the code to handle a backtracking, single-character loop. void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Notoneloop or RegexNode.Setloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop, $"Unexpected type: {node.Kind}"); // If this is actually a repeater, emit that instead; no backtracking necessary. if (node.M == node.N) @@ -2572,7 +2614,7 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL Ldloc(endingPos); BgeFar(doneLabel); - if (subsequent?.FindStartingCharacterOrString() is ValueTuple literal) + if (subsequent?.FindStartingLiteral() is ValueTuple literal) { // endingPos = inputSpan.Slice(startingPos, Math.Min(inputSpan.Length, endingPos + literal.Length - 1) - startingPos).LastIndexOf(literal); // if (endingPos < 0) @@ -2602,8 +2644,35 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL Ldloc(startingPos); Sub(); Call(s_spanSliceIntIntMethod); - Ldc(literal.Item1); - Call(s_spanLastIndexOfChar); + if (literal.Item3 is not null) + { + switch (literal.Item3.Length) + { + case 2: + Ldc(literal.Item3[0]); + Ldc(literal.Item3[1]); + Call(s_spanLastIndexOfAnyCharChar); + break; + + case 3: + Ldc(literal.Item3[0]); + Ldc(literal.Item3[1]); + Ldc(literal.Item3[2]); + Call(s_spanLastIndexOfAnyCharCharChar); + break; + + default: + Ldstr(literal.Item3); + Call(s_stringAsSpanMethod); + Call(s_spanLastIndexOfAnySpan); + break; + } + } + else + { + Ldc(literal.Item1); + Call(s_spanLastIndexOfChar); + } } Stloc(endingPos); Ldloc(endingPos); @@ -2646,7 +2715,7 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL void EmitSingleCharLazy(RegexNode node, RegexNode? subsequent = null, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.Type is RegexNode.Onelazy or RegexNode.Notonelazy or RegexNode.Setlazy, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy, $"Unexpected type: {node.Kind}"); // Emit the min iterations as a repeater. Any failures here don't necessitate backtracking, // as the lazy itself failed to match, and there's no backtracking possible by the individual @@ -2742,10 +2811,10 @@ void EmitSingleCharLazy(RegexNode node, RegexNode? subsequent = null, bool emitL // Now that we've appropriately advanced by one character and are set for what comes after the loop, // see if we can skip ahead more iterations by doing a search for a following literal. if (iterationCount is null && - node.Type is RegexNode.Notonelazy && + node.Kind is RegexNodeKind.Notonelazy && !IsCaseInsensitive(node) && - subsequent?.FindStartingCharacterOrString() is ValueTuple literal && - (literal.Item2?[0] ?? literal.Item1) != node.Ch) + subsequent?.FindStartingLiteral(4) is ValueTuple literal && // 5 == max optimized by IndexOfAny, and we need to reserve 1 for node.Ch + (literal.Item3 is not null ? !literal.Item3.Contains(node.Ch) : (literal.Item2?[0] ?? literal.Item1) != node.Ch)) // no overlap between node.Ch and the start of the literal { // e.g. "<[^>]*?>" // This lazy loop will consume all characters other than node.Ch until the subsequent literal. @@ -2754,9 +2823,30 @@ node.Type is RegexNode.Notonelazy && // startingPos = slice.IndexOfAny(node.Ch, literal); Ldloc(slice); - Ldc(node.Ch); - Ldc(literal.Item2?[0] ?? literal.Item1); - Call(s_spanIndexOfAnyCharChar); + if (literal.Item3 is not null) + { + switch (literal.Item3.Length) + { + case 2: + Ldc(node.Ch); + Ldc(literal.Item3[0]); + Ldc(literal.Item3[1]); + Call(s_spanIndexOfAnyCharCharChar); + break; + + default: + Ldstr(node.Ch + literal.Item3); + Call(s_stringAsSpanMethod); + Call(s_spanIndexOfAnySpan); + break; + } + } + else + { + Ldc(node.Ch); + Ldc(literal.Item2?[0] ?? literal.Item1); + Call(s_spanIndexOfAnyCharChar); + } Stloc(startingPos); // if ((uint)startingPos >= (uint)slice.Length) goto doneLabel; @@ -2782,9 +2872,9 @@ node.Type is RegexNode.Notonelazy && SliceInputSpan(); } else if (iterationCount is null && - node.Type is RegexNode.Setlazy && + node.Kind is RegexNodeKind.Setlazy && node.Str == RegexCharClass.AnyClass && - subsequent?.FindStartingCharacterOrString() is ValueTuple literal2) + subsequent?.FindStartingLiteral() is ValueTuple literal2) { // e.g. ".*?string" with RegexOptions.Singleline // This lazy loop will consume all characters until the subsequent literal. If the subsequent literal @@ -2798,6 +2888,30 @@ node.Type is RegexNode.Setlazy && Call(s_stringAsSpanMethod); Call(s_spanIndexOfSpan); } + else if (literal2.Item3 is not null) + { + switch (literal2.Item3.Length) + { + case 2: + Ldc(literal2.Item3[0]); + Ldc(literal2.Item3[1]); + Call(s_spanIndexOfAnyCharChar); + break; + + case 3: + Ldc(literal2.Item3[0]); + Ldc(literal2.Item3[1]); + Ldc(literal2.Item3[2]); + Call(s_spanIndexOfAnyCharCharChar); + break; + + default: + Ldstr(literal2.Item3); + Call(s_stringAsSpanMethod); + Call(s_spanIndexOfAnySpan); + break; + } + } else { Ldc(literal2.Item1); @@ -2889,7 +3003,7 @@ node.Type is RegexNode.Setlazy && void EmitLazy(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Lazyloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Lazyloop, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M < int.MaxValue, $"Unexpected M={node.M}"); Debug.Assert(node.N >= node.M, $"Unexpected M={node.M}, N={node.N}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); @@ -3134,7 +3248,7 @@ void EmitLazy(RegexNode node) // RegexNode.M is used for the number of iterations; RegexNode.N is ignored. void EmitSingleCharFixedRepeater(RegexNode node, bool emitLengthChecksIfRequired = true) { - Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Type}"); + Debug.Assert(node.IsOneFamily || node.IsNotoneFamily || node.IsSetFamily, $"Unexpected type: {node.Kind}"); int iterations = node.M; if (iterations == 0) @@ -3218,7 +3332,7 @@ void EmitSingleCharFixedRepeater(RegexNode node, bool emitLengthChecksIfRequired // Emits the code to handle a non-backtracking, variable-length loop around a single character comparison. void EmitSingleCharAtomicLoop(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Notoneloop or RegexNode.Notoneloopatomic or RegexNode.Setloop or RegexNode.Setloopatomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic, $"Unexpected type: {node.Kind}"); // If this is actually a repeater, emit that instead. if (node.M == node.N) @@ -3460,7 +3574,7 @@ void EmitSingleCharAtomicLoop(RegexNode node) // Emits the code to handle a non-backtracking optional zero-or-one loop. void EmitAtomicSingleCharZeroOrOne(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Notoneloop or RegexNode.Notoneloopatomic or RegexNode.Setloop or RegexNode.Setloopatomic, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M == 0 && node.N == 1); Label skipUpdatesLabel = DefineLabel(); @@ -3515,7 +3629,7 @@ void EmitAtomicSingleCharZeroOrOne(RegexNode node) void EmitLoop(RegexNode node) { - Debug.Assert(node.Type is RegexNode.Loop or RegexNode.Lazyloop, $"Unexpected type: {node.Type}"); + Debug.Assert(node.Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop, $"Unexpected type: {node.Kind}"); Debug.Assert(node.M < int.MaxValue, $"Unexpected M={node.M}"); Debug.Assert(node.N >= node.M, $"Unexpected M={node.M}, N={node.N}"); Debug.Assert(node.ChildCount() == 1, $"Expected 1 child, found {node.ChildCount()}"); @@ -3820,9 +3934,9 @@ private void InitializeCultureForGoIfNecessary() if (!needsCulture) { int[] codes = _code!.Codes; - for (int codepos = 0; codepos < codes.Length; codepos += RegexCode.OpcodeSize(codes[codepos])) + for (int codepos = 0; codepos < codes.Length; codepos += RegexCode.OpcodeSize((RegexOpcode)codes[codepos])) { - if ((codes[codepos] & RegexCode.Ci) == RegexCode.Ci) + if (((RegexOpcode)codes[codepos] & RegexOpcode.CaseInsensitive) == RegexOpcode.CaseInsensitive) { needsCulture = true; break; diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexFindOptimizations.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexFindOptimizations.cs index 7f8191e51752c..ee96e7e5cc847 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexFindOptimizations.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexFindOptimizations.cs @@ -10,7 +10,8 @@ namespace System.Text.RegularExpressions /// Contains state and provides operations related to finding the next location a match could possibly begin. internal sealed class RegexFindOptimizations { - /// The minimum required length an input need be to match the pattern. May be 0. + /// The minimum required length an input need be to match the pattern. + /// 0 is a valid minimum length. This value may also be the max (and hence fixed) length of the expression. private readonly int _minRequiredLength; /// True if the input should be processed right-to-left rather than left-to-right. private readonly bool _rightToLeft; @@ -27,30 +28,50 @@ public RegexFindOptimizations(RegexTree tree, CultureInfo culture) // Compute any anchor starting the expression. If there is one, we won't need to search for anything, // as we can just match at that single location. - LeadingAnchor = RegexPrefixAnalyzer.FindLeadingAnchor(tree); - if (_rightToLeft) + LeadingAnchor = RegexPrefixAnalyzer.FindLeadingAnchor(tree.Root); + if (_rightToLeft && LeadingAnchor == RegexNodeKind.Bol) { // Filter out Bol for RightToLeft, as we don't currently optimize for it. - LeadingAnchor &= ~RegexPrefixAnalyzer.Bol; + LeadingAnchor = RegexNodeKind.Unknown; } - if ((LeadingAnchor & (RegexPrefixAnalyzer.Beginning | RegexPrefixAnalyzer.Start | RegexPrefixAnalyzer.EndZ | RegexPrefixAnalyzer.End)) != 0) + if (LeadingAnchor is RegexNodeKind.Beginning or RegexNodeKind.Start or RegexNodeKind.EndZ or RegexNodeKind.End) { FindMode = (LeadingAnchor, _rightToLeft) switch { - (RegexPrefixAnalyzer.Beginning, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning, - (RegexPrefixAnalyzer.Beginning, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning, - (RegexPrefixAnalyzer.Start, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start, - (RegexPrefixAnalyzer.Start, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start, - (RegexPrefixAnalyzer.End, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End, - (RegexPrefixAnalyzer.End, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End, + (RegexNodeKind.Beginning, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning, + (RegexNodeKind.Beginning, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning, + (RegexNodeKind.Start, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start, + (RegexNodeKind.Start, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start, + (RegexNodeKind.End, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End, + (RegexNodeKind.End, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End, (_, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ, (_, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ, }; return; } + // Compute any anchor trailing the expression. If there is one, and we can also compute a fixed length + // for the whole expression, we can use that to quickly jump to the right location in the input. + if (!_rightToLeft) // haven't added FindNextStartingPositionMode support for RTL + { + TrailingAnchor = RegexPrefixAnalyzer.FindTrailingAnchor(tree.Root); + if (TrailingAnchor is RegexNodeKind.End or RegexNodeKind.EndZ && + tree.Root.ComputeMaxLength() is int maxLength) + { + Debug.Assert(maxLength >= _minRequiredLength, $"{maxLength} should have been greater than {_minRequiredLength} minimum"); + MaxPossibleLength = maxLength; + if (_minRequiredLength == maxLength) + { + FindMode = TrailingAnchor == RegexNodeKind.End ? + FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End : + FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ; + return; + } + } + } + // If there's a leading case-sensitive substring, just use IndexOf and inherit all of its optimizations. - string caseSensitivePrefix = RegexPrefixAnalyzer.FindCaseSensitivePrefix(tree); + string caseSensitivePrefix = RegexPrefixAnalyzer.FindCaseSensitivePrefix(tree.Root); if (caseSensitivePrefix.Length > 1) { LeadingCaseSensitivePrefix = caseSensitivePrefix; @@ -183,8 +204,18 @@ public RegexFindOptimizations(RegexTree tree, CultureInfo culture) /// Gets the selected mode for performing the next operation public FindNextStartingPositionMode FindMode { get; } = FindNextStartingPositionMode.NoSearch; - /// Gets the leading anchor, if one exists (RegexPrefixAnalyzer.Bol, etc). - public int LeadingAnchor { get; } + /// Gets the leading anchor (e.g. RegexNodeKind.Bol) if one exists and was computed. + public RegexNodeKind LeadingAnchor { get; } + + /// Gets the trailing anchor (e.g. RegexNodeKind.Bol) if one exists and was computed. + public RegexNodeKind TrailingAnchor { get; } + + /// The maximum possible length an input could be to match the pattern. + /// + /// This is currently only set when is found to be an end anchor. + /// That can be expanded in the future as needed. + /// + public int? MaxPossibleLength { get; } /// Gets the leading prefix. May be an empty string. public string LeadingCaseSensitivePrefix { get; } = string.Empty; @@ -230,7 +261,7 @@ public bool TryFindNextStartingPosition(ReadOnlySpan textSpan, ref int pos // other anchors like Beginning, there are potentially multiple places a BOL can match. So unlike // the other anchors, which all skip all subsequent processing if found, with BOL we just use it // to boost our position to the next line, and then continue normally with any searches. - if (LeadingAnchor == RegexPrefixAnalyzer.Bol) + if (LeadingAnchor == RegexNodeKind.Bol) { // If we're not currently positioned at the beginning of a line (either // the beginning of the string or just after a line feed), find the next @@ -315,6 +346,20 @@ public bool TryFindNextStartingPosition(ReadOnlySpan textSpan, ref int pos } return true; + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ: + if (pos < end - _minRequiredLength - 1) + { + pos = end - _minRequiredLength - 1; + } + return true; + + case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End: + if (pos < end - _minRequiredLength) + { + pos = end - _minRequiredLength; + } + return true; + // There's a case-sensitive prefix. Search for it with ordinal IndexOf. case FindNextStartingPositionMode.LeadingPrefix_LeftToRight_CaseSensitive: @@ -626,7 +671,7 @@ public bool TryFindNextStartingPosition(ReadOnlySpan textSpan, ref int pos Debug.Assert(LiteralAfterLoop is not null); (RegexNode loopNode, (char Char, string? String, char[]? Chars) literal) = LiteralAfterLoop.GetValueOrDefault(); - Debug.Assert(loopNode.Type is RegexNode.Setloop or RegexNode.Setlazy or RegexNode.Setloopatomic); + Debug.Assert(loopNode.Kind is RegexNodeKind.Setloop or RegexNodeKind.Setlazy or RegexNodeKind.Setloopatomic); Debug.Assert(loopNode.N == int.MaxValue); int startingPos = pos; @@ -698,6 +743,11 @@ internal enum FindNextStartingPositionMode /// An "end" anchor at the beginning of the right-to-left pattern. This is rare. LeadingAnchor_RightToLeft_End, + /// An "end" anchor at the end of the pattern, with the pattern always matching a fixed-length expression. + TrailingAnchor_FixedLength_LeftToRight_End, + /// An "endz" anchor at the end of the pattern, with the pattern always matching a fixed-length expression. + TrailingAnchor_FixedLength_LeftToRight_EndZ, + /// A case-sensitive multi-character substring at the beginning of the pattern. LeadingPrefix_LeftToRight_CaseSensitive, /// A case-sensitive multi-character substring at the beginning of the right-to-left pattern. diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexGeneratorAttribute.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexGeneratorAttribute.cs index 5b55a41c4cad8..827a43fc2dbfb 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexGeneratorAttribute.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexGeneratorAttribute.cs @@ -1,6 +1,7 @@ // 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.CodeAnalysis; using System.Threading; namespace System.Text.RegularExpressions; @@ -12,14 +13,14 @@ public sealed class RegexGeneratorAttribute : Attribute { /// Initializes a new instance of the with the specified pattern. /// The regular expression pattern to match. - public RegexGeneratorAttribute(string pattern) : this (pattern, RegexOptions.None) + public RegexGeneratorAttribute([StringSyntax(StringSyntaxAttribute.Regex)] string pattern) : this (pattern, RegexOptions.None) { } /// Initializes a new instance of the with the specified pattern and options. /// The regular expression pattern to match. /// A bitwise combination of the enumeration values that modify the regular expression. - public RegexGeneratorAttribute(string pattern, RegexOptions options) : this (pattern, options, Timeout.Infinite) + public RegexGeneratorAttribute([StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options) : this (pattern, options, Timeout.Infinite) { } @@ -27,7 +28,7 @@ public RegexGeneratorAttribute(string pattern, RegexOptions options) : this (pat /// The regular expression pattern to match. /// A bitwise combination of the enumeration values that modify the regular expression. /// A time-out interval (milliseconds), or to indicate that the method should not time out. - public RegexGeneratorAttribute(string pattern, RegexOptions options, int matchTimeoutMilliseconds) + public RegexGeneratorAttribute([StringSyntax(StringSyntaxAttribute.Regex, "options")] string pattern, RegexOptions options, int matchTimeoutMilliseconds) { Pattern = pattern; Options = options; diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs index 3f3f2808a01ef..9f615754a808f 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs @@ -16,7 +16,7 @@ internal sealed class RegexInterpreter : RegexRunner private readonly RegexCode _code; private readonly TextInfo _textInfo; - private int _operator; + private RegexOpcode _operator; private int _codepos; private bool _rightToLeft; private bool _caseInsensitive; @@ -35,7 +35,7 @@ public RegexInterpreter(RegexCode code, CultureInfo culture) private void Advance(int i) { _codepos += i + 1; - SetOperator(_code.Codes[_codepos]); + SetOperator((RegexOpcode)_code.Codes[_codepos]); } private void Goto(int newpos) @@ -47,7 +47,7 @@ private void Goto(int newpos) } _codepos = newpos; - SetOperator(_code.Codes[newpos]); + SetOperator((RegexOpcode)_code.Codes[newpos]); } private void Trackto(int newpos) => runtrackpos = runtrack!.Length - newpos; @@ -122,21 +122,16 @@ private void Backtrack() runtrackpos++; #if DEBUG - if (runmatch!.IsDebug) - { - Debug.WriteLine(newpos < 0 ? - $" Backtracking (back2) to code position {-newpos}" : - $" Backtracking to code position {newpos}"); - } + Debug.WriteLineIf(Regex.EnableDebugTracing, $" Backtracking{(newpos < 0 ? " (back2)" : "")} to code position {Math.Abs(newpos)}"); #endif - int back = RegexCode.Back; + int back = (int)RegexOpcode.Backtracking; if (newpos < 0) { newpos = -newpos; - back = RegexCode.Back2; + back = (int)RegexOpcode.BacktrackingSecond; } - SetOperator(_code.Codes[newpos] | back); + SetOperator((RegexOpcode)(_code.Codes[newpos] | back)); // When branching backward, ensure storage. if (newpos < _codepos) @@ -148,11 +143,11 @@ private void Backtrack() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetOperator(int op) + private void SetOperator(RegexOpcode op) { - _operator = op & ~(RegexCode.Rtl | RegexCode.Ci); - _caseInsensitive = (op & RegexCode.Ci) != 0; - _rightToLeft = (op & RegexCode.Rtl) != 0; + _operator = op & ~(RegexOpcode.RightToLeft | RegexOpcode.CaseInsensitive); + _caseInsensitive = (op & RegexOpcode.CaseInsensitive) != 0; + _rightToLeft = (op & RegexOpcode.RightToLeft) != 0; } private void TrackPop() => runtrackpos++; @@ -334,7 +329,7 @@ protected override bool FindFirstChar() => protected override void Go() { - SetOperator(_code.Codes[0]); + SetOperator((RegexOpcode)_code.Codes[0]); _codepos = 0; int advance = -1; ReadOnlySpan inputSpan = runtext; @@ -349,26 +344,26 @@ protected override void Go() advance = -1; } #if DEBUG - if (runmatch!.IsDebug) + if (Regex.EnableDebugTracing) { - DumpState(); + DebugTraceCurrentState(); } #endif CheckTimeout(); switch (_operator) { - case RegexCode.Stop: + case RegexOpcode.Stop: return; - case RegexCode.Nothing: + case RegexOpcode.Nothing: break; - case RegexCode.Goto: + case RegexOpcode.Goto: Goto(Operand(0)); continue; - case RegexCode.Testref: + case RegexOpcode.TestBackreference: if (!IsMatched(Operand(0))) { break; @@ -376,47 +371,47 @@ protected override void Go() advance = 1; continue; - case RegexCode.Lazybranch: + case RegexOpcode.Lazybranch: TrackPush(runtextpos); advance = 1; continue; - case RegexCode.Lazybranch | RegexCode.Back: + case RegexOpcode.Lazybranch | RegexOpcode.Backtracking: TrackPop(); runtextpos = TrackPeek(); Goto(Operand(0)); continue; - case RegexCode.Setmark: + case RegexOpcode.Setmark: StackPush(runtextpos); TrackPush(); advance = 0; continue; - case RegexCode.Nullmark: + case RegexOpcode.Nullmark: StackPush(-1); TrackPush(); advance = 0; continue; - case RegexCode.Setmark | RegexCode.Back: - case RegexCode.Nullmark | RegexCode.Back: + case RegexOpcode.Setmark | RegexOpcode.Backtracking: + case RegexOpcode.Nullmark | RegexOpcode.Backtracking: StackPop(); break; - case RegexCode.Getmark: + case RegexOpcode.Getmark: StackPop(); TrackPush(StackPeek()); runtextpos = StackPeek(); advance = 0; continue; - case RegexCode.Getmark | RegexCode.Back: + case RegexOpcode.Getmark | RegexOpcode.Backtracking: TrackPop(); StackPush(TrackPeek()); break; - case RegexCode.Capturemark: + case RegexOpcode.Capturemark: if (Operand(1) != -1 && !IsMatched(Operand(1))) { break; @@ -434,7 +429,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Capturemark | RegexCode.Back: + case RegexOpcode.Capturemark | RegexOpcode.Backtracking: TrackPop(); StackPush(TrackPeek()); Uncapture(); @@ -444,7 +439,7 @@ protected override void Go() } break; - case RegexCode.Branchmark: + case RegexOpcode.Branchmark: StackPop(); if (runtextpos != StackPeek()) { @@ -461,7 +456,7 @@ protected override void Go() } continue; - case RegexCode.Branchmark | RegexCode.Back: + case RegexOpcode.Branchmark | RegexOpcode.Backtracking: TrackPop(2); StackPop(); runtextpos = TrackPeek(1); // Recall position @@ -469,12 +464,12 @@ protected override void Go() advance = 1; // Straight continue; - case RegexCode.Branchmark | RegexCode.Back2: + case RegexOpcode.Branchmark | RegexOpcode.BacktrackingSecond: TrackPop(); StackPush(TrackPeek()); // Recall old mark break; // Backtrack - case RegexCode.Lazybranchmark: + case RegexOpcode.Lazybranchmark: // We hit this the first time through a lazy loop and after each // successful match of the inner expression. It simply continues // on and doesn't loop. @@ -506,13 +501,13 @@ protected override void Go() advance = 1; continue; - case RegexCode.Lazybranchmark | RegexCode.Back: + case RegexOpcode.Lazybranchmark | RegexOpcode.Backtracking: { - // After the first time, Lazybranchmark | RegexCode.Back occurs + // After the first time, Lazybranchmark | RegexOpcode.Back occurs // with each iteration of the loop, and therefore with every attempted // match of the inner expression. We'll try to match the inner expression, // then go back to Lazybranchmark if successful. If the inner expression - // fails, we go to Lazybranchmark | RegexCode.Back2 + // fails, we go to Lazybranchmark | RegexOpcode.Back2 TrackPop(2); int pos = TrackPeek(1); TrackPush2(TrackPeek()); // Save old mark @@ -522,7 +517,7 @@ protected override void Go() } continue; - case RegexCode.Lazybranchmark | RegexCode.Back2: + case RegexOpcode.Lazybranchmark | RegexOpcode.BacktrackingSecond: // The lazy loop has failed. We'll do a true backtrack and // start over before the lazy loop. StackPop(); @@ -530,25 +525,25 @@ protected override void Go() StackPush(TrackPeek()); // Recall old mark break; - case RegexCode.Setcount: + case RegexOpcode.Setcount: StackPush(runtextpos, Operand(0)); TrackPush(); advance = 1; continue; - case RegexCode.Nullcount: + case RegexOpcode.Nullcount: StackPush(-1, Operand(0)); TrackPush(); advance = 1; continue; - case RegexCode.Setcount | RegexCode.Back: - case RegexCode.Nullcount | RegexCode.Back: - case RegexCode.Setjump | RegexCode.Back: + case RegexOpcode.Setcount | RegexOpcode.Backtracking: + case RegexOpcode.Nullcount | RegexOpcode.Backtracking: + case RegexOpcode.Setjump | RegexOpcode.Backtracking: StackPop(2); break; - case RegexCode.Branchcount: + case RegexOpcode.Branchcount: // StackPush: // 0: Mark // 1: Count @@ -573,7 +568,7 @@ protected override void Go() } continue; - case RegexCode.Branchcount | RegexCode.Back: + case RegexOpcode.Branchcount | RegexOpcode.Backtracking: // TrackPush: // 0: Previous mark // StackPush: @@ -592,7 +587,7 @@ protected override void Go() StackPush(TrackPeek(), StackPeek(1) - 1); // Recall old mark, old count break; - case RegexCode.Branchcount | RegexCode.Back2: + case RegexOpcode.Branchcount | RegexOpcode.BacktrackingSecond: // TrackPush: // 0: Previous mark // 1: Previous count @@ -600,7 +595,7 @@ protected override void Go() StackPush(TrackPeek(), TrackPeek(1)); // Recall old mark, old count break; // Backtrack - case RegexCode.Lazybranchcount: + case RegexOpcode.Lazybranchcount: // StackPush: // 0: Mark // 1: Count @@ -624,7 +619,7 @@ protected override void Go() } continue; - case RegexCode.Lazybranchcount | RegexCode.Back: + case RegexOpcode.Lazybranchcount | RegexOpcode.Backtracking: // TrackPush: // 0: Mark // 1: Count @@ -650,7 +645,7 @@ protected override void Go() } } - case RegexCode.Lazybranchcount | RegexCode.Back2: + case RegexOpcode.Lazybranchcount | RegexOpcode.BacktrackingSecond: // TrackPush: // 0: Previous mark // StackPush: @@ -661,13 +656,13 @@ protected override void Go() StackPush(TrackPeek(), StackPeek(1) - 1); // Recall old mark, count break; // Backtrack - case RegexCode.Setjump: + case RegexOpcode.Setjump: StackPush(Trackpos(), Crawlpos()); TrackPush(); advance = 0; continue; - case RegexCode.Backjump: + case RegexOpcode.Backjump: // StackPush: // 0: Saved trackpos // 1: Crawlpos @@ -679,7 +674,7 @@ protected override void Go() } break; - case RegexCode.Forejump: + case RegexOpcode.Forejump: // StackPush: // 0: Saved trackpos // 1: Crawlpos @@ -689,7 +684,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.Forejump | RegexCode.Back: + case RegexOpcode.Forejump | RegexOpcode.Backtracking: // TrackPush: // 0: Crawlpos TrackPop(); @@ -699,7 +694,7 @@ protected override void Go() } break; - case RegexCode.Bol: + case RegexOpcode.Bol: if (Leftchars() > 0 && inputSpan[runtextpos - 1] != '\n') { break; @@ -707,7 +702,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.Eol: + case RegexOpcode.Eol: if (Rightchars() > 0 && inputSpan[runtextpos] != '\n') { break; @@ -715,7 +710,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.Boundary: + case RegexOpcode.Boundary: if (!IsBoundary(runtextpos, runtextbeg, runtextend)) { break; @@ -723,7 +718,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.NonBoundary: + case RegexOpcode.NonBoundary: if (IsBoundary(runtextpos, runtextbeg, runtextend)) { break; @@ -731,7 +726,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.ECMABoundary: + case RegexOpcode.ECMABoundary: if (!IsECMABoundary(runtextpos, runtextbeg, runtextend)) { break; @@ -739,7 +734,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.NonECMABoundary: + case RegexOpcode.NonECMABoundary: if (IsECMABoundary(runtextpos, runtextbeg, runtextend)) { break; @@ -747,7 +742,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.Beginning: + case RegexOpcode.Beginning: if (Leftchars() > 0) { break; @@ -755,7 +750,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.Start: + case RegexOpcode.Start: if (runtextpos != runtextstart) { break; @@ -763,7 +758,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.EndZ: + case RegexOpcode.EndZ: if (Rightchars() > 1 || Rightchars() == 1 && inputSpan[runtextpos] != '\n') { break; @@ -771,7 +766,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.End: + case RegexOpcode.End: if (Rightchars() > 0) { break; @@ -779,7 +774,7 @@ protected override void Go() advance = 0; continue; - case RegexCode.One: + case RegexOpcode.One: if (Forwardchars() < 1 || Forwardcharnext(inputSpan) != (char)Operand(0)) { break; @@ -787,7 +782,7 @@ protected override void Go() advance = 1; continue; - case RegexCode.Notone: + case RegexOpcode.Notone: if (Forwardchars() < 1 || Forwardcharnext(inputSpan) == (char)Operand(0)) { break; @@ -795,7 +790,7 @@ protected override void Go() advance = 1; continue; - case RegexCode.Set: + case RegexOpcode.Set: if (Forwardchars() < 1) { break; @@ -811,7 +806,7 @@ protected override void Go() advance = 1; continue; - case RegexCode.Multi: + case RegexOpcode.Multi: if (!MatchString(_code.Strings[Operand(0)], inputSpan)) { break; @@ -819,7 +814,7 @@ protected override void Go() advance = 1; continue; - case RegexCode.Ref: + case RegexOpcode.Backreference: { int capnum = Operand(0); if (IsMatched(capnum)) @@ -840,7 +835,7 @@ protected override void Go() advance = 1; continue; - case RegexCode.Onerep: + case RegexOpcode.Onerep: { int c = Operand(1); if (Forwardchars() < c) @@ -860,7 +855,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Notonerep: + case RegexOpcode.Notonerep: { int c = Operand(1); if (Forwardchars() < c) @@ -880,7 +875,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Setrep: + case RegexOpcode.Setrep: { int c = Operand(1); if (Forwardchars() < c) @@ -909,8 +904,8 @@ protected override void Go() advance = 2; continue; - case RegexCode.Oneloop: - case RegexCode.Oneloopatomic: + case RegexOpcode.Oneloop: + case RegexOpcode.Oneloopatomic: { int len = Math.Min(Operand(1), Forwardchars()); char ch = (char)Operand(0); @@ -925,7 +920,7 @@ protected override void Go() } } - if (len > i && _operator == RegexCode.Oneloop) + if (len > i && _operator == RegexOpcode.Oneloop) { TrackPush(len - i - 1, runtextpos - Bump()); } @@ -933,8 +928,8 @@ protected override void Go() advance = 2; continue; - case RegexCode.Notoneloop: - case RegexCode.Notoneloopatomic: + case RegexOpcode.Notoneloop: + case RegexOpcode.Notoneloopatomic: { int len = Math.Min(Operand(1), Forwardchars()); char ch = (char)Operand(0); @@ -968,7 +963,7 @@ protected override void Go() } } - if (len > i && _operator == RegexCode.Notoneloop) + if (len > i && _operator == RegexOpcode.Notoneloop) { TrackPush(len - i - 1, runtextpos - Bump()); } @@ -976,8 +971,8 @@ protected override void Go() advance = 2; continue; - case RegexCode.Setloop: - case RegexCode.Setloopatomic: + case RegexOpcode.Setloop: + case RegexOpcode.Setloopatomic: { int len = Math.Min(Operand(1), Forwardchars()); int operand0 = Operand(0); @@ -1000,7 +995,7 @@ protected override void Go() } } - if (len > i && _operator == RegexCode.Setloop) + if (len > i && _operator == RegexOpcode.Setloop) { TrackPush(len - i - 1, runtextpos - Bump()); } @@ -1008,9 +1003,9 @@ protected override void Go() advance = 2; continue; - case RegexCode.Oneloop | RegexCode.Back: - case RegexCode.Notoneloop | RegexCode.Back: - case RegexCode.Setloop | RegexCode.Back: + case RegexOpcode.Oneloop | RegexOpcode.Backtracking: + case RegexOpcode.Notoneloop | RegexOpcode.Backtracking: + case RegexOpcode.Setloop | RegexOpcode.Backtracking: TrackPop(2); { int i = TrackPeek(); @@ -1024,9 +1019,9 @@ protected override void Go() advance = 2; continue; - case RegexCode.Onelazy: - case RegexCode.Notonelazy: - case RegexCode.Setlazy: + case RegexOpcode.Onelazy: + case RegexOpcode.Notonelazy: + case RegexOpcode.Setlazy: { int c = Math.Min(Operand(1), Forwardchars()); if (c > 0) @@ -1037,7 +1032,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Onelazy | RegexCode.Back: + case RegexOpcode.Onelazy | RegexOpcode.Backtracking: TrackPop(2); { int pos = TrackPeek(1); @@ -1057,7 +1052,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Notonelazy | RegexCode.Back: + case RegexOpcode.Notonelazy | RegexOpcode.Backtracking: TrackPop(2); { int pos = TrackPeek(1); @@ -1077,7 +1072,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.Setlazy | RegexCode.Back: + case RegexOpcode.Setlazy | RegexOpcode.Backtracking: TrackPop(2); { int pos = TrackPeek(1); @@ -1098,7 +1093,7 @@ protected override void Go() advance = 2; continue; - case RegexCode.UpdateBumpalong: + case RegexOpcode.UpdateBumpalong: // UpdateBumpalong should only exist in the code stream at such a point where the root // of the backtracking stack contains the runtextpos from the start of this Go call. Replace // that tracking value with the current runtextpos value if it's greater. @@ -1125,14 +1120,10 @@ protected override void Go() #if DEBUG [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal override void DumpState() + internal override void DebugTraceCurrentState() { - base.DumpState(); - Debug.WriteLine( - " " + - _code.OpcodeDescription(_codepos) + - ((_operator & RegexCode.Back) != 0 ? " Back" : "") + - ((_operator & RegexCode.Back2) != 0 ? " Back2" : "")); + base.DebugTraceCurrentState(); + Debug.WriteLine($" {_code.DescribeInstruction(_codepos)} {((_operator & RegexOpcode.Backtracking) != 0 ? " Back" : "")} {((_operator & RegexOpcode.BacktrackingSecond) != 0 ? " Back2" : "")}"); Debug.WriteLine(""); } #endif diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs index 8f5c0a3039596..fc16f586d948e 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs @@ -1,43 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// This RegexNode class is internal to the Regex package. -// It is built into a parsed tree for a regular expression. - -// Implementation notes: -// -// Since the node tree is a temporary data structure only used -// during compilation of the regexp to integer codes, it's -// designed for clarity and convenience rather than -// space efficiency. -// -// RegexNodes are built into a tree, linked by the _children list. -// Each node also has a _parent and _ichild member indicating -// its parent and which child # it is in its parent's list. -// -// RegexNodes come in as many types as there are constructs in -// a regular expression, for example, "concatenate", "alternate", -// "one", "rept", "group". There are also node types for basic -// peephole optimizations, e.g., "onerep", "notsetrep", etc. -// -// Because perl 5 allows "lookback" groups that scan backwards, -// each node also gets a "direction". Normally the value of -// boolean _backward = false. -// -// During parsing, top-level nodes are also stacked onto a parse -// stack (a stack of trees). For this purpose we have a _next -// pointer. [Note that to save a few bytes, we could overload the -// _parent pointer instead.] -// -// On the parse stack, each tree has a "role" - basically, the -// nonterminal in the grammar that the parser has currently -// assigned to the tree. That code is stored in _role. -// -// Finally, some of the different kinds of nodes have data. -// Two integers (for the looping constructs) are stored in -// _operands, an object (either a string or a set) -// is stored in _data - using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -46,107 +9,75 @@ namespace System.Text.RegularExpressions { + /// Represents a regex subexpression. internal sealed class RegexNode { - // RegexNode types - - // The following are leaves, and correspond to primitive operations - - public const int Oneloop = RegexCode.Oneloop; // c,n a* - public const int Notoneloop = RegexCode.Notoneloop; // c,n .* - public const int Setloop = RegexCode.Setloop; // set,n \d* - - public const int Onelazy = RegexCode.Onelazy; // c,n a*? - public const int Notonelazy = RegexCode.Notonelazy; // c,n .*? - public const int Setlazy = RegexCode.Setlazy; // set,n \d*? - - public const int One = RegexCode.One; // char a - public const int Notone = RegexCode.Notone; // char . [^a] - public const int Set = RegexCode.Set; // set [a-z] \w \s \d - - public const int Multi = RegexCode.Multi; // string abcdef - public const int Ref = RegexCode.Ref; // index \1 - - public const int Bol = RegexCode.Bol; // ^ - public const int Eol = RegexCode.Eol; // $ - public const int Boundary = RegexCode.Boundary; // \b - public const int NonBoundary = RegexCode.NonBoundary; // \B - public const int ECMABoundary = RegexCode.ECMABoundary; // \b - public const int NonECMABoundary = RegexCode.NonECMABoundary; // \B - public const int Beginning = RegexCode.Beginning; // \A - public const int Start = RegexCode.Start; // \G - public const int EndZ = RegexCode.EndZ; // \Z - public const int End = RegexCode.End; // \z - - public const int Oneloopatomic = RegexCode.Oneloopatomic; // c,n (?> a*) - public const int Notoneloopatomic = RegexCode.Notoneloopatomic; // c,n (?> .*) - public const int Setloopatomic = RegexCode.Setloopatomic; // set,n (?> \d*) - public const int UpdateBumpalong = RegexCode.UpdateBumpalong; - - // Interior nodes do not correspond to primitive operations, but - // control structures compositing other operations - - // Concat and alternate take n children, and can run forward or backwards - - public const int Nothing = 22; // [] - public const int Empty = 23; // () - - public const int Alternate = 24; // a|b - public const int Concatenate = 25; // ab - - public const int Loop = 26; // m,x * + ? {,} - public const int Lazyloop = 27; // m,x *? +? ?? {,}? - - public const int Capture = 28; // n () - capturing group - public const int Group = 29; // (?:) - noncapturing group - public const int Require = 30; // (?=) (?<=) - lookahead and lookbehind assertions - public const int Prevent = 31; // (?!) (?) - atomic subexpression - public const int Testref = 33; // (?(n) | ) - alternation, reference - public const int Testgroup = 34; // (?(...) | )- alternation, expression - /// empty bit from the node's options to store data on whether a node contains captures internal const RegexOptions HasCapturesFlag = (RegexOptions)(1 << 31); + /// The node's children. + /// null if no children, a if one child, or a if multiple children. private object? Children; - public int Type { get; private set; } + + /// The kind of expression represented by this node. + public RegexNodeKind Kind { get; private set; } + + /// A string associated with the node. + /// For a , this is the string from the expression. For an node, this is the character class string from . public string? Str { get; private set; } + + /// The character associated with the node. + /// For a or node, the character from the expression. public char Ch { get; private set; } + + /// The minimum number of iterations for a loop, or the capture group number for a capture or backreference. + /// No minimum is represented by 0. No capture group is represented by -1. public int M { get; private set; } + + /// The maximum number of iterations for a loop, or the uncapture group number for a balancing group. + /// No upper bound is represented by . No capture group is represented by -1. public int N { get; private set; } + + /// The options associated with the node. public RegexOptions Options; - public RegexNode? Next; - public RegexNode(int type, RegexOptions options) + /// The node's parent node in the tree. + /// + /// During parsing, top-level nodes are also stacked onto a parse stack (a stack of trees) using . + /// After parsing, is the node in the tree that has this node as or in . + /// + public RegexNode? Parent; + + public RegexNode(RegexNodeKind kind, RegexOptions options) { - Type = type; + Kind = kind; Options = options; } - public RegexNode(int type, RegexOptions options, char ch) + public RegexNode(RegexNodeKind kind, RegexOptions options, char ch) { - Type = type; + Kind = kind; Options = options; Ch = ch; } - public RegexNode(int type, RegexOptions options, string str) + public RegexNode(RegexNodeKind kind, RegexOptions options, string str) { - Type = type; + Kind = kind; Options = options; Str = str; } - public RegexNode(int type, RegexOptions options, int m) + public RegexNode(RegexNodeKind kind, RegexOptions options, int m) { - Type = type; + Kind = kind; Options = options; M = m; } - public RegexNode(int type, RegexOptions options, int m, int n) + public RegexNode(RegexNodeKind kind, RegexOptions options, int m, int n) { - Type = type; + Kind = kind; Options = options; M = m; N = n; @@ -168,7 +99,7 @@ public static RegexNode CreateOneWithCaseConversion(char ch, RegexOptions option // we can simply strip out the IgnoreCase option and make the node case-sensitive. if (!RegexCharClass.ParticipatesInCaseConversion(ch)) { - return new RegexNode(One, options & ~RegexOptions.IgnoreCase, ch); + return new RegexNode(RegexNodeKind.One, options & ~RegexOptions.IgnoreCase, ch); } // Create a set for the character, trying to include all case-insensitive equivalent characters. @@ -177,7 +108,7 @@ public static RegexNode CreateOneWithCaseConversion(char ch, RegexOptions option string stringSet = RegexCharClass.OneToStringClass(ch, culture, out bool resultIsCaseInsensitive); if (!resultIsCaseInsensitive) { - return new RegexNode(Set, options & ~RegexOptions.IgnoreCase, stringSet); + return new RegexNode(RegexNodeKind.Set, options & ~RegexOptions.IgnoreCase, stringSet); } // Otherwise, until we can get rid of ToLower usage at match time entirely (https://github.com/dotnet/runtime/issues/61048), @@ -186,14 +117,14 @@ public static RegexNode CreateOneWithCaseConversion(char ch, RegexOptions option } // Create a One node for the character. - return new RegexNode(One, options, ch); + return new RegexNode(RegexNodeKind.One, options, ch); } /// Reverses all children of a concatenation when in RightToLeft mode. public RegexNode ReverseConcatenationIfRightToLeft() { if ((Options & RegexOptions.RightToLeft) != 0 && - Type == Concatenate && + Kind == RegexNodeKind.Concatenate && ChildCount() > 1) { ((List)Children!).Reverse(); @@ -205,32 +136,38 @@ public RegexNode ReverseConcatenationIfRightToLeft() /// /// Pass type as OneLazy or OneLoop /// - private void MakeRep(int type, int min, int max) + private void MakeRep(RegexNodeKind kind, int min, int max) { - Type += type - One; + Kind += kind - RegexNodeKind.One; M = min; N = max; } private void MakeLoopAtomic() { - switch (Type) + switch (Kind) { - case Oneloop or Notoneloop or Setloop: + case RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop: // For loops, we simply change the Type to the atomic variant. // Atomic greedy loops should consume as many values as they can. - Type += Oneloopatomic - Oneloop; + Kind += RegexNodeKind.Oneloopatomic - RegexNodeKind.Oneloop; break; - case Onelazy or Notonelazy or Setlazy: + case RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy: // For lazy, we not only change the Type, we also lower the max number of iterations // to the minimum number of iterations, as they should end up matching as little as possible. - Type += Oneloopatomic - Onelazy; + Kind += RegexNodeKind.Oneloopatomic - RegexNodeKind.Onelazy; N = M; + if (N == 0) + { + Kind = RegexNodeKind.Empty; + Str = null; + Ch = '\0'; + } break; default: - Debug.Fail($"Unexpected type: {Type}"); + Debug.Fail($"Unexpected type: {Kind}"); break; } } @@ -240,7 +177,7 @@ private void MakeLoopAtomic() [Conditional("DEBUG")] private void ValidateFinalTreeInvariants() { - Debug.Assert(Type == Capture, "Every generated tree should begin with a capture node"); + Debug.Assert(Kind == RegexNodeKind.Capture, "Every generated tree should begin with a capture node"); var toExamine = new Stack(); toExamine.Push(this); @@ -253,95 +190,95 @@ private void ValidateFinalTreeInvariants() for (int i = 0; i < childCount; i++) { RegexNode child = node.Child(i); - Debug.Assert(child.Next == node, $"{child.Description()} missing reference to parent {node.Description()}"); + Debug.Assert(child.Parent == node, $"{child.Describe()} missing reference to parent {node.Describe()}"); toExamine.Push(child); } // Validate that we never see certain node types. - Debug.Assert(Type != Group, "All Group nodes should have been removed."); + Debug.Assert(Kind != RegexNodeKind.Group, "All Group nodes should have been removed."); // Validate node types and expected child counts. - switch (node.Type) + switch (node.Kind) { - case Group: + case RegexNodeKind.Group: Debug.Fail("All Group nodes should have been removed."); break; - case Beginning: - case Bol: - case Boundary: - case ECMABoundary: - case Empty: - case End: - case EndZ: - case Eol: - case Multi: - case NonBoundary: - case NonECMABoundary: - case Nothing: - case Notone: - case Notonelazy: - case Notoneloop: - case Notoneloopatomic: - case One: - case Onelazy: - case Oneloop: - case Oneloopatomic: - case Ref: - case Set: - case Setlazy: - case Setloop: - case Setloopatomic: - case Start: - case UpdateBumpalong: - Debug.Assert(childCount == 0, $"Expected zero children for {node.TypeName}, got {childCount}."); + case RegexNodeKind.Beginning: + case RegexNodeKind.Bol: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.Empty: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: + case RegexNodeKind.Eol: + case RegexNodeKind.Multi: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Nothing: + case RegexNodeKind.Notone: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.One: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Backreference: + case RegexNodeKind.Set: + case RegexNodeKind.Setlazy: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Start: + case RegexNodeKind.UpdateBumpalong: + Debug.Assert(childCount == 0, $"Expected zero children for {node.Kind}, got {childCount}."); break; - case Atomic: - case Capture: - case Lazyloop: - case Loop: - case Prevent: - case Require: - Debug.Assert(childCount == 1, $"Expected one and only one child for {node.TypeName}, got {childCount}."); + case RegexNodeKind.Atomic: + case RegexNodeKind.Capture: + case RegexNodeKind.Lazyloop: + case RegexNodeKind.Loop: + case RegexNodeKind.NegativeLookaround: + case RegexNodeKind.PositiveLookaround: + Debug.Assert(childCount == 1, $"Expected one and only one child for {node.Kind}, got {childCount}."); break; - case Testref: - Debug.Assert(childCount == 2, $"Expected two children for {node.TypeName}, got {childCount}"); + case RegexNodeKind.BackreferenceConditional: + Debug.Assert(childCount == 2, $"Expected two children for {node.Kind}, got {childCount}"); break; - case Testgroup: - Debug.Assert(childCount == 3, $"Expected three children for {node.TypeName}, got {childCount}"); + case RegexNodeKind.ExpressionConditional: + Debug.Assert(childCount == 3, $"Expected three children for {node.Kind}, got {childCount}"); break; - case Concatenate: - case Alternate: - Debug.Assert(childCount >= 2, $"Expected at least two children for {node.TypeName}, got {childCount}."); + case RegexNodeKind.Concatenate: + case RegexNodeKind.Alternate: + Debug.Assert(childCount >= 2, $"Expected at least two children for {node.Kind}, got {childCount}."); break; default: - Debug.Fail($"Unexpected node type: {node.Type}"); + Debug.Fail($"Unexpected node type: {node.Kind}"); break; } // Validate node configuration. - switch (node.Type) + switch (node.Kind) { - case Multi: + case RegexNodeKind.Multi: Debug.Assert(node.Str is not null, "Expect non-null multi string"); Debug.Assert(node.Str.Length >= 2, $"Expected {node.Str} to be at least two characters"); break; - case Set: - case Setloop: - case Setloopatomic: - case Setlazy: - Debug.Assert(!string.IsNullOrEmpty(node.Str), $"Expected non-null, non-empty string for {node.TypeName}."); + case RegexNodeKind.Set: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Setlazy: + Debug.Assert(!string.IsNullOrEmpty(node.Str), $"Expected non-null, non-empty string for {node.Kind}."); break; default: - Debug.Assert(node.Str is null, $"Expected null string for {node.TypeName}, got \"{node.Str}\"."); + Debug.Assert(node.Str is null, $"Expected null string for {node.Kind}, got \"{node.Str}\"."); break; } } @@ -358,12 +295,21 @@ private void ValidateFinalTreeInvariants() internal RegexNode FinalOptimize() { RegexNode rootNode = this; - Debug.Assert(rootNode.Type == Capture); - Debug.Assert(rootNode.Next is null); + Debug.Assert(rootNode.Kind == RegexNodeKind.Capture); + Debug.Assert(rootNode.Parent is null); Debug.Assert(rootNode.ChildCount() == 1); - if ((Options & RegexOptions.RightToLeft) == 0) // only apply optimization when LTR to avoid needing additional code for the rarer RTL case + // Only apply optimization when LTR to avoid needing additional code for the much rarer RTL case. + // Also only apply these optimizations when not using NonBacktracking, as these optimizations are + // all about avoiding things that are impactful for the backtracking engines but nops for non-backtracking. + if ((Options & (RegexOptions.RightToLeft | RegexOptions.NonBacktracking)) == 0) { + // Optimization: eliminate backtracking for loops. + // For any single-character loop (Oneloop, Notoneloop, Setloop), see if we can automatically convert + // that into its atomic counterpart (Oneloopatomic, Notoneloopatomic, Setloopatomic) based on what + // comes after it in the expression tree. + rootNode.FindAndMakeLoopsAtomic(); + // Optimization: backtracking removal at expression end. // If we find backtracking construct at the end of the regex, we can instead make it non-backtracking, // since nothing would ever backtrack into it anyway. Doing this then makes the construct available @@ -389,19 +335,19 @@ internal RegexNode FinalOptimize() RegexNode node = rootNode.Child(0); // skip implicit root capture node while (true) { - switch (node.Type) + switch (node.Kind) { - case Atomic: - case Concatenate: + case RegexNodeKind.Atomic: + case RegexNodeKind.Concatenate: node = node.Child(0); continue; - case Oneloop or Oneloopatomic or Notoneloop or Notoneloopatomic or Setloop or Setloopatomic when node.N == int.MaxValue: - case Onelazy or Notonelazy or Setlazy when node.N == int.MaxValue && !node.IsAtomicByParent(): - RegexNode? parent = node.Next; - if (parent != null && parent.Type == Concatenate) + case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when node.N == int.MaxValue: + case RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy when node.N == int.MaxValue && !node.IsAtomicByParent(): + RegexNode? parent = node.Parent; + if (parent != null && parent.Kind == RegexNodeKind.Concatenate) { - parent.InsertChild(1, new RegexNode(UpdateBumpalong, node.Options)); + parent.InsertChild(1, new RegexNode(RegexNodeKind.UpdateBumpalong, node.Options)); } break; } @@ -426,16 +372,12 @@ internal RegexNode FinalOptimize() /// private void EliminateEndingBacktracking() { - if (!StackHelper.TryEnsureSufficientExecutionStack()) + if (!StackHelper.TryEnsureSufficientExecutionStack() || + (Options & (RegexOptions.RightToLeft | RegexOptions.NonBacktracking)) != 0) { // If we can't recur further, just stop optimizing. - return; - } - - // RegexOptions.NonBacktracking doesn't support atomic groups, so when that option - // is set we don't want to create atomic groups where they weren't explicitly authored. - if ((Options & RegexOptions.NonBacktracking) != 0) - { + // We haven't done the work to validate this is correct for RTL. + // And NonBacktracking doesn't support atomic groups and doesn't have backtracking to be eliminated. return; } @@ -443,39 +385,35 @@ private void EliminateEndingBacktracking() RegexNode node = this; while (true) { - switch (node.Type) + switch (node.Kind) { // {One/Notone/Set}loops can be upgraded to {One/Notone/Set}loopatomic nodes, e.g. [abc]* => (?>[abc]*). // And {One/Notone/Set}lazys can similarly be upgraded to be atomic, which really makes them into repeaters // or even empty nodes. - case Oneloop: - case Notoneloop: - case Setloop: - case Onelazy: - case Notonelazy: - case Setlazy: + case RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop: + case RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy: node.MakeLoopAtomic(); break; // Just because a particular node is atomic doesn't mean all its descendants are. // Process them as well. - case Atomic: + case RegexNodeKind.Atomic: node = node.Child(0); continue; // For Capture and Concatenate, we just recur into their last child (only child in the case - // of Capture). However, if the child is Alternate, Loop, and Lazyloop, we can also make the + // of Capture). However, if the child is an alternation or loop, we can also make the // node itself atomic by wrapping it in an Atomic node. Since we later check to see whether a // node is atomic based on its parent or grandparent, we don't bother wrapping such a node in // an Atomic one if its grandparent is already Atomic. // e.g. [xyz](?:abc|def) => [xyz](?>abc|def) - case Capture: - case Concatenate: + case RegexNodeKind.Capture: + case RegexNodeKind.Concatenate: RegexNode existingChild = node.Child(node.ChildCount() - 1); - if ((existingChild.Type == Alternate || existingChild.Type == Loop || existingChild.Type == Lazyloop) && - (node.Next is null || node.Next.Type != Atomic)) // validate grandparent isn't atomic + if ((existingChild.Kind is RegexNodeKind.Alternate or RegexNodeKind.BackreferenceConditional or RegexNodeKind.ExpressionConditional or RegexNodeKind.Loop or RegexNodeKind.Lazyloop) && + (node.Parent is null || node.Parent.Kind != RegexNodeKind.Atomic)) // validate grandparent isn't atomic { - var atomic = new RegexNode(Atomic, existingChild.Options); + var atomic = new RegexNode(RegexNodeKind.Atomic, existingChild.Options); atomic.AddChild(existingChild); node.ReplaceChild(node.ChildCount() - 1, atomic); } @@ -483,23 +421,47 @@ private void EliminateEndingBacktracking() continue; // For alternate, we can recur into each branch separately. We use this iteration for the first branch. + // Conditionals are just like alternations in this regard. // e.g. abc*|def* => ab(?>c*)|de(?>f*) - case Alternate: + case RegexNodeKind.Alternate: + case RegexNodeKind.BackreferenceConditional: + case RegexNodeKind.ExpressionConditional: { int branches = node.ChildCount(); for (int i = 1; i < branches; i++) { node.Child(i).EliminateEndingBacktracking(); } + + if (node.Kind != RegexNodeKind.ExpressionConditional) // ReduceTestgroup will have already applied ending backtracking removal + { + node = node.Child(0); + continue; + } } - node = node.Child(0); - continue; + break; - // For Loop, we search to see if there's a viable last expression, and iff there - // is we recur into processing it. + // For {Lazy}Loop, we search to see if there's a viable last expression, and iff there + // is we recur into processing it. Also, as with the single-char lazy loops, LazyLoop + // can have its max iteration count dropped to its min iteration count, as there's no + // reason for it to match more than the minimal at the end; that in turn makes it a + // repeater, which results in better code generation. // e.g. (?:abc*)* => (?:ab(?>c*))* - case Loop: + // e.g. (abc*?)+? => (ab){1} + case RegexNodeKind.Lazyloop: + node.N = node.M; + goto case RegexNodeKind.Loop; + case RegexNodeKind.Loop: { + if (node.N == 1) + { + // If the loop has a max iteration count of 1 (e.g. it's an optional node), + // there's no possibility for conflict between multiple iterations, so + // we can process it. + node = node.Child(0); + continue; + } + RegexNode? loopDescendent = node.FindLastExpressionInLoopForAutoAtomic(); if (loopDescendent != null) { @@ -523,31 +485,31 @@ public bool IsAtomicByParent() { // Walk up the parent hierarchy. RegexNode child = this; - for (RegexNode? parent = child.Next; parent is not null; child = parent, parent = child.Next) + for (RegexNode? parent = child.Parent; parent is not null; child = parent, parent = child.Parent) { - switch (parent.Type) + switch (parent.Kind) { - case Atomic: - case Prevent: - case Require: + case RegexNodeKind.Atomic: + case RegexNodeKind.NegativeLookaround: + case RegexNodeKind.PositiveLookaround: // If the parent is atomic, so is the child. That's the whole purpose // of the Atomic node, and lookarounds are also implicitly atomic. return true; - case Alternate: - case Testref: + case RegexNodeKind.Alternate: + case RegexNodeKind.BackreferenceConditional: // Skip alternations. Each branch is considered independently, // so any atomicity applied to the alternation also applies to // each individual branch. This is true as well for conditional // backreferences, where each of the yes/no branches are independent. - case Testgroup when parent.Child(0) != child: + case RegexNodeKind.ExpressionConditional when parent.Child(0) != child: // As with alternations, each yes/no branch of an expression conditional // are independent from each other, but the conditional expression itself // can be backtracked into from each of the branches, so we can't make // it atomic just because the whole conditional is. - case Capture: + case RegexNodeKind.Capture: // Skip captures. They don't affect atomicity. - case Concatenate when parent.Child(parent.ChildCount() - 1) == child: + case RegexNodeKind.Concatenate when parent.Child(parent.ChildCount() - 1) == child: // If the parent is a concatenation and this is the last node, // any atomicity applying to the concatenation applies to this // node, too. @@ -567,17 +529,18 @@ public bool IsAtomicByParent() /// Removes redundant nodes from the subtree, and returns an optimized subtree. /// internal RegexNode Reduce() => - Type switch - { - Alternate => ReduceAlternation(), - Atomic => ReduceAtomic(), - Concatenate => ReduceConcatenation(), - Group => ReduceGroup(), - Loop or Lazyloop => ReduceLoops(), - Prevent => ReducePrevent(), - Set or Setloop or Setloopatomic or Setlazy => ReduceSet(), - Testgroup => ReduceTestgroup(), - Testref => ReduceTestref(), + Kind switch + { + RegexNodeKind.Alternate => ReduceAlternation(), + RegexNodeKind.Atomic => ReduceAtomic(), + RegexNodeKind.Concatenate => ReduceConcatenation(), + RegexNodeKind.Group => ReduceGroup(), + RegexNodeKind.Loop or RegexNodeKind.Lazyloop => ReduceLoops(), + RegexNodeKind.NegativeLookaround => ReducePrevent(), + RegexNodeKind.PositiveLookaround => ReduceRequire(), + RegexNodeKind.Set or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy => ReduceSet(), + RegexNodeKind.ExpressionConditional => ReduceTestgroup(), + RegexNodeKind.BackreferenceConditional => ReduceTestref(), _ => this, }; @@ -585,17 +548,14 @@ internal RegexNode Reduce() => /// /// Simple optimization for a concatenation or alternation: /// - if the node has only one child, use it instead - /// - if the node has zero children, turn it into an empty with the specified empty type + /// - if the node has zero children, turn it into an empty with Nothing for an alternation or Empty for a concatenation /// - private RegexNode ReplaceNodeIfUnnecessary(int emptyTypeIfNoChildren) + private RegexNode ReplaceNodeIfUnnecessary() { - Debug.Assert( - (Type == Alternate && emptyTypeIfNoChildren == Nothing) || - (Type == Concatenate && emptyTypeIfNoChildren == Empty)); - + Debug.Assert(Kind is RegexNodeKind.Alternate or RegexNodeKind.Concatenate); return ChildCount() switch { - 0 => new RegexNode(emptyTypeIfNoChildren, Options), + 0 => new RegexNode(Kind == RegexNodeKind.Alternate ? RegexNodeKind.Nothing : RegexNodeKind.Empty, Options), 1 => Child(0), _ => this, }; @@ -609,10 +569,10 @@ private RegexNode ReplaceNodeIfUnnecessary(int emptyTypeIfNoChildren) /// private RegexNode ReduceGroup() { - Debug.Assert(Type == Group); + Debug.Assert(Kind == RegexNodeKind.Group); RegexNode u = this; - while (u.Type == Group) + while (u.Kind == RegexNodeKind.Group) { Debug.Assert(u.ChildCount() == 1); u = u.Child(0); @@ -637,39 +597,45 @@ private RegexNode ReduceAtomic() return this; } - Debug.Assert(Type == Atomic); + Debug.Assert(Kind == RegexNodeKind.Atomic); Debug.Assert(ChildCount() == 1); RegexNode atomic = this; RegexNode child = Child(0); - while (child.Type == Atomic) + while (child.Kind == RegexNodeKind.Atomic) { atomic = child; child = atomic.Child(0); } - switch (child.Type) + switch (child.Kind) { + // If the child is empty/nothing, there's nothing to be made atomic so the Atomic + // node can simply be removed. + case RegexNodeKind.Empty: + case RegexNodeKind.Nothing: + return child; + // If the child is already atomic, we can just remove the atomic node. - case Oneloopatomic: - case Notoneloopatomic: - case Setloopatomic: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Setloopatomic: return child; // If an atomic subexpression contains only a {one/notone/set}{loop/lazy}, // change it to be an {one/notone/set}loopatomic and remove the atomic node. - case Oneloop: - case Notoneloop: - case Setloop: - case Onelazy: - case Notonelazy: - case Setlazy: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Setloop: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Setlazy: child.MakeLoopAtomic(); return child; // Alternations have a variety of possible optimizations that can be applied // iff they're atomic. - case Alternate: + case RegexNodeKind.Alternate: if ((Options & RegexOptions.RightToLeft) == 0) { List? branches = child.Children as List; @@ -678,9 +644,9 @@ private RegexNode ReduceAtomic() // If an alternation is atomic and its first branch is Empty, the whole thing // is a nop, as Empty will match everything trivially, and no backtracking // into the node will be performed, making the remaining branches irrelevant. - if (branches[0].Type == Empty) + if (branches[0].Kind == RegexNodeKind.Empty) { - return new RegexNode(Empty, child.Options); + return new RegexNode(RegexNodeKind.Empty, child.Options); } // Similarly, we can trim off any branches after an Empty, as they'll never be used. @@ -689,7 +655,7 @@ private RegexNode ReduceAtomic() // but if the alternation is atomic, such backtracking won't happen. for (int i = 1; i < branches.Count - 1; i++) { - if (branches[i].Type == Empty) + if (branches[i].Kind == RegexNodeKind.Empty) { branches.RemoveRange(i + 1, branches.Count - (i + 1)); break; @@ -793,10 +759,10 @@ private RegexNode ReduceAtomic() /// private RegexNode ReduceLoops() { - Debug.Assert(Type == Loop || Type == Lazyloop); + Debug.Assert(Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop); RegexNode u = this; - int type = Type; + RegexNodeKind kind = Kind; int min = M; int max = N; @@ -806,30 +772,30 @@ private RegexNode ReduceLoops() RegexNode child = u.Child(0); // multiply reps of the same type only - if (child.Type != type) + if (child.Kind != kind) { bool valid = false; - if (type == Loop) + if (kind == RegexNodeKind.Loop) { - switch (child.Type) + switch (child.Kind) { - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Setloop: - case Setloopatomic: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: valid = true; break; } } else // type == Lazyloop { - switch (child.Type) + switch (child.Kind) { - case Onelazy: - case Notonelazy: - case Setlazy: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Setlazy: valid = true; break; } @@ -863,7 +829,7 @@ private RegexNode ReduceLoops() if (min == int.MaxValue) { - return new RegexNode(Nothing, Options); + return new RegexNode(RegexNodeKind.Nothing, Options); } // If the Loop or Lazyloop now only has one child node and its a Set, One, or Notone, @@ -873,12 +839,12 @@ private RegexNode ReduceLoops() if (u.ChildCount() == 1) { RegexNode child = u.Child(0); - switch (child.Type) + switch (child.Kind) { - case One: - case Notone: - case Set: - child.MakeRep(u.Type == Lazyloop ? Onelazy : Oneloop, u.M, u.N); + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: + child.MakeRep(u.Kind == RegexNodeKind.Lazyloop ? RegexNodeKind.Onelazy : RegexNodeKind.Oneloop, u.M, u.N); u = child; break; } @@ -902,33 +868,33 @@ private RegexNode ReduceLoops() private RegexNode ReduceSet() { // Extract empty-set, one, and not-one case as special - Debug.Assert(Type == Set || Type == Setloop || Type == Setloopatomic || Type == Setlazy); + Debug.Assert(Kind is RegexNodeKind.Set or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy); Debug.Assert(!string.IsNullOrEmpty(Str)); if (RegexCharClass.IsEmpty(Str)) { - Type = Nothing; + Kind = RegexNodeKind.Nothing; Str = null; } else if (RegexCharClass.IsSingleton(Str)) { Ch = RegexCharClass.SingletonChar(Str); Str = null; - Type = - Type == Set ? One : - Type == Setloop ? Oneloop : - Type == Setloopatomic ? Oneloopatomic : - Onelazy; + Kind = + Kind == RegexNodeKind.Set ? RegexNodeKind.One : + Kind == RegexNodeKind.Setloop ? RegexNodeKind.Oneloop : + Kind == RegexNodeKind.Setloopatomic ? RegexNodeKind.Oneloopatomic : + RegexNodeKind.Onelazy; } else if (RegexCharClass.IsSingletonInverse(Str)) { Ch = RegexCharClass.SingletonChar(Str); Str = null; - Type = - Type == Set ? Notone : - Type == Setloop ? Notoneloop : - Type == Setloopatomic ? Notoneloopatomic : - Notonelazy; + Kind = + Kind == RegexNodeKind.Set ? RegexNodeKind.Notone : + Kind == RegexNodeKind.Setloop ? RegexNodeKind.Notoneloop : + Kind == RegexNodeKind.Setloopatomic ? RegexNodeKind.Notoneloopatomic : + RegexNodeKind.Notonelazy; } return this; @@ -937,21 +903,31 @@ private RegexNode ReduceSet() /// Optimize an alternation. private RegexNode ReduceAlternation() { - Debug.Assert(Type == Alternate); + Debug.Assert(Kind == RegexNodeKind.Alternate); switch (ChildCount()) { case 0: - return new RegexNode(Nothing, Options); + return new RegexNode(RegexNodeKind.Nothing, Options); case 1: return Child(0); default: ReduceSingleLetterAndNestedAlternations(); - RegexNode node = ReplaceNodeIfUnnecessary(Nothing); - node = ExtractCommonPrefixText(node); - node = ExtractCommonPrefixOneNotoneSet(node); + RegexNode node = ReplaceNodeIfUnnecessary(); + if (node.Kind == RegexNodeKind.Alternate) + { + node = ExtractCommonPrefixText(node); + if (node.Kind == RegexNodeKind.Alternate) + { + node = ExtractCommonPrefixOneNotoneSet(node); + if (node.Kind == RegexNodeKind.Alternate) + { + node = RemoveRedundantEmptiesAndNothings(node); + } + } + } return node; } @@ -981,30 +957,30 @@ void ReduceSingleLetterAndNestedAlternations() while (true) { - if (at.Type == Alternate) + if (at.Kind == RegexNodeKind.Alternate) { if (at.Children is List atChildren) { for (int k = 0; k < atChildren.Count; k++) { - atChildren[k].Next = this; + atChildren[k].Parent = this; } children.InsertRange(i + 1, atChildren); } else { RegexNode atChild = (RegexNode)at.Children!; - atChild.Next = this; + atChild.Parent = this; children.Insert(i + 1, atChild); } j--; } - else if (at.Type == Set || at.Type == One) + else if (at.Kind is RegexNodeKind.Set or RegexNodeKind.One) { // Cannot merge sets if L or I options differ, or if either are negated. optionsAt = at.Options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); - if (at.Type == Set) + if (at.Kind == RegexNodeKind.Set) { if (!wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge || !RegexCharClass.IsMergeable(at.Str!)) { @@ -1028,7 +1004,7 @@ void ReduceSingleLetterAndNestedAlternations() prev = children[j]; RegexCharClass prevCharClass; - if (prev.Type == One) + if (prev.Kind == RegexNodeKind.One) { prevCharClass = new RegexCharClass(); prevCharClass.AddChar(prev.Ch); @@ -1038,7 +1014,7 @@ void ReduceSingleLetterAndNestedAlternations() prevCharClass = RegexCharClass.Parse(prev.Str!); } - if (at.Type == One) + if (at.Kind == RegexNodeKind.One) { prevCharClass.AddChar(at.Ch); } @@ -1048,7 +1024,7 @@ void ReduceSingleLetterAndNestedAlternations() prevCharClass.AddCharClass(atCharClass); } - prev.Type = Set; + prev.Kind = RegexNodeKind.Set; prev.Str = prevCharClass.ToStringClass(Options); if ((prev.Options & RegexOptions.IgnoreCase) != 0 && RegexCharClass.MakeCaseSensitiveIfPossible(prev.Str, RegexParser.GetTargetCulture(prev.Options)) is string newSetString) @@ -1057,7 +1033,7 @@ void ReduceSingleLetterAndNestedAlternations() prev.Options &= ~RegexOptions.IgnoreCase; } } - else if (at.Type == Nothing) + else if (at.Kind == RegexNodeKind.Nothing) { j--; } @@ -1081,11 +1057,7 @@ void ReduceSingleLetterAndNestedAlternations() // e.g. \w12|\d34|\d56|\w78|\w90 => \w12|\d(?:34|56)|\w(?:78|90) static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) { - if (alternation.Type != Alternate) - { - return alternation; - } - + Debug.Assert(alternation.Kind == RegexNodeKind.Alternate); Debug.Assert(alternation.Children is List { Count: >= 2 }); var children = (List)alternation.Children; @@ -1098,7 +1070,7 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) // Only handle the case where each branch is a concatenation foreach (RegexNode child in children) { - if (child.Type != Concatenate || child.ChildCount() < 2) + if (child.Kind != RegexNodeKind.Concatenate || child.ChildCount() < 2) { return alternation; } @@ -1113,11 +1085,11 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) // it for non-atomic variable length loops could change behavior as each branch could otherwise have a // different number of characters consumed by the loop based on what's after it. RegexNode required = children[startingIndex].Child(0); - switch (required.Type) + switch (required.Kind) { - case One or Notone or Set: - case Oneloopatomic or Notoneloopatomic or Setloopatomic: - case Oneloop or Notoneloop or Setloop or Onelazy or Notonelazy or Setlazy when required.M == required.N: + case RegexNodeKind.One or RegexNodeKind.Notone or RegexNodeKind.Set: + case RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloopatomic: + case RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop or RegexNodeKind.Onelazy or RegexNodeKind.Notonelazy or RegexNodeKind.Setlazy when required.M == required.N: break; default: @@ -1129,7 +1101,7 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) for (; endingIndex < children.Count; endingIndex++) { RegexNode other = children[endingIndex].Child(0); - if (required.Type != other.Type || + if (required.Kind != other.Kind || required.Options != other.Options || required.M != other.M || required.N != other.N || @@ -1147,7 +1119,7 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) } // Remove the prefix node from every branch, adding it to a new alternation - var newAlternate = new RegexNode(Alternate, alternation.Options); + var newAlternate = new RegexNode(RegexNodeKind.Alternate, alternation.Options); for (int i = startingIndex; i < endingIndex; i++) { ((List)children[i].Children!).RemoveAt(0); @@ -1155,25 +1127,61 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) } // If this alternation is wrapped as atomic, we need to do the same for the new alternation. - if (alternation.Next is RegexNode parent && parent.Type == Atomic) + if (alternation.Parent is RegexNode { Kind: RegexNodeKind.Atomic } parent) { - var atomic = new RegexNode(Atomic, alternation.Options); + var atomic = new RegexNode(RegexNodeKind.Atomic, alternation.Options); atomic.AddChild(newAlternate); newAlternate = atomic; } // Now create a concatenation of the prefix node with the new alternation for the combined // branches, and replace all of the branches in this alternation with that new concatenation. - var newConcat = new RegexNode(Concatenate, alternation.Options); + var newConcat = new RegexNode(RegexNodeKind.Concatenate, alternation.Options); newConcat.AddChild(required); newConcat.AddChild(newAlternate); alternation.ReplaceChild(startingIndex, newConcat); children.RemoveRange(startingIndex + 1, endingIndex - startingIndex - 1); } - // If we've reduced this alternation to just a single branch, return it. - // Otherwise, return the alternation. - return alternation.ChildCount() == 1 ? alternation.Child(0) : alternation; + return alternation.ReplaceNodeIfUnnecessary(); + } + + // Removes unnecessary Empty and Nothing nodes from the alternation. A Nothing will never + // match, so it can be removed entirely, and an Empty can be removed if there's a previous + // Empty in the alternation: it's an extreme case of just having a repeated branch in an + // alternation, and while we don't check for all duplicates, checking for empty is easy. + static RegexNode RemoveRedundantEmptiesAndNothings(RegexNode node) + { + Debug.Assert(node.Kind == RegexNodeKind.Alternate); + Debug.Assert(node.ChildCount() >= 2); + var children = (List)node.Children!; + + int i = 0, j = 0; + bool seenEmpty = false; + while (i < children.Count) + { + RegexNode child = children[i]; + switch (child.Kind) + { + case RegexNodeKind.Empty when !seenEmpty: + seenEmpty = true; + goto default; + + case RegexNodeKind.Empty: + case RegexNodeKind.Nothing: + i++; + break; + + default: + children[j] = children[i]; + i++; + j++; + break; + } + } + + children.RemoveRange(j, children.Count - j); + return node.ReplaceNodeIfUnnecessary(); } // Analyzes all the branches of the alternation for text that's identical at the beginning @@ -1187,11 +1195,7 @@ static RegexNode ExtractCommonPrefixOneNotoneSet(RegexNode alternation) // e.g. abc|ade => a(?bc|de) static RegexNode ExtractCommonPrefixText(RegexNode alternation) { - if (alternation.Type != Alternate) - { - return alternation; - } - + Debug.Assert(alternation.Kind == RegexNodeKind.Alternate); Debug.Assert(alternation.Children is List { Count: >= 2 }); var children = (List)alternation.Children; @@ -1219,7 +1223,7 @@ static RegexNode ExtractCommonPrefixText(RegexNode alternation) RegexOptions startingNodeOptions = startingNode.Options; startingSpan = startingNode.Str.AsSpan(); - if (startingNode.Type == One) + if (startingNode.Kind == RegexNodeKind.One) { scratchChar[0] = startingNode.Ch; startingSpan = scratchChar; @@ -1239,7 +1243,7 @@ static RegexNode ExtractCommonPrefixText(RegexNode alternation) // See if the new branch's prefix has a shared prefix with the current one. // If it does, shorten to that; if it doesn't, bail. - if (startingNode.Type == One) + if (startingNode.Kind == RegexNodeKind.One) { if (startingSpan[0] != startingNode.Ch) { @@ -1253,7 +1257,7 @@ static RegexNode ExtractCommonPrefixText(RegexNode alternation) } else { - Debug.Assert(startingNode.Type == Multi); + Debug.Assert(startingNode.Kind == RegexNodeKind.Multi); Debug.Assert(startingNode.Str!.Length > 0); int minLength = Math.Min(startingSpan.Length, startingNode.Str.Length); @@ -1284,48 +1288,39 @@ static RegexNode ExtractCommonPrefixText(RegexNode alternation) // that replaces all these branches in this alternation. var prefix = startingSpan.Length == 1 ? - new RegexNode(One, startingNodeOptions, startingSpan[0]) : - new RegexNode(Multi, startingNodeOptions, startingSpan.ToString()); - var newAlternate = new RegexNode(Alternate, startingNodeOptions); - bool seenEmpty = false; + new RegexNode(RegexNodeKind.One, startingNodeOptions, startingSpan[0]) : + new RegexNode(RegexNodeKind.Multi, startingNodeOptions, startingSpan.ToString()); + var newAlternate = new RegexNode(RegexNodeKind.Alternate, startingNodeOptions); for (int i = startingIndex; i < endingIndex; i++) { RegexNode branch = children[i]; - ProcessOneOrMulti(branch.Type == Concatenate ? branch.Child(0) : branch, startingSpan); + ProcessOneOrMulti(branch.Kind == RegexNodeKind.Concatenate ? branch.Child(0) : branch, startingSpan); branch = branch.Reduce(); - if (branch.Type == Empty) - { - if (seenEmpty) - { - continue; - } - seenEmpty = true; - } newAlternate.AddChild(branch); // Remove the starting text from the one or multi node. This may end up changing // the type of the node to be Empty if the starting text matches the node's full value. static void ProcessOneOrMulti(RegexNode node, ReadOnlySpan startingSpan) { - if (node.Type == One) + if (node.Kind == RegexNodeKind.One) { Debug.Assert(startingSpan.Length == 1); Debug.Assert(startingSpan[0] == node.Ch); - node.Type = Empty; + node.Kind = RegexNodeKind.Empty; node.Ch = '\0'; } else { - Debug.Assert(node.Type == Multi); + Debug.Assert(node.Kind == RegexNodeKind.Multi); Debug.Assert(node.Str.AsSpan().StartsWith(startingSpan, StringComparison.Ordinal)); if (node.Str!.Length == startingSpan.Length) { - node.Type = Empty; + node.Kind = RegexNodeKind.Empty; node.Str = null; } else if (node.Str.Length - 1 == startingSpan.Length) { - node.Type = One; + node.Kind = RegexNodeKind.One; node.Ch = node.Str[node.Str.Length - 1]; node.Str = null; } @@ -1337,14 +1332,14 @@ static void ProcessOneOrMulti(RegexNode node, ReadOnlySpan startingSpan) } } - if (alternation.Next is RegexNode parent && parent.Type == Atomic) + if (alternation.Parent is RegexNode parent && parent.Kind == RegexNodeKind.Atomic) { - var atomic = new RegexNode(Atomic, startingNodeOptions); + var atomic = new RegexNode(RegexNodeKind.Atomic, startingNodeOptions); atomic.AddChild(newAlternate); newAlternate = atomic; } - var newConcat = new RegexNode(Concatenate, startingNodeOptions); + var newConcat = new RegexNode(RegexNodeKind.Concatenate, startingNodeOptions); newConcat.AddChild(prefix); newConcat.AddChild(newAlternate); alternation.ReplaceChild(startingIndex, newConcat); @@ -1364,55 +1359,73 @@ static void ProcessOneOrMulti(RegexNode node, ReadOnlySpan startingSpan) /// public RegexNode? FindBranchOneOrMultiStart() { - RegexNode branch = this; - - if (branch.Type == Concatenate) - { - branch = branch.Child(0); - } + RegexNode branch = Kind == RegexNodeKind.Concatenate ? Child(0) : this; + return branch.Kind is RegexNodeKind.One or RegexNodeKind.Multi ? branch : null; + } - return branch.Type == One || branch.Type == Multi ? branch : null; + /// Same as but also for Sets. + public RegexNode? FindBranchOneMultiOrSetStart() + { + RegexNode branch = Kind == RegexNodeKind.Concatenate ? Child(0) : this; + return branch.Kind is RegexNodeKind.One or RegexNodeKind.Multi or RegexNodeKind.Set ? branch : null; } /// Gets the character that begins a One or Multi. public char FirstCharOfOneOrMulti() { - Debug.Assert(Type is One or Multi); + Debug.Assert(Kind is RegexNodeKind.One or RegexNodeKind.Multi); Debug.Assert((Options & RegexOptions.RightToLeft) == 0); - return Type == One ? Ch : Str![0]; + return Kind == RegexNodeKind.One ? Ch : Str![0]; } - /// Finds the guaranteed beginning character of the node, or null if none exists. - public (char Char, string? String)? FindStartingCharacterOrString() + /// Finds the guaranteed beginning literal(s) of the node, or null if none exists. + public (char Char, string? String, string? SetChars)? FindStartingLiteral(int maxSetCharacters = 5) // 5 is max optimized by IndexOfAny today { + Debug.Assert(maxSetCharacters >= 0 && maxSetCharacters <= 128, $"{nameof(maxSetCharacters)} == {maxSetCharacters} should be small enough to be stack allocated."); + RegexNode? node = this; while (true) { if (node is not null && (node.Options & RegexOptions.RightToLeft) == 0) { - switch (node.Type) + switch (node.Kind) { - case One: - case Oneloop or Oneloopatomic or Onelazy when node.M > 0: + case RegexNodeKind.One: + case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy when node.M > 0: if ((node.Options & RegexOptions.IgnoreCase) == 0 || !RegexCharClass.ParticipatesInCaseConversion(node.Ch)) { - return (node.Ch, null); + return (node.Ch, null, null); } break; - case Multi: + case RegexNodeKind.Multi: if ((node.Options & RegexOptions.IgnoreCase) == 0 || !RegexCharClass.ParticipatesInCaseConversion(node.Str.AsSpan())) { - return ('\0', node.Str); + return ('\0', node.Str, null); + } + break; + + case RegexNodeKind.Set: + case RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy when node.M > 0: + Span setChars = stackalloc char[maxSetCharacters]; + int numChars; + if (!RegexCharClass.IsNegated(node.Str!) && + (numChars = RegexCharClass.GetSetChars(node.Str!, setChars)) != 0) + { + setChars = setChars.Slice(0, numChars); + if ((node.Options & RegexOptions.IgnoreCase) == 0 || !RegexCharClass.ParticipatesInCaseConversion(setChars)) + { + return ('\0', null, setChars.ToString()); + } } break; - case Atomic: - case Concatenate: - case Capture: - case Group: - case Loop or Lazyloop when node.M > 0: - case Require: + case RegexNodeKind.Atomic: + case RegexNodeKind.Concatenate: + case RegexNodeKind.Capture: + case RegexNodeKind.Group: + case RegexNodeKind.Loop or RegexNodeKind.Lazyloop when node.M > 0: + case RegexNodeKind.PositiveLookaround: node = node.Child(0); continue; } @@ -1429,13 +1442,13 @@ public char FirstCharOfOneOrMulti() /// private RegexNode ReduceConcatenation() { - Debug.Assert(Type == Concatenate); + Debug.Assert(Kind == RegexNodeKind.Concatenate); // If the concat node has zero or only one child, get rid of the concat. switch (ChildCount()) { case 0: - return new RegexNode(Empty, Options); + return new RegexNode(RegexNodeKind.Empty, Options); case 1: return Child(0); } @@ -1447,15 +1460,9 @@ private RegexNode ReduceConcatenation() // and also help to reduce catastrophic backtracking. ReduceConcatenationWithAdjacentLoops(); - // Now convert as many loops as possible to be atomic to avoid unnecessary backtracking. - if ((Options & RegexOptions.RightToLeft) == 0) - { - ReduceConcatenationWithAutoAtomic(); - } - // If the concatenation is now empty, return an empty node, or if it's got a single child, return that child. // Otherwise, return this. - return ReplaceNodeIfUnnecessary(Empty); + return ReplaceNodeIfUnnecessary(); } /// @@ -1464,7 +1471,7 @@ private RegexNode ReduceConcatenation() /// private void ReduceConcatenationWithAdjacentStrings() { - Debug.Assert(Type == Concatenate); + Debug.Assert(Kind == RegexNodeKind.Concatenate); Debug.Assert(Children is List); bool wasLastString = false; @@ -1481,26 +1488,26 @@ private void ReduceConcatenationWithAdjacentStrings() children[j] = at; } - if (at.Type == Concatenate && + if (at.Kind == RegexNodeKind.Concatenate && ((at.Options & RegexOptions.RightToLeft) == (Options & RegexOptions.RightToLeft))) { if (at.Children is List atChildren) { for (int k = 0; k < atChildren.Count; k++) { - atChildren[k].Next = this; + atChildren[k].Parent = this; } children.InsertRange(i + 1, atChildren); } else { RegexNode atChild = (RegexNode)at.Children!; - atChild.Next = this; + atChild.Parent = this; children.Insert(i + 1, atChild); } j--; } - else if (at.Type == Multi || at.Type == One) + else if (at.Kind is RegexNodeKind.Multi or RegexNodeKind.One) { // Cannot merge strings if L or I options differ RegexOptions optionsAt = at.Options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); @@ -1514,22 +1521,22 @@ private void ReduceConcatenationWithAdjacentStrings() RegexNode prev = children[--j]; - if (prev.Type == One) + if (prev.Kind == RegexNodeKind.One) { - prev.Type = Multi; + prev.Kind = RegexNodeKind.Multi; prev.Str = prev.Ch.ToString(); } if ((optionsAt & RegexOptions.RightToLeft) == 0) { - prev.Str = (at.Type == One) ? $"{prev.Str}{at.Ch}" : prev.Str + at.Str; + prev.Str = (at.Kind == RegexNodeKind.One) ? $"{prev.Str}{at.Ch}" : prev.Str + at.Str; } else { - prev.Str = (at.Type == One) ? $"{at.Ch}{prev.Str}" : at.Str + prev.Str; + prev.Str = (at.Kind == RegexNodeKind.One) ? $"{at.Ch}{prev.Str}" : at.Str + prev.Str; } } - else if (at.Type == Empty) + else if (at.Kind == RegexNodeKind.Empty) { j--; } @@ -1551,7 +1558,7 @@ private void ReduceConcatenationWithAdjacentStrings() /// private void ReduceConcatenationWithAdjacentLoops() { - Debug.Assert(Type == Concatenate); + Debug.Assert(Kind == RegexNodeKind.Concatenate); Debug.Assert(Children is List); var children = (List)Children!; @@ -1586,11 +1593,11 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) return true; } - switch (currentNode.Type) + switch (currentNode.Kind) { // Coalescing a loop with its same type - case Oneloop or Oneloopatomic or Onelazy or Notoneloop or Notoneloopatomic or Notonelazy when nextNode.Type == currentNode.Type && currentNode.Ch == nextNode.Ch: - case Setloop or Setloopatomic or Setlazy when nextNode.Type == currentNode.Type && currentNode.Str == nextNode.Str: + case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy when nextNode.Kind == currentNode.Kind && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy when nextNode.Kind == currentNode.Kind && currentNode.Str == nextNode.Str: if (CanCombineCounts(currentNode.M, currentNode.N, nextNode.M, nextNode.N)) { currentNode.M += nextNode.M; @@ -1604,9 +1611,9 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) break; // Coalescing a loop with an additional item of the same type - case Oneloop or Oneloopatomic or Onelazy when nextNode.Type == One && currentNode.Ch == nextNode.Ch: - case Notoneloop or Notoneloopatomic or Notonelazy when nextNode.Type == Notone && currentNode.Ch == nextNode.Ch: - case Setloop or Setloopatomic or Setlazy when nextNode.Type == Set && currentNode.Str == nextNode.Str: + case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy when nextNode.Kind == RegexNodeKind.One && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy when nextNode.Kind == RegexNodeKind.Notone && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy when nextNode.Kind == RegexNodeKind.Set && currentNode.Str == nextNode.Str: if (CanCombineCounts(currentNode.M, currentNode.N, 1, 1)) { currentNode.M++; @@ -1620,12 +1627,12 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) break; // Coalescing an individual item with a loop. - case One when (nextNode.Type == Oneloop || nextNode.Type == Oneloopatomic || nextNode.Type == Onelazy) && currentNode.Ch == nextNode.Ch: - case Notone when (nextNode.Type == Notoneloop || nextNode.Type == Notoneloopatomic || nextNode.Type == Notonelazy) && currentNode.Ch == nextNode.Ch: - case Set when (nextNode.Type == Setloop || nextNode.Type == Setloopatomic || nextNode.Type == Setlazy) && currentNode.Str == nextNode.Str: + case RegexNodeKind.One when (nextNode.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy) && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Notone when (nextNode.Kind is RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy) && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Set when (nextNode.Kind is RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy) && currentNode.Str == nextNode.Str: if (CanCombineCounts(1, 1, nextNode.M, nextNode.N)) { - currentNode.Type = nextNode.Type; + currentNode.Kind = nextNode.Kind; currentNode.M = nextNode.M + 1; currentNode.N = nextNode.N == int.MaxValue ? int.MaxValue : nextNode.N + 1; next++; @@ -1634,9 +1641,9 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) break; // Coalescing an individual item with another individual item. - case One or Notone when nextNode.Type == currentNode.Type && currentNode.Ch == nextNode.Ch: - case Set when nextNode.Type == Set && currentNode.Str == nextNode.Str: - currentNode.MakeRep(Oneloop, 2, 2); + case RegexNodeKind.One or RegexNodeKind.Notone when nextNode.Kind == currentNode.Kind && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Set when nextNode.Kind == RegexNodeKind.Set && currentNode.Str == nextNode.Str: + currentNode.MakeRep(RegexNodeKind.Oneloop, 2, 2); next++; continue; } @@ -1658,21 +1665,43 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) /// to {one/notone/set}loopatomic nodes. Such changes avoid potential useless backtracking. /// e.g. A*B (where sets A and B don't overlap) => (?>A*)B. /// - private void ReduceConcatenationWithAutoAtomic() + private void FindAndMakeLoopsAtomic() { - // RegexOptions.NonBacktracking doesn't support atomic groups, so when that option - // is set we don't want to create atomic groups where they weren't explicitly authored. - if ((Options & RegexOptions.NonBacktracking) != 0) + Debug.Assert((Options & RegexOptions.NonBacktracking) == 0, "Atomic groups aren't supported and don't help performance with NonBacktracking"); + + if (!StackHelper.TryEnsureSufficientExecutionStack()) { + // If we're too deep on the stack, give up optimizing further. return; } - Debug.Assert(Type == Concatenate); - Debug.Assert((Options & RegexOptions.RightToLeft) == 0); - Debug.Assert(Children is List); + if ((Options & RegexOptions.RightToLeft) != 0) + { + // RTL is so rare, we don't need to spend additional time/code optimizing for it. + return; + } + + // For all node types that have children, recur into each of those children. + int childCount = ChildCount(); + if (childCount != 0) + { + for (int i = 0; i < childCount; i++) + { + Child(i).FindAndMakeLoopsAtomic(); + } + } + + // If this isn't a concatenation, nothing more to do. + if (Kind is not RegexNodeKind.Concatenate) + { + return; + } + // This is a concatenation. Iterate through each pair of nodes in the concatenation seeing whether we can + // make the first node (or its right-most child) atomic based on the second node (or its left-most child). + Debug.Assert(Children is List); var children = (List)Children; - for (int i = 0; i < children.Count - 1; i++) + for (int i = 0; i < childCount - 1; i++) { ProcessNode(children[i], children[i + 1]); @@ -1688,7 +1717,7 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) while (true) { // We can always recur into captures and into the last node of concatenations. - if (node.Type == Capture || node.Type == Concatenate) + if (node.Kind is RegexNodeKind.Capture or RegexNodeKind.Concatenate) { node = node.Child(node.ChildCount() - 1); continue; @@ -1698,7 +1727,7 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) // we need to be careful not to just always do so; the ending node of a loop can only // be made atomic if what comes after the loop but also the beginning of the loop are // compatible for the optimization. - if (node.Type == Loop) + if (node.Kind == RegexNodeKind.Loop) { RegexNode? loopDescendent = node.FindLastExpressionInLoopForAutoAtomic(); if (loopDescendent != null) @@ -1713,23 +1742,24 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) } // If the node can be changed to atomic based on what comes after it, do so. - switch (node.Type) + switch (node.Kind) { - case Oneloop when CanBeMadeAtomic(node, subsequent): - case Notoneloop when CanBeMadeAtomic(node, subsequent): - case Setloop when CanBeMadeAtomic(node, subsequent): + case RegexNodeKind.Oneloop or RegexNodeKind.Notoneloop or RegexNodeKind.Setloop when CanBeMadeAtomic(node, subsequent, allowSubsequentIteration: true): node.MakeLoopAtomic(); break; - case Alternate: + + case RegexNodeKind.Alternate or RegexNodeKind.BackreferenceConditional or RegexNodeKind.ExpressionConditional: // In the case of alternation, we can't change the alternation node itself // based on what comes after it (at least not with more complicated analysis // that factors in all branches together), but we can look at each individual // branch, and analyze ending loops in each branch individually to see if they // can be made atomic. Then if we do end up backtracking into the alternation, - // we at least won't need to backtrack into that loop. + // we at least won't need to backtrack into that loop. The same is true for + // conditionals, though we don't want to process the condition expression + // itself, as it's already considered atomic and handled as part of ReduceTestgroup. { int alternateBranches = node.ChildCount(); - for (int b = 0; b < alternateBranches; b++) + for (int b = node.Kind == RegexNodeKind.ExpressionConditional ? 1 : 0; b < alternateBranches; b++) { ProcessNode(node.Child(b), subsequent); } @@ -1749,13 +1779,13 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) { RegexNode node = this; - Debug.Assert(node.Type == Loop); + Debug.Assert(node.Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop); // Start by looking at the loop's sole child. node = node.Child(0); // Skip past captures. - while (node.Type == Capture) + while (node.Kind == RegexNodeKind.Capture) { node = node.Child(0); } @@ -1766,11 +1796,11 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) // example, in the expression (a+[def])*, the last child is [def] and the first is // a+, which can't possibly overlap with [def]. In contrast, if we had (a+[ade])*, // [ade] could potentially match the starting 'a'. - if (node.Type == Concatenate) + if (node.Kind == RegexNodeKind.Concatenate) { int concatCount = node.ChildCount(); RegexNode lastConcatChild = node.Child(concatCount - 1); - if (CanBeMadeAtomic(lastConcatChild, node.Child(0))) + if (CanBeMadeAtomic(lastConcatChild, node.Child(0), allowSubsequentIteration: false)) { return lastConcatChild; } @@ -1780,18 +1810,41 @@ static void ProcessNode(RegexNode node, RegexNode subsequent) return null; } + /// Optimizations for positive lookaheads/behinds. + private RegexNode ReduceRequire() + { + Debug.Assert(Kind == RegexNodeKind.PositiveLookaround); + Debug.Assert(ChildCount() == 1); + + // A positive lookaround is a zero-width atomic assertion. + // As it's atomic, nothing will backtrack into it, and we can + // eliminate any ending backtracking from it. + EliminateEndingBacktracking(); + + // A positive lookaround wrapped around an empty is a nop, and can just + // be made into an empty. A developer typically doesn't write this, but + // rather it evolves due to optimizations resulting in empty. + if (Child(0).Kind == RegexNodeKind.Empty) + { + Kind = RegexNodeKind.Empty; + Children = null; + } + + return this; + } + /// Optimizations for negative lookaheads/behinds. private RegexNode ReducePrevent() { - Debug.Assert(Type == Prevent); + Debug.Assert(Kind == RegexNodeKind.NegativeLookaround); Debug.Assert(ChildCount() == 1); - // A negative lookahead/lookbehind wrapped around an empty child, i.e. (?!), is + // A negative lookaround wrapped around an empty child, i.e. (?!), is // sometimes used as a way to insert a guaranteed no-match into the expression. // We can reduce it to simply Nothing. - if (Child(0).Type == Empty) + if (Child(0).Kind == RegexNodeKind.Empty) { - Type = Nothing; + Kind = RegexNodeKind.Nothing; Children = null; } @@ -1801,7 +1854,7 @@ private RegexNode ReducePrevent() /// Optimizations for backreference conditionals. private RegexNode ReduceTestref() { - Debug.Assert(Type == Testref); + Debug.Assert(Kind == RegexNodeKind.BackreferenceConditional); Debug.Assert(ChildCount() is 1 or 2); // This isn't so much an optimization as it is changing the tree for consistency. @@ -1810,7 +1863,7 @@ private RegexNode ReduceTestref() // we add one that will match empty. if (ChildCount() == 1) { - AddChild(new RegexNode(Empty, Options)); + AddChild(new RegexNode(RegexNodeKind.Empty, Options)); } return this; @@ -1819,7 +1872,7 @@ private RegexNode ReduceTestref() /// Optimizations for expression conditionals. private RegexNode ReduceTestgroup() { - Debug.Assert(Type == Testgroup); + Debug.Assert(Kind == RegexNodeKind.ExpressionConditional); Debug.Assert(ChildCount() is 2 or 3); // This isn't so much an optimization as it is changing the tree for consistency. @@ -1828,7 +1881,7 @@ private RegexNode ReduceTestgroup() // we add one that will match empty. if (ChildCount() == 2) { - AddChild(new RegexNode(Empty, Options)); + AddChild(new RegexNode(RegexNodeKind.Empty, Options)); } // It's common for the condition to be an explicit positive lookahead, as specifying @@ -1837,11 +1890,16 @@ private RegexNode ReduceTestgroup() // there's no ambiguity, and we can remove an extra level of positive lookahead, as the // engines need to treat the condition as a zero-width positive, atomic assertion regardless. RegexNode condition = Child(0); - if (condition.Type == Require && (condition.Options & RegexOptions.RightToLeft) == 0) + if (condition.Kind == RegexNodeKind.PositiveLookaround && (condition.Options & RegexOptions.RightToLeft) == 0) { ReplaceChild(0, condition.Child(0)); } + // We can also eliminate any ending backtracking in the condition, as the condition + // is considered to be a positive lookahead, which is an atomic zero-width assertion. + condition = Child(0); + condition.EliminateEndingBacktracking(); + return this; } @@ -1849,7 +1907,7 @@ private RegexNode ReduceTestgroup() /// Determines whether node can be switched to an atomic loop. Subsequent is the node /// immediately after 'node'. /// - private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent) + private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, bool allowSubsequentIteration) { if (!StackHelper.TryEnsureSufficientExecutionStack()) { @@ -1857,102 +1915,191 @@ private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent) return false; } - // Skip the successor down to the closest node that's guaranteed to follow it. - while (subsequent.ChildCount() > 0) + // In most case, we'll simply check the node against whatever subsequent is. However, in case + // subsequent ends up being a loop with a min bound of 0, we'll also need to evaluate the node + // against whatever comes after subsequent. In that case, we'll walk the tree to find the + // next subsequent, and we'll loop around against to perform the comparison again. + while (true) { - Debug.Assert(subsequent.Type != Group); - switch (subsequent.Type) + // Skip the successor down to the closest node that's guaranteed to follow it. + int childCount; + while ((childCount = subsequent.ChildCount()) > 0) { - case Concatenate: - case Capture: - case Atomic: - case Require when (subsequent.Options & RegexOptions.RightToLeft) == 0: // only lookaheads, not lookbehinds (represented as RTL Require nodes) - case Loop or Lazyloop when subsequent.M > 0: - subsequent = subsequent.Child(0); - continue; + Debug.Assert(subsequent.Kind != RegexNodeKind.Group); + switch (subsequent.Kind) + { + case RegexNodeKind.Concatenate: + case RegexNodeKind.Capture: + case RegexNodeKind.Atomic: + case RegexNodeKind.PositiveLookaround when (subsequent.Options & RegexOptions.RightToLeft) == 0: // only lookaheads, not lookbehinds (represented as RTL PositiveLookaround nodes) + case RegexNodeKind.Loop or RegexNodeKind.Lazyloop when subsequent.M > 0: + subsequent = subsequent.Child(0); + continue; + } + + break; } - break; - } + // If the two nodes don't agree on options in any way, don't try to optimize them. + // TODO: Remove this once https://github.com/dotnet/runtime/issues/61048 is implemented. + if (node.Options != subsequent.Options) + { + return false; + } - // If the two nodes don't agree on options in any way, don't try to optimize them. - if (node.Options != subsequent.Options) - { - return false; - } + // If the successor is an alternation, all of its children need to be evaluated, since any of them + // could come after this node. If any of them fail the optimization, then the whole node fails. + // This applies to expression conditionals as well, as long as they have both a yes and a no branch (if there's + // only a yes branch, we'd need to also check whatever comes after the conditional). It doesn't apply to + // backreference conditionals, as the condition itself is unknown statically and could overlap with the + // loop being considered for atomicity. + switch (subsequent.Kind) + { + case RegexNodeKind.Alternate: + case RegexNodeKind.ExpressionConditional when childCount == 3: // condition, yes, and no branch + for (int i = 0; i < childCount; i++) + { + if (!CanBeMadeAtomic(node, subsequent.Child(i), allowSubsequentIteration)) + { + return false; + } + } + return true; + } - // If the successor is an alternation, all of its children need to be evaluated, since any of them - // could come after this node. If any of them fail the optimization, then the whole node fails. - if (subsequent.Type == Alternate) - { - int childCount = subsequent.ChildCount(); - for (int i = 0; i < childCount; i++) + // If this node is a {one/notone/set}loop, see if it overlaps with its successor in the concatenation. + // If it doesn't, then we can upgrade it to being a {one/notone/set}loopatomic. + // Doing so avoids unnecessary backtracking. + switch (node.Kind) { - if (!CanBeMadeAtomic(node, subsequent.Child(i))) - { + case RegexNodeKind.Oneloop: + switch (subsequent.Kind) + { + case RegexNodeKind.One when node.Ch != subsequent.Ch: + case RegexNodeKind.Notone when node.Ch == subsequent.Ch: + case RegexNodeKind.Set when !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M > 0 && node.Ch != subsequent.Ch: + case RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch: + case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): + case RegexNodeKind.Multi when node.Ch != subsequent.Str![0]: + case RegexNodeKind.End: + case RegexNodeKind.EndZ or RegexNodeKind.Eol when node.Ch != '\n': + case RegexNodeKind.Boundary when RegexCharClass.IsBoundaryWordChar(node.Ch): + case RegexNodeKind.NonBoundary when !RegexCharClass.IsBoundaryWordChar(node.Ch): + case RegexNodeKind.ECMABoundary when RegexCharClass.IsECMAWordChar(node.Ch): + case RegexNodeKind.NonECMABoundary when !RegexCharClass.IsECMAWordChar(node.Ch): + return true; + + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M == 0 && node.Ch != subsequent.Ch: + case RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic when subsequent.M == 0 && node.Ch == subsequent.Ch: + case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): + // The loop can be made atomic based on this subsequent node, but we'll need to evaluate the next one as well. + break; + + default: + return false; + } + break; + + case RegexNodeKind.Notoneloop: + switch (subsequent.Kind) + { + case RegexNodeKind.One when node.Ch == subsequent.Ch: + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch: + case RegexNodeKind.Multi when node.Ch == subsequent.Str![0]: + case RegexNodeKind.End: + return true; + + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M == 0 && node.Ch == subsequent.Ch: + // The loop can be made atomic based on this subsequent node, but we'll need to evaluate the next one as well. + break; + + default: + return false; + } + break; + + case RegexNodeKind.Setloop: + switch (subsequent.Kind) + { + case RegexNodeKind.One when !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): + case RegexNodeKind.Set when !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): + case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M > 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): + case RegexNodeKind.Multi when !RegexCharClass.CharInClass(subsequent.Str![0], node.Str!): + case RegexNodeKind.End: + case RegexNodeKind.EndZ or RegexNodeKind.Eol when !RegexCharClass.CharInClass('\n', node.Str!): + case RegexNodeKind.Boundary when node.Str is RegexCharClass.WordClass or RegexCharClass.DigitClass: + case RegexNodeKind.NonBoundary when node.Str is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass: + case RegexNodeKind.ECMABoundary when node.Str is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass: + case RegexNodeKind.NonECMABoundary when node.Str is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass: + return true; + + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): + case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M == 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): + // The loop can be made atomic based on this subsequent node, but we'll need to evaluate the next one as well. + break; + + default: + return false; + } + break; + + default: return false; - } } - return true; - } + // We only get here if the node could be made atomic based on subsequent but subsequent has a lower bound of zero + // and thus we need to move subsequent to be the next node in sequence and loop around to try again. + Debug.Assert(subsequent.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy); + Debug.Assert(subsequent.M == 0); + if (!allowSubsequentIteration) + { + return false; + } - // If this node is a {one/notone/set}loop, see if it overlaps with its successor in the concatenation. - // If it doesn't, then we can upgrade it to being a {one/notone/set}loopatomic. - // Doing so avoids unnecessary backtracking. - switch (node.Type) - { - case Oneloop: - switch (subsequent.Type) + // To be conservative, we only walk up through a very limited set of constructs (even though we may have walked + // down through more, like loops), looking for the next concatenation that we're not at the end of, at + // which point subsequent becomes whatever node is next in that concatenation. + while (true) + { + RegexNode? parent = subsequent.Parent; + switch (parent?.Kind) { - case One when node.Ch != subsequent.Ch: - case Onelazy or Oneloop or Oneloopatomic when subsequent.M > 0 && node.Ch != subsequent.Ch: - case Notone when node.Ch == subsequent.Ch: - case Notonelazy or Notoneloop or Notoneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch: - case Multi when node.Ch != subsequent.Str![0]: - case Set when !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): - case Setlazy or Setloop or Setloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): - case End: - case EndZ or Eol when node.Ch != '\n': - case Boundary when RegexCharClass.IsBoundaryWordChar(node.Ch): - case NonBoundary when !RegexCharClass.IsBoundaryWordChar(node.Ch): - case ECMABoundary when RegexCharClass.IsECMAWordChar(node.Ch): - case NonECMABoundary when !RegexCharClass.IsECMAWordChar(node.Ch): - return true; - } - break; + case RegexNodeKind.Atomic: + case RegexNodeKind.Alternate: + case RegexNodeKind.Capture: + subsequent = parent; + continue; - case Notoneloop: - switch (subsequent.Type) - { - case One when node.Ch == subsequent.Ch: - case Onelazy or Oneloop or Oneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch: - case Multi when node.Ch == subsequent.Str![0]: - case End: - return true; - } - break; + case RegexNodeKind.Concatenate: + var peers = (List)parent.Children!; + int currentIndex = peers.IndexOf(subsequent); + Debug.Assert(currentIndex >= 0, "Node should have been in its parent's child list"); + if (currentIndex + 1 == peers.Count) + { + subsequent = parent; + continue; + } + else + { + subsequent = peers[currentIndex + 1]; + break; + } - case Setloop: - switch (subsequent.Type) - { - case One when !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): - case Onelazy or Oneloop or Oneloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): - case Multi when !RegexCharClass.CharInClass(subsequent.Str![0], node.Str!): - case Set when !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): - case Setlazy or Setloop or Setloopatomic when subsequent.M > 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): - case End: - case EndZ or Eol when !RegexCharClass.CharInClass('\n', node.Str!): - case Boundary when node.Str == RegexCharClass.WordClass || node.Str == RegexCharClass.DigitClass: - case NonBoundary when node.Str == RegexCharClass.NotWordClass || node.Str == RegexCharClass.NotDigitClass: - case ECMABoundary when node.Str == RegexCharClass.ECMAWordClass || node.Str == RegexCharClass.ECMADigitClass: - case NonECMABoundary when node.Str == RegexCharClass.NotECMAWordClass || node.Str == RegexCharClass.NotDigitClass: + case null: + // If we hit the root, we're at the end of the expression, at which point nothing could backtrack + // in and we can declare success. return true; + + default: + // Anything else, we don't know what to do, so we have to assume it could conflict with the loop. + return false; } + break; + } } - - return false; } /// Computes a min bound on the required length of any string that could possibly match. @@ -1968,36 +2115,36 @@ public int ComputeMinLength() return 0; } - switch (Type) + switch (Kind) { - case One: - case Notone: - case Set: + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: // Single character. return 1; - case Multi: + case RegexNodeKind.Multi: // Every character in the string needs to match. return Str!.Length; - case Notonelazy: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Oneloop: - case Oneloopatomic: - case Setlazy: - case Setloop: - case Setloopatomic: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Setlazy: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: // One character repeated at least M times. return M; - case Lazyloop: - case Loop: + case RegexNodeKind.Lazyloop: + case RegexNodeKind.Loop: // A node graph repeated at least M times. - return (int)Math.Min(int.MaxValue, (long)M * Child(0).ComputeMinLength()); + return (int)Math.Min(int.MaxValue - 1, (long)M * Child(0).ComputeMinLength()); - case Alternate: + case RegexNodeKind.Alternate: // The minimum required length for any of the alternation's branches. { int childCount = ChildCount(); @@ -2010,7 +2157,15 @@ public int ComputeMinLength() return min; } - case Concatenate: + case RegexNodeKind.BackreferenceConditional: + // Minimum of its yes and no branches. The backreference doesn't add to the length. + return Math.Min(Child(0).ComputeMinLength(), Child(1).ComputeMinLength()); + + case RegexNodeKind.ExpressionConditional: + // Minimum of its yes and no branches. The condition is a zero-width assertion. + return Math.Min(Child(1).ComputeMinLength(), Child(2).ComputeMinLength()); + + case RegexNodeKind.Concatenate: // The sum of all of the concatenation's children. { long sum = 0; @@ -2019,49 +2174,181 @@ public int ComputeMinLength() { sum += Child(i).ComputeMinLength(); } - return (int)Math.Min(int.MaxValue, sum); + return (int)Math.Min(int.MaxValue - 1, sum); } - case Atomic: - case Capture: - case Group: + case RegexNodeKind.Atomic: + case RegexNodeKind.Capture: + case RegexNodeKind.Group: // For groups, we just delegate to the sole child. Debug.Assert(ChildCount() == 1); return Child(0).ComputeMinLength(); - case Empty: - case Nothing: - case UpdateBumpalong: - // Nothing to match. In the future, we could potentially use Nothing to say that the min length - // is infinite, but that would require a different structure, as that would only apply if the - // Nothing match is required in all cases (rather than, say, as one branch of an alternation). - case Beginning: - case Bol: - case Boundary: - case ECMABoundary: - case End: - case EndZ: - case Eol: - case NonBoundary: - case NonECMABoundary: - case Start: - // Difficult to glean anything meaningful from boundaries or results only known at run time. - case Prevent: - case Require: - // Lookaheads/behinds could potentially be included in the future, but that will require - // a different structure, as they can't be added as part of a concatenation, since they overlap - // with what comes after. - case Ref: - case Testgroup: - case Testref: - // Constructs requiring data at runtime from the matching pattern can't influence min length. + case RegexNodeKind.Empty: + case RegexNodeKind.Nothing: + case RegexNodeKind.UpdateBumpalong: + // Nothing to match. In the future, we could potentially use Nothing to say that the min length + // is infinite, but that would require a different structure, as that would only apply if the + // Nothing match is required in all cases (rather than, say, as one branch of an alternation). + case RegexNodeKind.Beginning: + case RegexNodeKind.Bol: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: + case RegexNodeKind.Eol: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Start: + case RegexNodeKind.NegativeLookaround: + case RegexNodeKind.PositiveLookaround: + // Zero-width + case RegexNodeKind.Backreference: + // Requires matching data available only at run-time. In the future, we could choose to find + // and follow the capture group this aligns with, while being careful not to end up in an + // infinite cycle. return 0; default: -#if DEBUG - Debug.Fail($"Unknown node: {TypeName}"); -#endif - goto case Empty; + Debug.Fail($"Unknown node: {Kind}"); + goto case RegexNodeKind.Empty; + } + } + + /// Computes a maximum length of any string that could possibly match. + /// The maximum length of any string that could possibly match, or null if the length may not always be the same. + /// + /// e.g. abc[def](gh|ijklmnop) => 12 + /// + public int? ComputeMaxLength() + { + if (!StackHelper.TryEnsureSufficientExecutionStack()) + { + // If we can't recur further, assume there's no minimum we can enforce. + return null; + } + + switch (Kind) + { + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: + // Single character. + return 1; + + case RegexNodeKind.Multi: + // Every character in the string needs to match. + return Str!.Length; + + case RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or + RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or + RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic: + // Return the max number of iterations if there's an upper bound, or null if it's infinite + return N == int.MaxValue ? null : N; + + case RegexNodeKind.Loop or RegexNodeKind.Lazyloop: + if (N != int.MaxValue) + { + // A node graph repeated a fixed number of times + if (Child(0).ComputeMaxLength() is int childMaxLength) + { + long maxLength = (long)N * childMaxLength; + if (maxLength < int.MaxValue) + { + return (int)maxLength; + } + } + } + return null; + + case RegexNodeKind.Alternate: + // The maximum length of any child branch, as long as they all have one. + { + int childCount = ChildCount(); + Debug.Assert(childCount >= 2); + if (Child(0).ComputeMaxLength() is not int maxLength) + { + return null; + } + + for (int i = 1; i < childCount; i++) + { + if (Child(i).ComputeMaxLength() is not int next) + { + return null; + } + + maxLength = Math.Max(maxLength, next); + } + + return maxLength; + } + + case RegexNodeKind.BackreferenceConditional: + case RegexNodeKind.ExpressionConditional: + // The maximum length of either child branch, as long as they both have one.. The condition for an expression conditional is a zero-width assertion. + { + int i = Kind == RegexNodeKind.BackreferenceConditional ? 0 : 1; + return Child(i).ComputeMaxLength() is int yes && Child(i + 1).ComputeMaxLength() is int no ? + Math.Max(yes, no) : + null; + } + + case RegexNodeKind.Concatenate: + // The sum of all of the concatenation's children's max lengths, as long as they all have one. + { + long sum = 0; + int childCount = ChildCount(); + for (int i = 0; i < childCount; i++) + { + if (Child(i).ComputeMaxLength() is not int length) + { + return null; + } + sum += length; + } + + if (sum < int.MaxValue) + { + return (int)sum; + } + + return null; + } + + case RegexNodeKind.Atomic: + case RegexNodeKind.Capture: + // For groups, we just delegate to the sole child. + Debug.Assert(ChildCount() == 1); + return Child(0).ComputeMaxLength(); + + case RegexNodeKind.Empty: + case RegexNodeKind.Nothing: + case RegexNodeKind.UpdateBumpalong: + case RegexNodeKind.Beginning: + case RegexNodeKind.Bol: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: + case RegexNodeKind.Eol: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Start: + case RegexNodeKind.PositiveLookaround: + case RegexNodeKind.NegativeLookaround: + // Zero-width + return 0; + + case RegexNodeKind.Backreference: + // Requires matching data available only at run-time. In the future, we could choose to find + // and follow the capture group this aligns with, while being careful not to end up in an + // infinite cycle. + return null; + + default: + Debug.Fail($"Unknown node: {Kind}"); + goto case RegexNodeKind.Empty; } } @@ -2084,13 +2371,14 @@ public int ComputeMinLength() /// public bool TryGetJoinableLengthCheckChildRange(int childIndex, out int requiredLength, out int exclusiveEnd) { - static bool CanJoinLengthCheck(RegexNode node) => node.Type switch - { - One or Notone or Set => true, - Multi => true, - Oneloop or Onelazy or Oneloopatomic or - Notoneloop or Notonelazy or Notoneloopatomic or - Setloop or Setlazy or Setloopatomic when node.M == node.N => true, + static bool CanJoinLengthCheck(RegexNode node) => node.Kind switch + { + RegexNodeKind.One or RegexNodeKind.Notone or RegexNodeKind.Set => true, + RegexNodeKind.Multi => true, + RegexNodeKind.Oneloop or RegexNodeKind.Onelazy or RegexNodeKind.Oneloopatomic or + RegexNodeKind.Notoneloop or RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloopatomic or + RegexNodeKind.Setloop or RegexNodeKind.Setlazy or RegexNodeKind.Setloopatomic + when node.M == node.N => true, _ => false, }; @@ -2125,21 +2413,21 @@ Notoneloop or Notonelazy or Notoneloopatomic or public RegexNode MakeQuantifier(bool lazy, int min, int max) { if (min == 0 && max == 0) - return new RegexNode(Empty, Options); + return new RegexNode(RegexNodeKind.Empty, Options); if (min == 1 && max == 1) return this; - switch (Type) + switch (Kind) { - case One: - case Notone: - case Set: - MakeRep(lazy ? Onelazy : Oneloop, min, max); + case RegexNodeKind.One: + case RegexNodeKind.Notone: + case RegexNodeKind.Set: + MakeRep(lazy ? RegexNodeKind.Onelazy : RegexNodeKind.Oneloop, min, max); return this; default: - var result = new RegexNode(lazy ? Lazyloop : Loop, Options, min, max); + var result = new RegexNode(lazy ? RegexNodeKind.Lazyloop : RegexNodeKind.Loop, Options, min, max); result.AddChild(this); return result; } @@ -2147,9 +2435,9 @@ public RegexNode MakeQuantifier(bool lazy, int min, int max) public void AddChild(RegexNode newChild) { - newChild.Next = this; // so that the child can see its parent while being reduced + newChild.Parent = this; // so that the child can see its parent while being reduced newChild = newChild.Reduce(); - newChild.Next = this; // in case Reduce returns a different node that needs to be reparented + newChild.Parent = this; // in case Reduce returns a different node that needs to be reparented if (Children is null) { @@ -2169,9 +2457,9 @@ public void InsertChild(int index, RegexNode newChild) { Debug.Assert(Children is List); - newChild.Next = this; // so that the child can see its parent while being reduced + newChild.Parent = this; // so that the child can see its parent while being reduced newChild = newChild.Reduce(); - newChild.Next = this; // in case Reduce returns a different node that needs to be reparented + newChild.Parent = this; // in case Reduce returns a different node that needs to be reparented ((List)Children).Insert(index, newChild); } @@ -2181,9 +2469,9 @@ public void ReplaceChild(int index, RegexNode newChild) Debug.Assert(Children != null); Debug.Assert(index < ChildCount()); - newChild.Next = this; // so that the child can see its parent while being reduced + newChild.Parent = this; // so that the child can see its parent while being reduced newChild = newChild.Reduce(); - newChild.Next = this; // in case Reduce returns a different node that needs to be reparented + newChild.Parent = this; // in case Reduce returns a different node that needs to be reparented if (Children is RegexNode) { @@ -2195,15 +2483,7 @@ public void ReplaceChild(int index, RegexNode newChild) } } - public RegexNode Child(int i) - { - if (Children is RegexNode child) - { - return child; - } - - return ((List)Children!)[i]; - } + public RegexNode Child(int i) => Children is RegexNode child ? child : ((List)Children!)[i]; public int ChildCount() { @@ -2250,10 +2530,10 @@ internal bool SupportsCompilation() // TODO: This should be moved somewhere else, to a pass somewhere where we explicitly // annotate the tree, potentially as part of the final optimization pass. It doesn't // belong in this check. - if (Type == Capture) + if (Kind == RegexNodeKind.Capture) { // If we've found a supported capture, mark all of the nodes in its parent hierarchy as containing a capture. - for (RegexNode? parent = this; parent != null && (parent.Options & HasCapturesFlag) == 0; parent = parent.Next) + for (RegexNode? parent = this; parent != null && (parent.Options & HasCapturesFlag) == 0; parent = parent.Parent) { parent.Options |= HasCapturesFlag; } @@ -2264,20 +2544,20 @@ internal bool SupportsCompilation() } /// Gets whether the node is a Set/Setloop/Setloopatomic/Setlazy node. - public bool IsSetFamily => Type is Set or Setloop or Setloopatomic or Setlazy; + public bool IsSetFamily => Kind is RegexNodeKind.Set or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy; /// Gets whether the node is a One/Oneloop/Oneloopatomic/Onelazy node. - public bool IsOneFamily => Type is One or Oneloop or Oneloopatomic or Onelazy; + public bool IsOneFamily => Kind is RegexNodeKind.One or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy; /// Gets whether the node is a Notone/Notoneloop/Notoneloopatomic/Notonelazy node. - public bool IsNotoneFamily => Type is Notone or Notoneloop or Notoneloopatomic or Notonelazy; + public bool IsNotoneFamily => Kind is RegexNodeKind.Notone or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy; /// Gets whether this node is contained inside of a loop. public bool IsInLoop() { - for (RegexNode? parent = Next; parent is not null; parent = parent.Next) + for (RegexNode? parent = Parent; parent is not null; parent = parent.Parent) { - if (parent.Type is Loop or Lazyloop) + if (parent.Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop) { return true; } @@ -2287,54 +2567,43 @@ public bool IsInLoop() } #if DEBUG - private string TypeName => - Type switch - { - Oneloop => nameof(Oneloop), - Notoneloop => nameof(Notoneloop), - Setloop => nameof(Setloop), - Onelazy => nameof(Onelazy), - Notonelazy => nameof(Notonelazy), - Setlazy => nameof(Setlazy), - One => nameof(One), - Notone => nameof(Notone), - Set => nameof(Set), - Multi => nameof(Multi), - Ref => nameof(Ref), - Bol => nameof(Bol), - Eol => nameof(Eol), - Boundary => nameof(Boundary), - NonBoundary => nameof(NonBoundary), - ECMABoundary => nameof(ECMABoundary), - NonECMABoundary => nameof(NonECMABoundary), - Beginning => nameof(Beginning), - Start => nameof(Start), - EndZ => nameof(EndZ), - End => nameof(End), - Oneloopatomic => nameof(Oneloopatomic), - Notoneloopatomic => nameof(Notoneloopatomic), - Setloopatomic => nameof(Setloopatomic), - Nothing => nameof(Nothing), - Empty => nameof(Empty), - Alternate => nameof(Alternate), - Concatenate => nameof(Concatenate), - Loop => nameof(Loop), - Lazyloop => nameof(Lazyloop), - Capture => nameof(Capture), - Group => nameof(Group), - Require => nameof(Require), - Prevent => nameof(Prevent), - Atomic => nameof(Atomic), - Testref => nameof(Testref), - Testgroup => nameof(Testgroup), - UpdateBumpalong => nameof(UpdateBumpalong), - _ => $"(unknown {Type})" - }; + [ExcludeFromCodeCoverage] + public override string ToString() + { + RegexNode? curNode = this; + int curChild = 0; + var sb = new StringBuilder().AppendLine(curNode.Describe()); + var stack = new List(); + while (true) + { + if (curChild < curNode!.ChildCount()) + { + stack.Add(curChild + 1); + curNode = curNode.Child(curChild); + curChild = 0; + + sb.Append(new string(' ', stack.Count * 2)).Append(curNode.Describe()).AppendLine(); + } + else + { + if (stack.Count == 0) + { + break; + } + + curChild = stack[stack.Count - 1]; + stack.RemoveAt(stack.Count - 1); + curNode = curNode.Parent; + } + } + + return sb.ToString(); + } [ExcludeFromCodeCoverage] - public string Description() + private string Describe() { - var sb = new StringBuilder(TypeName); + var sb = new StringBuilder(Kind.ToString()); if ((Options & RegexOptions.ExplicitCapture) != 0) sb.Append("-C"); if ((Options & RegexOptions.IgnoreCase) != 0) sb.Append("-I"); @@ -2344,53 +2613,53 @@ public string Description() if ((Options & RegexOptions.IgnorePatternWhitespace) != 0) sb.Append("-X"); if ((Options & RegexOptions.ECMAScript) != 0) sb.Append("-E"); - switch (Type) - { - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Notonelazy: - case One: - case Notone: - sb.Append(" '").Append(RegexCharClass.CharDescription(Ch)).Append('\''); + switch (Kind) + { + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.One: + case RegexNodeKind.Notone: + sb.Append(" '").Append(RegexCharClass.DescribeChar(Ch)).Append('\''); break; - case Capture: + case RegexNodeKind.Capture: sb.Append(' ').Append($"index = {M}"); if (N != -1) { sb.Append($", unindex = {N}"); } break; - case Ref: - case Testref: + case RegexNodeKind.Backreference: + case RegexNodeKind.BackreferenceConditional: sb.Append(' ').Append($"index = {M}"); break; - case Multi: + case RegexNodeKind.Multi: sb.Append(" \"").Append(Str).Append('"'); break; - case Set: - case Setloop: - case Setloopatomic: - case Setlazy: - sb.Append(' ').Append(RegexCharClass.SetDescription(Str!)); + case RegexNodeKind.Set: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Setlazy: + sb.Append(' ').Append(RegexCharClass.DescribeSet(Str!)); break; } - switch (Type) + switch (Kind) { - case Oneloop: - case Oneloopatomic: - case Notoneloop: - case Notoneloopatomic: - case Onelazy: - case Notonelazy: - case Setloop: - case Setloopatomic: - case Setlazy: - case Loop: - case Lazyloop: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Onelazy: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Setlazy: + case RegexNodeKind.Loop: + case RegexNodeKind.Lazyloop: sb.Append( (M == 0 && N == int.MaxValue) ? "*" : (M == 0 && N == 1) ? "?" : @@ -2403,42 +2672,6 @@ public string Description() return sb.ToString(); } - - [ExcludeFromCodeCoverage] - public void Dump() => Debug.WriteLine(ToString()); - - [ExcludeFromCodeCoverage] - public override string ToString() - { - RegexNode? curNode = this; - int curChild = 0; - var sb = new StringBuilder().AppendLine(curNode.Description()); - var stack = new List(); - while (true) - { - if (curChild < curNode!.ChildCount()) - { - stack.Add(curChild + 1); - curNode = curNode.Child(curChild); - curChild = 0; - - sb.Append(new string(' ', stack.Count * 2)).Append(curNode.Description()).AppendLine(); - } - else - { - if (stack.Count == 0) - { - break; - } - - curChild = stack[stack.Count - 1]; - stack.RemoveAt(stack.Count - 1); - curNode = curNode.Next; - } - } - - return sb.ToString(); - } #endif } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNodeKind.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNodeKind.cs new file mode 100644 index 0000000000000..9db755a4fdc67 --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNodeKind.cs @@ -0,0 +1,180 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.RegularExpressions +{ + /// Specifies the kind of a . + internal enum RegexNodeKind + { + /// Unknown node type. + /// This should never occur on an actual node, and instead is used as a sentinel. + Unknown = 0, + + // The following are leaves (no children) and correspond to primitive operations in the regular expression. + + /// A specific character, e.g. `a`. + /// The character is specified in . + One = RegexOpcode.One, + /// Anything other than a specific character, e.g. `.` when not in mode, or `[^a]`. + /// The character is specified in . + Notone = RegexOpcode.Notone, + /// A character class / set, e.g. `[a-z1-9]` or `\w`. + /// The set string is specified in . + Set = RegexOpcode.Set, + + /// A sequence of at least two specific characters, e.g. `abc`. + /// The characters are specified in . This is purely a representational optimization, equivalent to multiple nodes concatenated together. + Multi = RegexOpcode.Multi, + + /// A loop around a specific character, e.g. `a*`. + /// + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + /// + Oneloop = RegexOpcode.Oneloop, + /// A loop around anything other than a specific character, e.g. `.*` when not in mode, or `[^a]*`. + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + Notoneloop = RegexOpcode.Notoneloop, + /// A loop around a character class / set, e.g. `[a-z1-9]*` or `\w*`. + /// The set string is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + Setloop = RegexOpcode.Setloop, + + /// A lazy loop around a specific character, e.g. `a*?`. + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + Onelazy = RegexOpcode.Onelazy, + /// A lazy loop around anything other than a specific character, e.g. `.*?` when not in mode, or `[^a]*?`. + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + Notonelazy = RegexOpcode.Notonelazy, + /// A lazy loop around a character class / set, e.g. `[a-z1-9]*?` or `\w?`. + /// The set string is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + Setlazy = RegexOpcode.Setlazy, + + /// An atomic loop around a specific character, e.g. `(?> a*)`. + /// + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + /// + Oneloopatomic = RegexOpcode.Oneloopatomic, + /// An atomic loop around anything other than a specific character, e.g. `(?>.*)` when not in mode. + /// + /// The character is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + /// + Notoneloopatomic = RegexOpcode.Notoneloopatomic, + /// An atomic loop around a character class / set, e.g. `(?>\d*)`. + /// + /// The set string is specified in , the minimum number of iterations in , and the maximum number of iterations in . + /// This is purely a representational optimization, equivalent to a wrapped around a . + /// + Setloopatomic = RegexOpcode.Setloopatomic, + + /// A backreference, e.g. `\1`. + /// The capture group number referenced is stored in . + Backreference = RegexOpcode.Backreference, + + /// A beginning-of-line anchor, e.g. `^` in mode. + Bol = RegexOpcode.Bol, + /// An end-of-line anchor, e.g. `$` in mode. + Eol = RegexOpcode.Eol, + /// A word boundary anchor, e.g. `\b`. + Boundary = RegexOpcode.Boundary, + /// Not a word boundary anchor, e.g. `\B`. + NonBoundary = RegexOpcode.NonBoundary, + /// A word boundary anchor, e.g. `\b` in mode. + ECMABoundary = RegexOpcode.ECMABoundary, + /// Not a word boundary anchor, e.g. `\B` in mode.. + NonECMABoundary = RegexOpcode.NonECMABoundary, + /// A beginning-of-string anchor, e.g. `\A`, or `^` when not in mode. + Beginning = RegexOpcode.Beginning, + /// A start anchor, e.g. `\G`. + Start = RegexOpcode.Start, + /// A end-of-string-or-before-ending-newline anchor, e.g. `\Z`, or `$` when not in mode. + EndZ = RegexOpcode.EndZ, + /// A end-of-string-only anchor, e.g. `\z`. + End = RegexOpcode.End, + + /// A fabricated node injected during analyses to signal a location in the matching where the engine may set the next bumpalong position to the current position. + UpdateBumpalong = RegexOpcode.UpdateBumpalong, + + /// Fails when matching an empty string, e.g. `(?!)`. + Nothing = RegexOpcode.Nothing, + /// Matches the empty string, e.g. ``. + Empty = 23, + + // The following are interior nodes (have at least one child) and correspond to control structures composing other operations. + + /// An alternation between branches, e.g. `ab|cd`. + /// + /// Each child represents one branch, in lexical order. A valid alternation contains at + /// least two children: if an alternation contains only a single child, it can be replaced + /// by that child, and if an alternation has no children, it can be replaced by . + /// + Alternate = 24, + /// A sequence / concatenation of nodes, e.g. a[bc]. + /// + /// Each child represents one node in the sequence, in lexical order. A valid concatenation contains at + /// least two children: if a concatenation contains only a single child, it can be replaced + /// by that child, and if a concatenation has no children, it can be replaced by . + /// + Concatenate = 25, + + /// A loop around an arbitrary , e.g. `(ab|cd)*`. + /// + /// One and only one child, the expression in the loop. The minimum number of iterations is in , + /// and the maximum number of iterations is in . + /// + Loop = 26, + /// A lazy loop around an arbitrary , e.g. `(ab|cd)*?`. + /// + /// One and only one child, the expression in the loop. The minimum number of iterations is in , + /// and the maximum number of iterations is in . + /// + Lazyloop = 27, + + /// A capture group, e.g. `(\w*)`. + /// + /// One and only one child, the expression in the capture. is the number of the capture, and if a balancing + /// group, is the uncapture. + /// + Capture = 28, + /// A non-capturing group, e.g. `(?:ab|cd)`. + /// + /// One and only one child, the expression in the group. Groups are irrelevant after parsing and can be replaced entirely by their child. + /// These should not be in a valid tree returned from the parsing / reduction phases of processing. + /// + Group = 29, + /// An atomic group, e.g. `(?>ab|cd)`. + /// One and only one child, the expression in the group. + Atomic = 32, + + /// + /// A positive lookaround assertion: lookahead if is not set and lookbehind if + /// is set, e.g. `(?=abc)` or `(?<=abc)`. + /// One and only one child, the expression in the assertion. + PositiveLookaround = 30, + /// + /// A negative lookaround assertion: lookahead if is not set and lookbehind if + /// is set, e.g. `(?!abc)` or `(?<!abc)`. + /// One and only one child, the expression in the assertion. + NegativeLookaround = 31, + + /// A backreference conditional, e.g. `(?(1)abc|def)`. + /// + /// Two children, the first to use if the reference capture group matched and the second to use if it didn't. + /// The referenced capture group number is stored in . + /// + BackreferenceConditional = 33, + /// An expression conditional, e.g. `(?(\d{3})123456|abc)`. + /// + /// Three children. The first is the expression to evaluate as a positive lookahead assertion, the second is + /// the expression to match if the positive lookahead assertion was successful, and the third is the expression + /// to match if the positive lookahead assertion was unsuccessful. + /// + ExpressionConditional = 34, + } +} diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOpcode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOpcode.cs new file mode 100644 index 0000000000000..eaaa355aa9700 --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOpcode.cs @@ -0,0 +1,162 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.RegularExpressions +{ + /// Opcodes written by and used by to process a regex. + /// + /// stores an int[] containing all of the codes that make up the instructions for + /// the interpreter to process the regular expression. The array contains a packed sequence of operations, + /// each of which is an stored as an int, followed immediately by all of the operands + /// required for that operation. For example, the subexpression `a{2,7}[^b]` would be represented as the sequence + /// 0 97 2 3 97 5 10 98 + /// which is interpreted as: + /// 0 = opcode for Onerep (a{2, 7} is written out as a repeater for the minimum followed by a loop for the maximum minus the minimum) + /// 97 = 'a' + /// 2 = repeat count + /// 3 = opcode for Oneloop + /// 97 = 'a' + /// 5 = max iteration count + /// 10 = opcode for Notone + /// 98 = 'b' + /// + internal enum RegexOpcode + { + // Primitive operations + + /// Repeater of the specified character. + /// Operand 0 is the character. Operand 1 is the repetition count. + Onerep = 0, + /// Repeater of a single character other than the one specified. + /// Operand 0 is the character. Operand 1 is the repetition count. + Notonerep = 1, + /// Repeater of a single character matching the specified set + /// Operand 0 is index into the strings table of the character class description. Operand 1 is the repetition count. + Setrep = 2, + + /// Greedy loop of the specified character. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Oneloop = 3, + /// Greedy loop of a single character other than the one specified. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Notoneloop = 4, + /// Greedy loop of a single character matching the specified set + /// Operand 0 is index into the strings table of the character class description. Operand 1 is the repetition count. + Setloop = 5, + + /// Lazy loop of the specified character. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Onelazy = 6, + /// Lazy loop of a single character other than the one specified. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Notonelazy = 7, + /// Lazy loop of a single character matching the specified set + /// Operand 0 is index into the strings table of the character class description. Operand 1 is the repetition count. + Setlazy = 8, + + /// Single specified character. + /// Operand 0 is the character. + One = 9, + /// Single character other than the one specified. + /// Operand 0 is the character. + Notone = 10, + /// Single character matching the specified set. + /// Operand 0 is index into the strings table of the character class description. + Set = 11, + + /// Multiple characters in sequence. + /// Operand 0 is index into the strings table for the string of characters. + Multi = 12, + + /// Backreference to a capture group. + /// Operand 0 is the capture group number. + Backreference = 13, + + /// Beginning-of-line anchor (^ with RegexOptions.Multiline). + Bol = 14, + /// End-of-line anchor ($ with RegexOptions.Multiline). + Eol = 15, + /// Word boundary (\b). + Boundary = 16, + /// Word non-boundary (\B). + NonBoundary = 17, + /// Beginning-of-input anchor (\A). + Beginning = 18, + /// Start-of-input anchor (\G). + Start = 19, + /// End-of-input anchor (\Z). + EndZ = 20, + /// End-of-input anchor (\z). + End = 21, + /// Match nothing (fail). + Nothing = 22, + /// Word boundary (\b with RegexOptions.ECMAScript). + ECMABoundary = 41, + /// Word non-boundary (\B with RegexOptions.ECMAScript). + NonECMABoundary = 42, + + /// Atomic loop of the specified character. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Oneloopatomic = 43, + /// Atomic loop of a single character other than the one specified. + /// Operand 0 is the character. Operand 1 is the max iteration count. + Notoneloopatomic = 44, + /// Atomic loop of a single character matching the specified set + /// Operand 0 is index into the strings table of the character class description. Operand 1 is the repetition count. + Setloopatomic = 45, + + /// Updates the bumpalong position to the current position. + UpdateBumpalong = 46, + + // Primitive control structures + // TODO: Figure out what these comments mean / what these control structures actually do :) + + /// back jump straight first. + Lazybranch = 23, + /// back jump branch first for loop. + Branchmark = 24, + /// back jump straight first for loop. + Lazybranchmark = 25, + /// back val set counter, null mark. + Nullcount = 26, + /// back val set counter, make mark + Setcount = 27, + /// back jump,limit branch++ if zero<=c<limit. + Branchcount = 28, + /// back jump,limit same, but straight first. + Lazybranchcount = 29, + /// back save position. + Nullmark = 30, + /// back save position. + Setmark = 31, + /// back group define group. + Capturemark = 32, + /// back recall position. + Getmark = 33, + /// back save backtrack state. + Setjump = 34, + /// zap back to saved state. + Backjump = 35, + /// zap backtracking state. + Forejump = 36, + /// Backtrack if ref undefined. + TestBackreference = 37, + /// jump just go. + Goto = 38, + /// done! + Stop = 40, + + // Modifiers for alternate modes + + /// Mask to get unmodified ordinary operator. + OperatorMask = 63, + /// Indicates that we're reverse scanning. + RightToLeft = 64, + /// Indicates that we're backtracking. + Backtracking = 128, + /// Indicates that we're backtracking on a second branch. + BacktrackingSecond = 256, + /// Indicates that we're case-insensitive + CaseInsensitive = 512, + } +} diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs index 47b7eed807dc7..351b1b91a9fe5 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs @@ -30,7 +30,7 @@ enum RegexOptions ExplicitCapture = 0x0004, // "n" /// Compile the regular expression to Microsoft intermediate language (MSIL). - Compiled = 0x0008, // "c" + Compiled = 0x0008, /// /// Use single-line mode, where the period (.) matches every character (instead of every character except \n). @@ -41,15 +41,10 @@ enum RegexOptions IgnorePatternWhitespace = 0x0020, // "x" /// Change the search direction. Search moves from right to left instead of from left to right. - RightToLeft = 0x0040, // "r" - -#if DEBUG - /// Enable Regex debugging. - Debug = 0x0080, // "d" -#endif + RightToLeft = 0x0040, /// Enable ECMAScript-compliant behavior for the expression. - ECMAScript = 0x0100, // "e" + ECMAScript = 0x0100, /// Ignore cultural differences in language. CultureInvariant = 0x0200, diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs index 02b4f1408e679..b81e9d88e86b2 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs @@ -255,7 +255,7 @@ private RegexNode ScanRegex() char ch; bool isQuantifier = false; - StartGroup(new RegexNode(RegexNode.Capture, _options, 0, -1)); + StartGroup(new RegexNode(RegexNodeKind.Capture, _options, 0, -1)); while (CharsRight() > 0) { @@ -326,8 +326,8 @@ private RegexNode ScanRegex() { string setString = ScanCharClass(UseOptionI(), scanOnly: false)!.ToStringClass(_options); _unit = UseOptionI() && RegexCharClass.MakeCaseSensitiveIfPossible(setString, _culture) is string newSetString ? - new RegexNode(RegexNode.Set, _options & ~RegexOptions.IgnoreCase, newSetString) : - new RegexNode(RegexNode.Set, _options, setString); + new RegexNode(RegexNodeKind.Set, _options & ~RegexOptions.IgnoreCase, newSetString) : + new RegexNode(RegexNodeKind.Set, _options, setString); } break; @@ -379,17 +379,17 @@ private RegexNode ScanRegex() break; case '^': - AddUnitType(UseOptionM() ? RegexNode.Bol : RegexNode.Beginning); + AddUnitType(UseOptionM() ? RegexNodeKind.Bol : RegexNodeKind.Beginning); break; case '$': - AddUnitType(UseOptionM() ? RegexNode.Eol : RegexNode.EndZ); + AddUnitType(UseOptionM() ? RegexNodeKind.Eol : RegexNodeKind.EndZ); break; case '.': _unit = UseOptionS() ? - new RegexNode(RegexNode.Set, _options & ~RegexOptions.IgnoreCase, RegexCharClass.AnyClass) : - new RegexNode(RegexNode.Notone, _options & ~RegexOptions.IgnoreCase, '\n'); + new RegexNode(RegexNodeKind.Set, _options & ~RegexOptions.IgnoreCase, RegexCharClass.AnyClass) : + new RegexNode(RegexNodeKind.Notone, _options & ~RegexOptions.IgnoreCase, '\n'); break; case '{': @@ -451,10 +451,7 @@ private RegexNode ScanRegex() if (CharsRight() > 0 && RightChar() == ',') { MoveRight(); - if (CharsRight() == 0 || RightChar() == '}') - max = int.MaxValue; - else - max = ScanDecimal(); + max = CharsRight() == 0 || RightChar() == '}' ? int.MaxValue : ScanDecimal(); } } @@ -511,7 +508,7 @@ private RegexNode ScanRegex() */ private RegexNode ScanReplacement() { - _concatenation = new RegexNode(RegexNode.Concatenate, _options); + _concatenation = new RegexNode(RegexNodeKind.Concatenate, _options); while (true) { @@ -541,7 +538,7 @@ private RegexNode ScanReplacement() // groups are unsupported. However, the replacement patterns that refer to the left/right portion // or all of the input as well as referring to group 0 (i.e. the whole match) are supported. if ((_options & RegexOptions.NonBacktracking) != 0 && - node.Type == RegexNode.Ref && + node.Kind == RegexNodeKind.Backreference && node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortion or RegexReplacement.WholeString)) { throw new NotSupportedException(SR.NotSupported_NonBacktrackingAndReplacementsWithSubstitutionsOfGroups); @@ -788,11 +785,11 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio if (UseOptionN() || _ignoreNextParen) { _ignoreNextParen = false; - return new RegexNode(RegexNode.Group, _options); + return new RegexNode(RegexNodeKind.Group, _options); } else { - return new RegexNode(RegexNode.Capture, _options, _autocap++, -1); + return new RegexNode(RegexNodeKind.Capture, _options, _autocap++, -1); } } @@ -805,31 +802,31 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio break; } - int nodeType; + RegexNodeKind nodeType; char close = '>'; char ch = RightCharMoveRight(); switch (ch) { case ':': // noncapturing group - nodeType = RegexNode.Group; + nodeType = RegexNodeKind.Group; break; case '=': // lookahead assertion _options &= ~RegexOptions.RightToLeft; - nodeType = RegexNode.Require; + nodeType = RegexNodeKind.PositiveLookaround; break; case '!': // negative lookahead assertion _options &= ~RegexOptions.RightToLeft; - nodeType = RegexNode.Prevent; + nodeType = RegexNodeKind.NegativeLookaround; break; case '>': // atomic subexpression - nodeType = RegexNode.Atomic; + nodeType = RegexNodeKind.Atomic; break; case '\'': @@ -852,7 +849,7 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio // lookbehind assertion _options |= RegexOptions.RightToLeft; - nodeType = RegexNode.Require; + nodeType = RegexNodeKind.PositiveLookaround; break; case '!': @@ -863,7 +860,7 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio // negative lookbehind assertion _options |= RegexOptions.RightToLeft; - nodeType = RegexNode.Prevent; + nodeType = RegexNodeKind.NegativeLookaround; break; default: @@ -921,7 +918,7 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio // grab part after - if any - if ((capnum != -1 || proceed == true) && CharsRight() > 1 && RightChar() == '-') + if ((capnum != -1 || proceed) && CharsRight() > 1 && RightChar() == '-') { MoveRight(); ch = RightChar(); @@ -971,7 +968,7 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio if ((capnum != -1 || uncapnum != -1) && CharsRight() > 0 && RightCharMoveRight() == close) { - return new RegexNode(RegexNode.Capture, _options, capnum, uncapnum); + return new RegexNode(RegexNodeKind.Capture, _options, capnum, uncapnum); } goto BreakRecognize; } @@ -993,7 +990,7 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio { if (IsCaptureSlot(capnum)) { - return new RegexNode(RegexNode.Testref, _options, capnum); + return new RegexNode(RegexNodeKind.BackreferenceConditional, _options, capnum); } throw MakeException(RegexParseError.AlternationHasUndefinedReference, SR.Format(SR.AlternationHasUndefinedReference, capnum.ToString())); @@ -1007,12 +1004,12 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio if (IsCaptureName(capname) && CharsRight() > 0 && RightCharMoveRight() == ')') { - return new RegexNode(RegexNode.Testref, _options, CaptureSlotFromName(capname)); + return new RegexNode(RegexNodeKind.BackreferenceConditional, _options, CaptureSlotFromName(capname)); } } } // not a backref - nodeType = RegexNode.Testgroup; + nodeType = RegexNodeKind.ExpressionConditional; Textto(parenPos - 1); // jump to the start of the parentheses _ignoreNextParen = true; // but make sure we don't try to capture the insides @@ -1044,9 +1041,9 @@ node.M is not (0 or RegexReplacement.LeftPortion or RegexReplacement.RightPortio default: MoveLeft(); - nodeType = RegexNode.Group; + nodeType = RegexNodeKind.Group; // Disallow options in the children of a testgroup node - if (_group!.Type != RegexNode.Testgroup) + if (_group!.Kind != RegexNodeKind.ExpressionConditional) { ScanOptions(); } @@ -1173,32 +1170,32 @@ private void ScanBlank() case 'w': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMAWordClass : RegexCharClass.WordClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMAWordClass : RegexCharClass.WordClass); case 'W': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMAWordClass : RegexCharClass.NotWordClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMAWordClass : RegexCharClass.NotWordClass); case 's': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMASpaceClass : RegexCharClass.SpaceClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMASpaceClass : RegexCharClass.SpaceClass); case 'S': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMASpaceClass : RegexCharClass.NotSpaceClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMASpaceClass : RegexCharClass.NotSpaceClass); case 'd': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMADigitClass : RegexCharClass.DigitClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.ECMADigitClass : RegexCharClass.DigitClass); case 'D': MoveRight(); return scanOnly ? null : - new RegexNode(RegexNode.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMADigitClass : RegexCharClass.NotDigitClass); + new RegexNode(RegexNodeKind.Set, RemoveIgnoreCaseIfNotEcma(_options), UseOptionE() ? RegexCharClass.NotECMADigitClass : RegexCharClass.NotDigitClass); case 'p': case 'P': @@ -1215,7 +1212,7 @@ private void ScanBlank() cc.AddLowercase(_culture); } - return new RegexNode(RegexNode.Set, _options, cc.ToStringClass(_options)); + return new RegexNode(RegexNodeKind.Set, _options, cc.ToStringClass(_options)); default: return ScanBasicBackslash(scanOnly); @@ -1259,7 +1256,7 @@ static RegexOptions RemoveIgnoreCaseIfNotEcma(RegexOptions options) { MoveRight(); ch = RightCharMoveRight(); - if (ch == '<' || ch == '\'') + if (ch is '<' or '\'') { angled = true; close = (ch == '\'') ? '\'' : '>'; @@ -1294,7 +1291,7 @@ static RegexOptions RemoveIgnoreCaseIfNotEcma(RegexOptions options) { return scanOnly ? null : - IsCaptureSlot(capnum) ? new RegexNode(RegexNode.Ref, _options, capnum) : + IsCaptureSlot(capnum) ? new RegexNode(RegexNodeKind.Backreference, _options, capnum) : throw MakeException(RegexParseError.UndefinedNumberedReference, SR.Format(SR.UndefinedNumberedReference, capnum.ToString())); } } @@ -1326,7 +1323,7 @@ static RegexOptions RemoveIgnoreCaseIfNotEcma(RegexOptions options) if (capnum >= 0) { - return scanOnly ? null : new RegexNode(RegexNode.Ref, _options, capnum); + return scanOnly ? null : new RegexNode(RegexNodeKind.Backreference, _options, capnum); } } else @@ -1340,7 +1337,7 @@ static RegexOptions RemoveIgnoreCaseIfNotEcma(RegexOptions options) if (IsCaptureSlot(capnum)) { - return new RegexNode(RegexNode.Ref, _options, capnum); + return new RegexNode(RegexNodeKind.Backreference, _options, capnum); } if (capnum <= 9) @@ -1360,7 +1357,7 @@ static RegexOptions RemoveIgnoreCaseIfNotEcma(RegexOptions options) { return scanOnly ? null : - IsCaptureName(capname) ? new RegexNode(RegexNode.Ref, _options, CaptureSlotFromName(capname)) : + IsCaptureName(capname) ? new RegexNode(RegexNodeKind.Backreference, _options, CaptureSlotFromName(capname)) : throw MakeException(RegexParseError.UndefinedNamedReference, SR.Format(SR.UndefinedNamedReference, capname)); } } @@ -1440,7 +1437,7 @@ private RegexNode ScanDollar() Textto(lastEndPos); if (capnum >= 0) { - return new RegexNode(RegexNode.Ref, _options, capnum); + return new RegexNode(RegexNodeKind.Backreference, _options, capnum); } } else @@ -1451,7 +1448,7 @@ private RegexNode ScanDollar() CheckUnsupportedNonBacktrackingNumericRef(capnum); if (IsCaptureSlot(capnum)) { - return new RegexNode(RegexNode.Ref, _options, capnum); + return new RegexNode(RegexNodeKind.Backreference, _options, capnum); } } } @@ -1470,7 +1467,7 @@ private RegexNode ScanDollar() if (IsCaptureName(capname)) { - return new RegexNode(RegexNode.Ref, _options, CaptureSlotFromName(capname)); + return new RegexNode(RegexNodeKind.Backreference, _options, CaptureSlotFromName(capname)); } } } @@ -1508,7 +1505,7 @@ private RegexNode ScanDollar() if (capnum != 1) { MoveRight(); - return new RegexNode(RegexNode.Ref, _options, capnum); + return new RegexNode(RegexNodeKind.Backreference, _options, capnum); } } @@ -1786,41 +1783,30 @@ private string ParseProperty() return capname; } - /// Returns ReNode type for zero-length assertions with a \ code. - private int TypeFromCode(char ch) => + /// Returns the node kind for zero-length assertions with a \ code. + private RegexNodeKind TypeFromCode(char ch) => ch switch { - 'b' => UseOptionE() ? RegexNode.ECMABoundary : RegexNode.Boundary, - 'B' => UseOptionE() ? RegexNode.NonECMABoundary : RegexNode.NonBoundary, - 'A' => RegexNode.Beginning, - 'G' => RegexNode.Start, - 'Z' => RegexNode.EndZ, - 'z' => RegexNode.End, - _ => RegexNode.Nothing, + 'b' => UseOptionE() ? RegexNodeKind.ECMABoundary : RegexNodeKind.Boundary, + 'B' => UseOptionE() ? RegexNodeKind.NonECMABoundary : RegexNodeKind.NonBoundary, + 'A' => RegexNodeKind.Beginning, + 'G' => RegexNodeKind.Start, + 'Z' => RegexNodeKind.EndZ, + 'z' => RegexNodeKind.End, + _ => RegexNodeKind.Nothing, }; - /// Returns option bit from single-char (?cimsx) code. - private static RegexOptions OptionFromCode(char ch) - { - // case-insensitive - if ((uint)(ch - 'A') <= 'Z' - 'A') - { - ch += (char)('a' - 'A'); - } - - return ch switch + /// Returns option bit from single-char (?imnsx) code. + private static RegexOptions OptionFromCode(char ch) => + (char)(ch | 0x20) switch { 'i' => RegexOptions.IgnoreCase, 'm' => RegexOptions.Multiline, 'n' => RegexOptions.ExplicitCapture, 's' => RegexOptions.Singleline, 'x' => RegexOptions.IgnorePatternWhitespace, -#if DEBUG - 'd' => RegexOptions.Debug, -#endif - _ => 0, + _ => RegexOptions.None, }; - } /// /// A prescanner for deducing the slots used for captures by doing a partial tokenization of the pattern. @@ -2183,7 +2169,7 @@ private void AddConcatenate(int pos, int cch, bool isReplacement) break; case > 1 when !UseOptionI() || isReplacement || !RegexCharClass.ParticipatesInCaseConversion(_pattern.AsSpan(pos, cch)): - _concatenation!.AddChild(new RegexNode(RegexNode.Multi, _options & ~RegexOptions.IgnoreCase, _pattern.Substring(pos, cch))); + _concatenation!.AddChild(new RegexNode(RegexNodeKind.Multi, _options & ~RegexOptions.IgnoreCase, _pattern.Substring(pos, cch))); break; default: @@ -2198,9 +2184,9 @@ private void AddConcatenate(int pos, int cch, bool isReplacement) /// Push the parser state (in response to an open paren) private void PushGroup() { - _group!.Next = _stack; - _alternation!.Next = _group; - _concatenation!.Next = _alternation; + _group!.Parent = _stack; + _alternation!.Parent = _group; + _concatenation!.Parent = _alternation; _stack = _concatenation; } @@ -2208,12 +2194,12 @@ private void PushGroup() private void PopGroup() { _concatenation = _stack; - _alternation = _concatenation!.Next; - _group = _alternation!.Next; - _stack = _group!.Next; + _alternation = _concatenation!.Parent; + _group = _alternation!.Parent; + _stack = _group!.Parent; // The first () inside a Testgroup group goes directly to the group - if (_group.Type == RegexNode.Testgroup && _group.ChildCount() == 0) + if (_group.Kind == RegexNodeKind.ExpressionConditional && _group.ChildCount() == 0) { if (_unit == null) { @@ -2232,8 +2218,8 @@ private void PopGroup() private void StartGroup(RegexNode openGroup) { _group = openGroup; - _alternation = new RegexNode(RegexNode.Alternate, _options); - _concatenation = new RegexNode(RegexNode.Concatenate, _options); + _alternation = new RegexNode(RegexNodeKind.Alternate, _options); + _concatenation = new RegexNode(RegexNodeKind.Concatenate, _options); } /// Finish the current concatenation (in response to a |) @@ -2241,7 +2227,7 @@ private void AddAlternate() { // The | parts inside a Testgroup group go directly to the group - if (_group!.Type == RegexNode.Testgroup || _group.Type == RegexNode.Testref) + if (_group!.Kind is RegexNodeKind.ExpressionConditional or RegexNodeKind.BackreferenceConditional) { _group.AddChild(_concatenation!.ReverseConcatenationIfRightToLeft()); } @@ -2250,7 +2236,7 @@ private void AddAlternate() _alternation!.AddChild(_concatenation!.ReverseConcatenationIfRightToLeft()); } - _concatenation = new RegexNode(RegexNode.Concatenate, _options); + _concatenation = new RegexNode(RegexNodeKind.Concatenate, _options); } /// Finish the current quantifiable (when a quantifier is not found or is not possible) @@ -2279,16 +2265,16 @@ private void AddConcatenate(bool lazy, int min, int max) private void AddUnitNode(RegexNode node) => _unit = node; /// Sets the current unit to an assertion of the specified type - private void AddUnitType(int type) => _unit = new RegexNode(type, _options); + private void AddUnitType(RegexNodeKind type) => _unit = new RegexNode(type, _options); /// Finish the current group (in response to a ')' or end) private void AddGroup() { - if (_group!.Type == RegexNode.Testgroup || _group.Type == RegexNode.Testref) + if (_group!.Kind is RegexNodeKind.ExpressionConditional or RegexNodeKind.BackreferenceConditional) { _group.AddChild(_concatenation!.ReverseConcatenationIfRightToLeft()); - if (_group.Type == RegexNode.Testref && _group.ChildCount() > 2 || _group.ChildCount() > 3) + if (_group.Kind == RegexNodeKind.BackreferenceConditional && _group.ChildCount() > 2 || _group.ChildCount() > 3) { throw MakeException(RegexParseError.AlternationHasTooManyConditions, SR.AlternationHasTooManyConditions); } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs index 7b762188411b4..c3e80fc991371 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Threading; @@ -14,18 +13,8 @@ namespace System.Text.RegularExpressions internal ref struct RegexPrefixAnalyzer { private const int StackBufferSize = 32; - private const int BeforeChild = 64; - private const int AfterChild = 128; - - // where the regex can be pegged - public const int Beginning = 0x0001; - public const int Bol = 0x0002; - public const int Start = 0x0004; - public const int Eol = 0x0008; - public const int EndZ = 0x0010; - public const int End = 0x0020; - public const int Boundary = 0x0040; - public const int ECMABoundary = 0x0080; + private const RegexNodeKind BeforeChild = (RegexNodeKind)64; + private const RegexNodeKind AfterChild = (RegexNodeKind)128; private readonly List _fcStack; private ValueListBuilder _intStack; // must not be readonly @@ -33,6 +22,14 @@ internal ref struct RegexPrefixAnalyzer private bool _skipchild; // don't process the current child. private bool _failed; +#if DEBUG + static RegexPrefixAnalyzer() + { + Debug.Assert(!Enum.IsDefined(typeof(RegexNodeKind), BeforeChild)); + Debug.Assert(!Enum.IsDefined(typeof(RegexNodeKind), AfterChild)); + } +#endif + private RegexPrefixAnalyzer(Span intStack) { _fcStack = new List(StackBufferSize); @@ -42,11 +39,11 @@ private RegexPrefixAnalyzer(Span intStack) _skipAllChildren = false; } - /// Computes the leading substring in ; may be empty. - public static string FindCaseSensitivePrefix(RegexTree tree) + /// Computes the leading substring in ; may be empty. + public static string FindCaseSensitivePrefix(RegexNode node) { var vsb = new ValueStringBuilder(stackalloc char[64]); - Process(tree.Root, ref vsb); + Process(node, ref vsb); return vsb.ToString(); // Processes the node, adding any prefix text to the builder. @@ -63,10 +60,10 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) // when handling RightToLeft. bool rtl = (node.Options & RegexOptions.RightToLeft) != 0; - switch (node.Type) + switch (node.Kind) { // Concatenation - case RegexNode.Concatenate: + case RegexNodeKind.Concatenate: { int childCount = node.ChildCount(); for (int i = 0; i < childCount; i++) @@ -80,17 +77,19 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) } // Alternation: find a string that's a shared prefix of all branches - case RegexNode.Alternate: + case RegexNodeKind.Alternate: { int childCount = node.ChildCount(); - // Store the initial branch into the target builder + // Store the initial branch into the target builder, keeping track + // of how much was appended. Any of this contents that doesn't overlap + // will every other branch will be removed before returning. int initialLength = vsb.Length; - bool keepExploring = Process(node.Child(0), ref vsb); + Process(node.Child(0), ref vsb); int addedLength = vsb.Length - initialLength; // Then explore the rest of the branches, finding the length - // a prefix they all share in common with the initial branch. + // of prefix they all share in common with the initial branch. if (addedLength != 0) { var alternateSb = new ValueStringBuilder(64); @@ -101,19 +100,18 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) { alternateSb.Length = 0; - // Process the branch. We want to keep exploring after this alternation, - // but we can't if either this branch doesn't allow for it or if the prefix - // supplied by this branch doesn't entirely match all the previous ones. - keepExploring &= Process(node.Child(i), ref alternateSb); - keepExploring &= alternateSb.Length == addedLength; + // Process the branch into a temporary builder. + Process(node.Child(i), ref alternateSb); + // Find how much overlap there is between this branch's prefix + // and the smallest amount of prefix that overlapped with all + // the previously seen branches. addedLength = Math.Min(addedLength, alternateSb.Length); for (int j = 0; j < addedLength; j++) { if (vsb[initialLength + j] != alternateSb[j]) { addedLength = j; - keepExploring = false; break; } } @@ -125,28 +123,31 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) vsb.Length = initialLength + addedLength; } - return !rtl && keepExploring; + // Don't explore anything after the alternation. We could make this work if desirable, + // but it's currently not worth the extra complication. The entire contents of every + // branch would need to be identical other than zero-width anchors/assertions. + return false; } // One character - case RegexNode.One when (node.Options & RegexOptions.IgnoreCase) == 0: + case RegexNodeKind.One when (node.Options & RegexOptions.IgnoreCase) == 0: vsb.Append(node.Ch); return !rtl; // Multiple characters - case RegexNode.Multi when (node.Options & RegexOptions.IgnoreCase) == 0: + case RegexNodeKind.Multi when (node.Options & RegexOptions.IgnoreCase) == 0: vsb.Append(node.Str); return !rtl; // Loop of one character - case RegexNode.Oneloop or RegexNode.Oneloopatomic or RegexNode.Onelazy when node.M > 0 && (node.Options & RegexOptions.IgnoreCase) == 0: + case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy when node.M > 0 && (node.Options & RegexOptions.IgnoreCase) == 0: const int SingleCharIterationLimit = 32; // arbitrary cut-off to avoid creating super long strings unnecessarily int count = Math.Min(node.M, SingleCharIterationLimit); vsb.Append(node.Ch, count); return count == node.N && !rtl; // Loop of a node - case RegexNode.Loop or RegexNode.Lazyloop when node.M > 0: + case RegexNodeKind.Loop or RegexNodeKind.Lazyloop when node.M > 0: { const int NodeIterationLimit = 4; // arbitrary cut-off to avoid creating super long strings unnecessarily int limit = Math.Min(node.M, NodeIterationLimit); @@ -161,25 +162,25 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) } // Grouping nodes for which we only care about their single child - case RegexNode.Atomic: - case RegexNode.Capture: + case RegexNodeKind.Atomic: + case RegexNodeKind.Capture: return Process(node.Child(0), ref vsb); // Zero-width anchors and assertions - case RegexNode.Bol: - case RegexNode.Eol: - case RegexNode.Boundary: - case RegexNode.ECMABoundary: - case RegexNode.NonBoundary: - case RegexNode.NonECMABoundary: - case RegexNode.Beginning: - case RegexNode.Start: - case RegexNode.EndZ: - case RegexNode.End: - case RegexNode.Empty: - case RegexNode.UpdateBumpalong: - case RegexNode.Require: - case RegexNode.Prevent: + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.EndZ: + case RegexNodeKind.End: + case RegexNodeKind.Empty: + case RegexNodeKind.UpdateBumpalong: + case RegexNodeKind.PositiveLookaround: + case RegexNodeKind.NegativeLookaround: return true; // Give up for anything else @@ -342,9 +343,9 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in bool caseInsensitive = (node.Options & RegexOptions.IgnoreCase) != 0; - switch (node.Type) + switch (node.Kind) { - case RegexNode.One: + case RegexNodeKind.One: if (results.Count < MaxFixedResults) { string setString = RegexCharClass.OneToStringClass(node.Ch, caseInsensitive ? culture : null, out bool resultIsCaseInsensitive); @@ -353,7 +354,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in } return false; - case RegexNode.Onelazy or RegexNode.Oneloop or RegexNode.Oneloopatomic when node.M > 0: + case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when node.M > 0: { string setString = RegexCharClass.OneToStringClass(node.Ch, caseInsensitive ? culture : null, out bool resultIsCaseInsensitive); int minIterations = Math.Min(node.M, MaxLoopExpansion); @@ -365,7 +366,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in return i == node.M && i == node.N; } - case RegexNode.Multi: + case RegexNodeKind.Multi: { string s = node.Str!; int i = 0; @@ -377,7 +378,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in return i == s.Length; } - case RegexNode.Set: + case RegexNodeKind.Set: if (results.Count < MaxFixedResults) { results.Add((null, node.Str!, distance++, caseInsensitive)); @@ -385,7 +386,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in } return false; - case RegexNode.Setlazy or RegexNode.Setloop or RegexNode.Setloopatomic when node.M > 0: + case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when node.M > 0: { int minIterations = Math.Min(node.M, MaxLoopExpansion); int i = 0; @@ -396,41 +397,41 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in return i == node.M && i == node.N; } - case RegexNode.Notone: + case RegexNodeKind.Notone: // We could create a set out of Notone, but it will be of little value in helping to improve // the speed of finding the first place to match, as almost every character will match it. distance++; return true; - case RegexNode.Notonelazy or RegexNode.Notoneloop or RegexNode.Notoneloopatomic when node.M == node.N: + case RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic when node.M == node.N: distance += node.M; return true; - case RegexNode.Beginning: - case RegexNode.Bol: - case RegexNode.Boundary: - case RegexNode.ECMABoundary: - case RegexNode.Empty: - case RegexNode.End: - case RegexNode.EndZ: - case RegexNode.Eol: - case RegexNode.NonBoundary: - case RegexNode.NonECMABoundary: - case RegexNode.UpdateBumpalong: - case RegexNode.Start: - case RegexNode.Prevent: - case RegexNode.Require: - // Zero-width anchors and assertions. In theory for Prevent and Require we could also investigate - // them and use the learned knowledge to impact the generated sets, at least for lookaheads. + case RegexNodeKind.Beginning: + case RegexNodeKind.Bol: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.Empty: + case RegexNodeKind.End: + case RegexNodeKind.EndZ: + case RegexNodeKind.Eol: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.UpdateBumpalong: + case RegexNodeKind.Start: + case RegexNodeKind.NegativeLookaround: + case RegexNodeKind.PositiveLookaround: + // Zero-width anchors and assertions. In theory, for PositiveLookaround and NegativeLookaround we could also + // investigate them and use the learned knowledge to impact the generated sets, at least for lookaheads. // For now, we don't bother. return true; - case RegexNode.Atomic: - case RegexNode.Group: - case RegexNode.Capture: + case RegexNodeKind.Atomic: + case RegexNodeKind.Group: + case RegexNodeKind.Capture: return TryFindFixedSets(node.Child(0), results, ref distance, culture, thorough); - case RegexNode.Lazyloop or RegexNode.Loop when node.M > 0: + case RegexNodeKind.Lazyloop or RegexNodeKind.Loop when node.M > 0: // This effectively only iterates the loop once. If deemed valuable, // it could be updated in the future to duplicate the found results // (updated to incorporate distance from previous iterations) and @@ -440,7 +441,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in TryFindFixedSets(node.Child(0), results, ref distance, culture, thorough); return false; - case RegexNode.Concatenate: + case RegexNodeKind.Concatenate: { int childCount = node.ChildCount(); for (int i = 0; i < childCount; i++) @@ -453,7 +454,7 @@ static bool TryFindFixedSets(RegexNode node, List<(char[]? Chars, string Set, in return true; } - case RegexNode.Alternate when thorough: + case RegexNodeKind.Alternate when thorough: { int childCount = node.ChildCount(); bool allSameSize = true; @@ -572,11 +573,11 @@ public static (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Li } // Find the first concatenation. - while ((node.Type is RegexNode.Atomic or RegexNode.Capture) || (node.Type is RegexNode.Loop or RegexNode.Lazyloop && node.M > 0)) + while ((node.Kind is RegexNodeKind.Atomic or RegexNodeKind.Capture) || (node.Kind is RegexNodeKind.Loop or RegexNodeKind.Lazyloop && node.M > 0)) { node = node.Child(0); } - if (node.Type != RegexNode.Concatenate) + if (node.Kind != RegexNodeKind.Concatenate) { return null; } @@ -589,7 +590,7 @@ public static (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Li // could also be made to support Oneloopatomic and Notoneloopatomic, but the scenarios for that are rare. Debug.Assert(node.ChildCount() >= 2); RegexNode firstChild = node.Child(0); - if (firstChild.Type is not (RegexNode.Setloop or RegexNode.Setloopatomic or RegexNode.Setlazy) || firstChild.N != int.MaxValue) + if (firstChild.Kind is not (RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy) || firstChild.N != int.MaxValue) { return null; } @@ -597,7 +598,7 @@ public static (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Li // Get the subsequent node. An UpdateBumpalong may have been added as an optimization, but it doesn't have an // impact on semantics and we can skip it. RegexNode nextChild = node.Child(1); - if (nextChild.Type == RegexNode.UpdateBumpalong) + if (nextChild.Kind == RegexNodeKind.UpdateBumpalong) { if (node.ChildCount() == 2) { @@ -611,15 +612,15 @@ public static (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Li // and they're both case-sensitive, we have a winner. if (((firstChild.Options | nextChild.Options) & RegexOptions.IgnoreCase) == 0) { - switch (nextChild.Type) + switch (nextChild.Kind) { - case RegexNode.One when !RegexCharClass.CharInClass(nextChild.Ch, firstChild.Str!): + case RegexNodeKind.One when !RegexCharClass.CharInClass(nextChild.Ch, firstChild.Str!): return (firstChild, (nextChild.Ch, null, null)); - case RegexNode.Multi when !RegexCharClass.CharInClass(nextChild.Str![0], firstChild.Str!): + case RegexNodeKind.Multi when !RegexCharClass.CharInClass(nextChild.Str![0], firstChild.Str!): return (firstChild, ('\0', nextChild.Str, null)); - case RegexNode.Set when !RegexCharClass.IsNegated(nextChild.Str!): + case RegexNodeKind.Set when !RegexCharClass.IsNegated(nextChild.Str!): Span chars = stackalloc char[5]; // maximum number of chars optimized by IndexOfAny chars = chars.Slice(0, RegexCharClass.GetSetChars(nextChild.Str!, chars)); if (!chars.IsEmpty) @@ -642,94 +643,116 @@ public static (RegexNode LoopNode, (char Char, string? String, char[]? Chars) Li return null; } - /// Takes a RegexTree and computes the leading anchor that it encounters. - public static int FindLeadingAnchor(RegexTree tree) + /// Computes the leading anchor of a node. + public static RegexNodeKind FindLeadingAnchor(RegexNode node) => + FindLeadingOrTrailingAnchor(node, leading: true); + + /// Computes the leading anchor of a node. + public static RegexNodeKind FindTrailingAnchor(RegexNode node) => + FindLeadingOrTrailingAnchor(node, leading: false); + + /// Computes the leading or trailing anchor of a node. + private static RegexNodeKind FindLeadingOrTrailingAnchor(RegexNode node, bool leading) { - RegexNode curNode = tree.Root; - RegexNode? concatNode = null; - int nextChild = 0; + if (!StackHelper.TryEnsureSufficientExecutionStack()) + { + // We only recur for alternations, but with a really deep nesting of alternations we could potentially overflow. + // In such a case, simply stop searching for an anchor. + return RegexNodeKind.Unknown; + } while (true) { - switch (curNode.Type) + switch (node.Kind) { - case RegexNode.Bol: - return Bol; - - case RegexNode.Eol: - return Eol; - - case RegexNode.Boundary: - return Boundary; - - case RegexNode.ECMABoundary: - return ECMABoundary; - - case RegexNode.Beginning: - return Beginning; + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.EndZ: + case RegexNodeKind.End: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: + // Return any anchor found. + return node.Kind; + + case RegexNodeKind.Atomic: + case RegexNodeKind.Capture: + // For groups, continue exploring the sole child. + node = node.Child(0); + continue; - case RegexNode.Start: - return Start; + case RegexNodeKind.Concatenate: + // For concatenations, we expect primarily to explore its first (for leading) or last (for trailing) child, + // but we can also skip over certain kinds of nodes (e.g. Empty), and thus iterate through its children backward + // looking for the last we shouldn't skip. + { + int childCount = node.ChildCount(); + RegexNode? child = null; + if (leading) + { + for (int i = 0; i < childCount; i++) + { + if (node.Child(i).Kind is not (RegexNodeKind.Empty or RegexNodeKind.PositiveLookaround or RegexNodeKind.NegativeLookaround)) + { + child = node.Child(i); + break; + } + } + } + else + { + for (int i = childCount - 1; i >= 0; i--) + { + if (node.Child(i).Kind is not (RegexNodeKind.Empty or RegexNodeKind.PositiveLookaround or RegexNodeKind.NegativeLookaround)) + { + child = node.Child(i); + break; + } + } + } - case RegexNode.EndZ: - return EndZ; + if (child is not null) + { + node = child; + continue; + } - case RegexNode.End: - return End; + goto default; + } - case RegexNode.Concatenate: - if (curNode.ChildCount() > 0) + case RegexNodeKind.Alternate: + // For alternations, every branch needs to lead or trail with the same anchor. { - concatNode = curNode; - nextChild = 0; - } - break; + // Get the leading/trailing anchor of the first branch. If there isn't one, bail. + RegexNodeKind anchor = FindLeadingOrTrailingAnchor(node.Child(0), leading); + if (anchor == RegexNodeKind.Unknown) + { + return RegexNodeKind.Unknown; + } - case RegexNode.Atomic: - case RegexNode.Capture: - curNode = curNode.Child(0); - concatNode = null; - continue; + // Look at each subsequent branch and validate it has the same leading or trailing + // anchor. If any doesn't, bail. + int childCount = node.ChildCount(); + for (int i = 1; i < childCount; i++) + { + if (FindLeadingOrTrailingAnchor(node.Child(i), leading) != anchor) + { + return RegexNodeKind.Unknown; + } + } - case RegexNode.Empty: - case RegexNode.Require: - case RegexNode.Prevent: - break; + // All branches have the same leading/trailing anchor. Return it. + return anchor; + } default: - return 0; + // For everything else, we couldn't find an anchor. + return RegexNodeKind.Unknown; } - - if (concatNode == null || nextChild >= concatNode.ChildCount()) - { - return 0; - } - - curNode = concatNode.Child(nextChild++); } } -#if DEBUG - [ExcludeFromCodeCoverage] - public static string AnchorDescription(int anchors) - { - var sb = new StringBuilder(); - - if ((anchors & Beginning) != 0) sb.Append(", Beginning"); - if ((anchors & Start) != 0) sb.Append(", Start"); - if ((anchors & Bol) != 0) sb.Append(", Bol"); - if ((anchors & Boundary) != 0) sb.Append(", Boundary"); - if ((anchors & ECMABoundary) != 0) sb.Append(", ECMABoundary"); - if ((anchors & Eol) != 0) sb.Append(", Eol"); - if ((anchors & End) != 0) sb.Append(", End"); - if ((anchors & EndZ) != 0) sb.Append(", EndZ"); - - return sb.Length >= 2 ? - sb.ToString(2, sb.Length - 2) : - "None"; - } -#endif - /// /// To avoid recursion, we use a simple integer stack. /// @@ -776,12 +799,12 @@ private RegexFC PopFC() if (curNodeChildCount == 0) { // This is a leaf node - CalculateFC(curNode.Type, curNode, 0); + CalculateFC(curNode.Kind, curNode, 0); } else if (curChild < curNodeChildCount && !_skipAllChildren) { // This is an interior node, and we have more children to analyze - CalculateFC(curNode.Type | BeforeChild, curNode, curChild); + CalculateFC(curNode.Kind | BeforeChild, curNode, curChild); if (!_skipchild) { @@ -806,9 +829,9 @@ private RegexFC PopFC() break; curChild = PopInt(); - curNode = curNode.Next; + curNode = curNode.Parent; - CalculateFC(curNode!.Type | AfterChild, curNode, curChild); + CalculateFC(curNode!.Kind | AfterChild, curNode, curChild); if (_failed) return null; @@ -829,30 +852,30 @@ private RegexFC PopFC() /// /// FC computation and shortcut cases for each node type /// - private void CalculateFC(int NodeType, RegexNode node, int CurIndex) + private void CalculateFC(RegexNodeKind nodeType, RegexNode node, int CurIndex) { bool ci = (node.Options & RegexOptions.IgnoreCase) != 0; bool rtl = (node.Options & RegexOptions.RightToLeft) != 0; - switch (NodeType) + switch (nodeType) { - case RegexNode.Concatenate | BeforeChild: - case RegexNode.Alternate | BeforeChild: - case RegexNode.Testref | BeforeChild: - case RegexNode.Loop | BeforeChild: - case RegexNode.Lazyloop | BeforeChild: + case RegexNodeKind.Concatenate | BeforeChild: + case RegexNodeKind.Alternate | BeforeChild: + case RegexNodeKind.BackreferenceConditional | BeforeChild: + case RegexNodeKind.Loop | BeforeChild: + case RegexNodeKind.Lazyloop | BeforeChild: break; - case RegexNode.Testgroup | BeforeChild: + case RegexNodeKind.ExpressionConditional | BeforeChild: if (CurIndex == 0) SkipChild(); break; - case RegexNode.Empty: + case RegexNodeKind.Empty: PushFC(new RegexFC(true)); break; - case RegexNode.Concatenate | AfterChild: + case RegexNodeKind.Concatenate | AfterChild: if (CurIndex != 0) { RegexFC child = PopFC(); @@ -865,7 +888,7 @@ private void CalculateFC(int NodeType, RegexNode node, int CurIndex) _skipAllChildren = true; break; - case RegexNode.Testgroup | AfterChild: + case RegexNodeKind.ExpressionConditional | AfterChild: if (CurIndex > 1) { RegexFC child = PopFC(); @@ -875,8 +898,8 @@ private void CalculateFC(int NodeType, RegexNode node, int CurIndex) } break; - case RegexNode.Alternate | AfterChild: - case RegexNode.Testref | AfterChild: + case RegexNodeKind.Alternate | AfterChild: + case RegexNodeKind.BackreferenceConditional | AfterChild: if (CurIndex != 0) { RegexFC child = PopFC(); @@ -886,48 +909,48 @@ private void CalculateFC(int NodeType, RegexNode node, int CurIndex) } break; - case RegexNode.Loop | AfterChild: - case RegexNode.Lazyloop | AfterChild: + case RegexNodeKind.Loop | AfterChild: + case RegexNodeKind.Lazyloop | AfterChild: if (node.M == 0) TopFC()._nullable = true; break; - case RegexNode.Group | BeforeChild: - case RegexNode.Group | AfterChild: - case RegexNode.Capture | BeforeChild: - case RegexNode.Capture | AfterChild: - case RegexNode.Atomic | BeforeChild: - case RegexNode.Atomic | AfterChild: + case RegexNodeKind.Group | BeforeChild: + case RegexNodeKind.Group | AfterChild: + case RegexNodeKind.Capture | BeforeChild: + case RegexNodeKind.Capture | AfterChild: + case RegexNodeKind.Atomic | BeforeChild: + case RegexNodeKind.Atomic | AfterChild: break; - case RegexNode.Require | BeforeChild: - case RegexNode.Prevent | BeforeChild: + case RegexNodeKind.PositiveLookaround | BeforeChild: + case RegexNodeKind.NegativeLookaround | BeforeChild: SkipChild(); PushFC(new RegexFC(true)); break; - case RegexNode.Require | AfterChild: - case RegexNode.Prevent | AfterChild: + case RegexNodeKind.PositiveLookaround | AfterChild: + case RegexNodeKind.NegativeLookaround | AfterChild: break; - case RegexNode.One: - case RegexNode.Notone: - PushFC(new RegexFC(node.Ch, NodeType == RegexNode.Notone, false, ci)); + case RegexNodeKind.One: + case RegexNodeKind.Notone: + PushFC(new RegexFC(node.Ch, nodeType == RegexNodeKind.Notone, false, ci)); break; - case RegexNode.Oneloop: - case RegexNode.Oneloopatomic: - case RegexNode.Onelazy: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Onelazy: PushFC(new RegexFC(node.Ch, false, node.M == 0, ci)); break; - case RegexNode.Notoneloop: - case RegexNode.Notoneloopatomic: - case RegexNode.Notonelazy: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Notonelazy: PushFC(new RegexFC(node.Ch, true, node.M == 0, ci)); break; - case RegexNode.Multi: + case RegexNodeKind.Multi: if (node.Str!.Length == 0) PushFC(new RegexFC(true)); else if (!rtl) @@ -936,37 +959,38 @@ private void CalculateFC(int NodeType, RegexNode node, int CurIndex) PushFC(new RegexFC(node.Str[node.Str.Length - 1], false, false, ci)); break; - case RegexNode.Set: + case RegexNodeKind.Set: PushFC(new RegexFC(node.Str!, false, ci)); break; - case RegexNode.Setloop: - case RegexNode.Setloopatomic: - case RegexNode.Setlazy: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Setlazy: PushFC(new RegexFC(node.Str!, node.M == 0, ci)); break; - case RegexNode.Ref: + case RegexNodeKind.Backreference: PushFC(new RegexFC(RegexCharClass.AnyClass, true, false)); break; - case RegexNode.Nothing: - case RegexNode.Bol: - case RegexNode.Eol: - case RegexNode.Boundary: - case RegexNode.NonBoundary: - case RegexNode.ECMABoundary: - case RegexNode.NonECMABoundary: - case RegexNode.Beginning: - case RegexNode.Start: - case RegexNode.EndZ: - case RegexNode.End: - case RegexNode.UpdateBumpalong: + case RegexNodeKind.Nothing: + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.Boundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.EndZ: + case RegexNodeKind.End: + case RegexNodeKind.UpdateBumpalong: PushFC(new RegexFC(true)); break; default: - throw new ArgumentException(SR.Format(SR.UnexpectedOpcode, NodeType.ToString(CultureInfo.CurrentCulture))); + Debug.Fail($"Unexpected node: {nodeType}"); + break; } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexReplacement.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexReplacement.cs index 814f05e5aeb11..2027763780d2c 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexReplacement.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexReplacement.cs @@ -31,7 +31,7 @@ internal sealed class RegexReplacement /// public RegexReplacement(string rep, RegexNode concat, Hashtable _caps) { - if (concat.Type != RegexNode.Concatenate) + if (concat.Kind != RegexNodeKind.Concatenate) { throw ThrowHelper.CreateArgumentException(ExceptionResource.ReplacementError); } @@ -47,17 +47,17 @@ public RegexReplacement(string rep, RegexNode concat, Hashtable _caps) { RegexNode child = concat.Child(i); - switch (child.Type) + switch (child.Kind) { - case RegexNode.Multi: + case RegexNodeKind.Multi: vsb.Append(child.Str!); break; - case RegexNode.One: + case RegexNodeKind.One: vsb.Append(child.Ch); break; - case RegexNode.Ref: + case RegexNodeKind.Backreference: if (vsb.Length > 0) { rules.Append(strings.Length); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexRunner.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexRunner.cs index 15f33145b7983..13a9fbf155bb1 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexRunner.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexRunner.cs @@ -145,16 +145,10 @@ protected RegexRunner() { } bool initialized = false; while (true) { + // Find the next potential location for a match in the input. #if DEBUG - if (regex.IsDebug) - { - Debug.WriteLine(""); - Debug.WriteLine($"Search range: from {runtextbeg} to {runtextend}"); - Debug.WriteLine($"Firstchar search starting at {runtextpos} stopping at {stoppos}"); - } + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Calling FindFirstChar at {nameof(runtextbeg)}={runtextbeg}, {nameof(runtextpos)}={runtextpos}, {nameof(runtextend)}={runtextend}"); #endif - - // Find the next potential location for a match in the input. if (FindFirstChar()) { if (!ignoreTimeout) @@ -170,15 +164,10 @@ protected RegexRunner() { } initialized = true; } + // See if there's a match at this position. #if DEBUG - if (regex.IsDebug) - { - Debug.WriteLine($"Executing engine starting at {runtextpos}"); - Debug.WriteLine(""); - } + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Calling Go at {nameof(runtextpos)}={runtextpos}"); #endif - - // See if there's a match at this position. Go(); // If we got a match, we're done. @@ -264,16 +253,10 @@ internal void ScanInternal(Regex regex, string text, int textstart, ref bool initialized = false; while (true) { + // Find the next potential location for a match in the input. #if DEBUG - if (regex.IsDebug) - { - Debug.WriteLine(""); - Debug.WriteLine($"Search range: from {runtextbeg} to {runtextend}"); - Debug.WriteLine($"Firstchar search starting at {runtextpos} stopping at {stoppos}"); - } + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Calling FindFirstChar at {nameof(runtextbeg)}={runtextbeg}, {nameof(runtextpos)}={runtextpos}, {nameof(runtextend)}={runtextend}"); #endif - - // Find the next potential location for a match in the input. if (FindFirstChar()) { if (!ignoreTimeout) @@ -290,11 +273,7 @@ internal void ScanInternal(Regex regex, string text, int textstart, ref } #if DEBUG - if (regex.IsDebug) - { - Debug.WriteLine($"Executing engine starting at {runtextpos}"); - Debug.WriteLine(""); - } + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Calling Go at {nameof(runtextpos)}={runtextpos}"); #endif // See if there's a match at this position. @@ -406,19 +385,6 @@ private void DoCheckTimeout() if (0 > _timeoutOccursAt && 0 < currentMillis) return; -#if DEBUG - if (runregex!.IsDebug) - { - Debug.WriteLine(""); - Debug.WriteLine("RegEx match timeout occurred!"); - Debug.WriteLine($"Specified timeout: {TimeSpan.FromMilliseconds(_timeout)}"); - Debug.WriteLine($"Timeout check frequency: {TimeoutCheckFrequency}"); - Debug.WriteLine($"Search pattern: {runregex.pattern}"); - Debug.WriteLine($"Input: {runtext}"); - Debug.WriteLine("About to throw RegexMatchTimeoutException."); - } -#endif - throw new RegexMatchTimeoutException(runtext!, runregex!.pattern!, TimeSpan.FromMilliseconds(_timeout)); } @@ -714,81 +680,77 @@ protected int MatchLength(int cap) /// Dump the current state /// [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal virtual void DumpState() - { - Debug.WriteLine($"Text: {TextposDescription()}"); - Debug.WriteLine($"Track: {StackDescription(runtrack!, runtrackpos)}"); - Debug.WriteLine($"Stack: {StackDescription(runstack!, runstackpos)}"); - } - - [ExcludeFromCodeCoverage(Justification = "Debug only")] - private static string StackDescription(int[] a, int index) + internal virtual void DebugTraceCurrentState() { - var sb = new StringBuilder(); - - sb.Append(a.Length - index); - sb.Append('/'); - sb.Append(a.Length); + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Text: {DescribeTextPosition()}"); + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Track: {DescribeStack(runtrack!, runtrackpos)}"); + Debug.WriteLineIf(Regex.EnableDebugTracing, $"Stack: {DescribeStack(runstack!, runstackpos)}"); - if (sb.Length < 8) + string DescribeTextPosition() { - sb.Append(' ', 8 - sb.Length); - } + var sb = new StringBuilder(); - sb.Append('('); + sb.Append(runtextpos); - for (int i = index; i < a.Length; i++) - { - if (i > index) + if (sb.Length < 8) { - sb.Append(' '); + sb.Append(' ', 8 - sb.Length); } - sb.Append(a[i]); - } - - sb.Append(')'); - return sb.ToString(); - } + if (runtextpos > runtextbeg) + { + sb.Append(RegexCharClass.DescribeChar(runtext![runtextpos - 1])); + } + else + { + sb.Append('^'); + } - [ExcludeFromCodeCoverage(Justification = "Debug only")] - internal virtual string TextposDescription() - { - var sb = new StringBuilder(); + sb.Append('>'); - sb.Append(runtextpos); + for (int i = runtextpos; i < runtextend; i++) + { + sb.Append(RegexCharClass.DescribeChar(runtext![i])); + } + if (sb.Length >= 64) + { + sb.Length = 61; + sb.Append("..."); + } + else + { + sb.Append('$'); + } - if (sb.Length < 8) - { - sb.Append(' ', 8 - sb.Length); + return sb.ToString(); } - if (runtextpos > runtextbeg) - { - sb.Append(RegexCharClass.CharDescription(runtext![runtextpos - 1])); - } - else + static string DescribeStack(int[] stack, int index) { - sb.Append('^'); - } + var sb = new StringBuilder(); - sb.Append('>'); + sb.Append(stack.Length - index).Append('/').Append(stack.Length); - for (int i = runtextpos; i < runtextend; i++) - { - sb.Append(RegexCharClass.CharDescription(runtext![i])); - } - if (sb.Length >= 64) - { - sb.Length = 61; - sb.Append("..."); - } - else - { - sb.Append('$'); - } + if (sb.Length < 8) + { + sb.Append(' ', 8 - sb.Length); + } - return sb.ToString(); + sb.Append('('); + + for (int i = index; i < stack.Length; i++) + { + if (i > index) + { + sb.Append(' '); + } + sb.Append(stack[i]); + } + + sb.Append(')'); + + return sb.ToString(); + } } #endif } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexTree.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexTree.cs index c86d8f54c0337..2394cddeeecf7 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexTree.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexTree.cs @@ -1,14 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// RegexTree is just a wrapper for a node tree with some -// global information attached. - using System.Collections; -using System.Diagnostics.CodeAnalysis; namespace System.Text.RegularExpressions { + /// Wrapper for a node tree with additional information attached. internal sealed class RegexTree { public readonly RegexNode Root; @@ -31,16 +28,5 @@ internal RegexTree(RegexNode root, Hashtable caps, int[] capNumList, int capTop, Options = options; MinRequiredLength = minRequiredLength; } - -#if DEBUG - [ExcludeFromCodeCoverage] - public void Dump() => Root.Dump(); - - [ExcludeFromCodeCoverage] - public override string ToString() => Root.ToString(); - - [ExcludeFromCodeCoverage] - public bool Debug => (Options & RegexOptions.Debug) != 0; -#endif } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs index d3caec254a94f..9fc977fce9587 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; @@ -12,8 +13,8 @@ namespace System.Text.RegularExpressions internal ref struct RegexWriter { // These must be unused RegexNode type bits. - private const int BeforeChild = 64; - private const int AfterChild = 128; + private const RegexNodeKind BeforeChild = (RegexNodeKind)64; + private const RegexNodeKind AfterChild = (RegexNodeKind)128; // Distribution of common patterns indicates an average amount of 56 op codes. Since we're stackalloc'ing, // we can afford to make it a bit higher and a power of two for simplicity. @@ -26,6 +27,14 @@ internal ref struct RegexWriter private Hashtable? _caps; private int _trackCount; +#if DEBUG + static RegexWriter() + { + Debug.Assert(!Enum.IsDefined(typeof(RegexNodeKind), BeforeChild)); + Debug.Assert(!Enum.IsDefined(typeof(RegexNodeKind), AfterChild)); + } +#endif + private RegexWriter(Span emittedSpan, Span intStackSpan) { _emitted = new ValueListBuilder(emittedSpan); @@ -37,23 +46,12 @@ private RegexWriter(Span emittedSpan, Span intStackSpan) /// /// This is the only function that should be called from outside. - /// It takes a RegexTree and creates a corresponding RegexCode. + /// It takes a and creates a corresponding . /// public static RegexCode Write(RegexTree tree, CultureInfo culture) { - var writer = new RegexWriter(stackalloc int[EmittedSize], stackalloc int[IntStackSize]); - RegexCode code = writer.RegexCodeFromRegexTree(tree, culture); - writer.Dispose(); - -#if DEBUG - if (tree.Debug) - { - tree.Dump(); - code.Dump(); - } -#endif - - return code; + using var writer = new RegexWriter(stackalloc int[EmittedSize], stackalloc int[IntStackSize]); + return writer.RegexCodeFromRegexTree(tree, culture); } /// @@ -93,7 +91,7 @@ public RegexCode RegexCodeFromRegexTree(RegexTree tree, CultureInfo culture) // Every written code begins with a lazy branch. This will be back-patched // to point to the ending Stop after the whole expression has been written. - Emit(RegexCode.Lazybranch, 0); + Emit(RegexOpcode.Lazybranch, 0); // Emit every node. RegexNode curNode = tree.Root; @@ -103,11 +101,11 @@ public RegexCode RegexCodeFromRegexTree(RegexTree tree, CultureInfo culture) int curNodeChildCount = curNode.ChildCount(); if (curNodeChildCount == 0) { - EmitFragment(curNode.Type, curNode, 0); + EmitFragment(curNode.Kind, curNode, 0); } else if (curChild < curNodeChildCount) { - EmitFragment(curNode.Type | BeforeChild, curNode, curChild); + EmitFragment(curNode.Kind | BeforeChild, curNode, curChild); curNode = curNode.Child(curChild); _intStack.Append(curChild); @@ -121,15 +119,15 @@ public RegexCode RegexCodeFromRegexTree(RegexTree tree, CultureInfo culture) } curChild = _intStack.Pop(); - curNode = curNode.Next!; + curNode = curNode.Parent!; - EmitFragment(curNode.Type | AfterChild, curNode, curChild); + EmitFragment(curNode.Kind | AfterChild, curNode, curChild); curChild++; } // Patch the starting Lazybranch, emit the final Stop, and get the resulting code array. PatchJump(0, _emitted.Length); - Emit(RegexCode.Stop); + Emit(RegexOpcode.Stop); int[] emitted = _emitted.AsSpan().ToArray(); // Convert the string table into an ordered string array. @@ -157,37 +155,37 @@ private void PatchJump(int offset, int jumpDest) /// functions all run in two modes: they can emit code, or /// they can just count the size of the code. /// - private void Emit(int op) + private void Emit(RegexOpcode op) { if (RegexCode.OpcodeBacktracks(op)) { _trackCount++; } - _emitted.Append(op); + _emitted.Append((int)op); } /// Emits a one-argument operation. - private void Emit(int op, int opd1) + private void Emit(RegexOpcode op, int opd1) { if (RegexCode.OpcodeBacktracks(op)) { _trackCount++; } - _emitted.Append(op); + _emitted.Append((int)op); _emitted.Append(opd1); } /// Emits a two-argument operation. - private void Emit(int op, int opd1, int opd2) + private void Emit(RegexOpcode op, int opd1, int opd2) { if (RegexCode.OpcodeBacktracks(op)) { _trackCount++; } - _emitted.Append(op); + _emitted.Append((int)op); _emitted.Append(opd1); _emitted.Append(opd2); } @@ -219,40 +217,40 @@ private int StringCode(string str) /// through the tree and calls EmitFragment to emits code before /// and after each child of an interior node, and at each leaf. /// - private void EmitFragment(int nodetype, RegexNode node, int curIndex) + private void EmitFragment(RegexNodeKind nodeType, RegexNode node, int curIndex) { - int bits = 0; + RegexOpcode bits = 0; if ((node.Options & RegexOptions.RightToLeft) != 0) { - bits |= RegexCode.Rtl; + bits |= RegexOpcode.RightToLeft; } if ((node.Options & RegexOptions.IgnoreCase) != 0) { - bits |= RegexCode.Ci; + bits |= RegexOpcode.CaseInsensitive; } - switch (nodetype) + switch (nodeType) { - case RegexNode.Concatenate | BeforeChild: - case RegexNode.Concatenate | AfterChild: - case RegexNode.Empty: + case RegexNodeKind.Concatenate | BeforeChild: + case RegexNodeKind.Concatenate | AfterChild: + case RegexNodeKind.Empty: break; - case RegexNode.Alternate | BeforeChild: + case RegexNodeKind.Alternate | BeforeChild: if (curIndex < node.ChildCount() - 1) { _intStack.Append(_emitted.Length); - Emit(RegexCode.Lazybranch, 0); + Emit(RegexOpcode.Lazybranch, 0); } break; - case RegexNode.Alternate | AfterChild: + case RegexNodeKind.Alternate | AfterChild: { if (curIndex < node.ChildCount() - 1) { int lazyBranchPos = _intStack.Pop(); _intStack.Append(_emitted.Length); - Emit(RegexCode.Goto, 0); + Emit(RegexOpcode.Goto, 0); PatchJump(lazyBranchPos, _emitted.Length); } else @@ -265,29 +263,29 @@ private void EmitFragment(int nodetype, RegexNode node, int curIndex) break; } - case RegexNode.Testref | BeforeChild: + case RegexNodeKind.BackreferenceConditional | BeforeChild: switch (curIndex) { case 0: - Emit(RegexCode.Setjump); + Emit(RegexOpcode.Setjump); _intStack.Append(_emitted.Length); - Emit(RegexCode.Lazybranch, 0); - Emit(RegexCode.Testref, RegexParser.MapCaptureNumber(node.M, _caps)); - Emit(RegexCode.Forejump); + Emit(RegexOpcode.Lazybranch, 0); + Emit(RegexOpcode.TestBackreference, RegexParser.MapCaptureNumber(node.M, _caps)); + Emit(RegexOpcode.Forejump); break; } break; - case RegexNode.Testref | AfterChild: + case RegexNodeKind.BackreferenceConditional | AfterChild: switch (curIndex) { case 0: { int Branchpos = _intStack.Pop(); _intStack.Append(_emitted.Length); - Emit(RegexCode.Goto, 0); + Emit(RegexOpcode.Goto, 0); PatchJump(Branchpos, _emitted.Length); - Emit(RegexCode.Forejump); + Emit(RegexOpcode.Forejump); break; } case 1: @@ -296,32 +294,32 @@ private void EmitFragment(int nodetype, RegexNode node, int curIndex) } break; - case RegexNode.Testgroup | BeforeChild: + case RegexNodeKind.ExpressionConditional | BeforeChild: switch (curIndex) { case 0: - Emit(RegexCode.Setjump); - Emit(RegexCode.Setmark); + Emit(RegexOpcode.Setjump); + Emit(RegexOpcode.Setmark); _intStack.Append(_emitted.Length); - Emit(RegexCode.Lazybranch, 0); + Emit(RegexOpcode.Lazybranch, 0); break; } break; - case RegexNode.Testgroup | AfterChild: + case RegexNodeKind.ExpressionConditional | AfterChild: switch (curIndex) { case 0: - Emit(RegexCode.Getmark); - Emit(RegexCode.Forejump); + Emit(RegexOpcode.Getmark); + Emit(RegexOpcode.Forejump); break; case 1: int Branchpos = _intStack.Pop(); _intStack.Append(_emitted.Length); - Emit(RegexCode.Goto, 0); + Emit(RegexOpcode.Goto, 0); PatchJump(Branchpos, _emitted.Length); - Emit(RegexCode.Getmark); - Emit(RegexCode.Forejump); + Emit(RegexOpcode.Getmark); + Emit(RegexOpcode.Forejump); break; case 2: PatchJump(_intStack.Pop(), _emitted.Length); @@ -329,147 +327,148 @@ private void EmitFragment(int nodetype, RegexNode node, int curIndex) } break; - case RegexNode.Loop | BeforeChild: - case RegexNode.Lazyloop | BeforeChild: + case RegexNodeKind.Loop | BeforeChild: + case RegexNodeKind.Lazyloop | BeforeChild: if (node.N < int.MaxValue || node.M > 1) - Emit(node.M == 0 ? RegexCode.Nullcount : RegexCode.Setcount, node.M == 0 ? 0 : 1 - node.M); + Emit(node.M == 0 ? RegexOpcode.Nullcount : RegexOpcode.Setcount, node.M == 0 ? 0 : 1 - node.M); else - Emit(node.M == 0 ? RegexCode.Nullmark : RegexCode.Setmark); + Emit(node.M == 0 ? RegexOpcode.Nullmark : RegexOpcode.Setmark); if (node.M == 0) { _intStack.Append(_emitted.Length); - Emit(RegexCode.Goto, 0); + Emit(RegexOpcode.Goto, 0); } _intStack.Append(_emitted.Length); break; - case RegexNode.Loop | AfterChild: - case RegexNode.Lazyloop | AfterChild: + case RegexNodeKind.Loop | AfterChild: + case RegexNodeKind.Lazyloop | AfterChild: { int StartJumpPos = _emitted.Length; - int Lazy = (nodetype - (RegexNode.Loop | AfterChild)); + int Lazy = (nodeType - (RegexNodeKind.Loop | AfterChild)); if (node.N < int.MaxValue || node.M > 1) - Emit(RegexCode.Branchcount + Lazy, _intStack.Pop(), node.N == int.MaxValue ? int.MaxValue : node.N - node.M); + Emit(RegexOpcode.Branchcount + Lazy, _intStack.Pop(), node.N == int.MaxValue ? int.MaxValue : node.N - node.M); else - Emit(RegexCode.Branchmark + Lazy, _intStack.Pop()); + Emit(RegexOpcode.Branchmark + Lazy, _intStack.Pop()); if (node.M == 0) PatchJump(_intStack.Pop(), StartJumpPos); } break; - case RegexNode.Group | BeforeChild: - case RegexNode.Group | AfterChild: + case RegexNodeKind.Group | BeforeChild: + case RegexNodeKind.Group | AfterChild: break; - case RegexNode.Capture | BeforeChild: - Emit(RegexCode.Setmark); + case RegexNodeKind.Capture | BeforeChild: + Emit(RegexOpcode.Setmark); break; - case RegexNode.Capture | AfterChild: - Emit(RegexCode.Capturemark, RegexParser.MapCaptureNumber(node.M, _caps), RegexParser.MapCaptureNumber(node.N, _caps)); + case RegexNodeKind.Capture | AfterChild: + Emit(RegexOpcode.Capturemark, RegexParser.MapCaptureNumber(node.M, _caps), RegexParser.MapCaptureNumber(node.N, _caps)); break; - case RegexNode.Require | BeforeChild: - Emit(RegexCode.Setjump); // causes lookahead/lookbehind to be non-backtracking - Emit(RegexCode.Setmark); + case RegexNodeKind.PositiveLookaround | BeforeChild: + Emit(RegexOpcode.Setjump); // causes lookahead/lookbehind to be non-backtracking + Emit(RegexOpcode.Setmark); break; - case RegexNode.Require | AfterChild: - Emit(RegexCode.Getmark); - Emit(RegexCode.Forejump); // causes lookahead/lookbehind to be non-backtracking + case RegexNodeKind.PositiveLookaround | AfterChild: + Emit(RegexOpcode.Getmark); + Emit(RegexOpcode.Forejump); // causes lookahead/lookbehind to be non-backtracking break; - case RegexNode.Prevent | BeforeChild: - Emit(RegexCode.Setjump); + case RegexNodeKind.NegativeLookaround | BeforeChild: + Emit(RegexOpcode.Setjump); _intStack.Append(_emitted.Length); - Emit(RegexCode.Lazybranch, 0); + Emit(RegexOpcode.Lazybranch, 0); break; - case RegexNode.Prevent | AfterChild: - Emit(RegexCode.Backjump); + case RegexNodeKind.NegativeLookaround | AfterChild: + Emit(RegexOpcode.Backjump); PatchJump(_intStack.Pop(), _emitted.Length); - Emit(RegexCode.Forejump); + Emit(RegexOpcode.Forejump); break; - case RegexNode.Atomic | BeforeChild: - Emit(RegexCode.Setjump); + case RegexNodeKind.Atomic | BeforeChild: + Emit(RegexOpcode.Setjump); break; - case RegexNode.Atomic | AfterChild: - Emit(RegexCode.Forejump); + case RegexNodeKind.Atomic | AfterChild: + Emit(RegexOpcode.Forejump); break; - case RegexNode.One: - case RegexNode.Notone: - Emit(node.Type | bits, node.Ch); + case RegexNodeKind.One: + case RegexNodeKind.Notone: + Emit((RegexOpcode)node.Kind | bits, node.Ch); break; - case RegexNode.Notoneloop: - case RegexNode.Notoneloopatomic: - case RegexNode.Notonelazy: - case RegexNode.Oneloop: - case RegexNode.Oneloopatomic: - case RegexNode.Onelazy: + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notoneloopatomic: + case RegexNodeKind.Notonelazy: + case RegexNodeKind.Oneloop: + case RegexNodeKind.Oneloopatomic: + case RegexNodeKind.Onelazy: if (node.M > 0) { - Emit(((node.Type == RegexNode.Oneloop || node.Type == RegexNode.Oneloopatomic || node.Type == RegexNode.Onelazy) ? - RegexCode.Onerep : RegexCode.Notonerep) | bits, node.Ch, node.M); + Emit(((node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy) ? + RegexOpcode.Onerep : RegexOpcode.Notonerep) | bits, node.Ch, node.M); } if (node.N > node.M) { - Emit(node.Type | bits, node.Ch, node.N == int.MaxValue ? int.MaxValue : node.N - node.M); + Emit((RegexOpcode)node.Kind | bits, node.Ch, node.N == int.MaxValue ? int.MaxValue : node.N - node.M); } break; - case RegexNode.Setloop: - case RegexNode.Setloopatomic: - case RegexNode.Setlazy: + case RegexNodeKind.Setloop: + case RegexNodeKind.Setloopatomic: + case RegexNodeKind.Setlazy: { int stringCode = StringCode(node.Str!); if (node.M > 0) { - Emit(RegexCode.Setrep | bits, stringCode, node.M); + Emit(RegexOpcode.Setrep | bits, stringCode, node.M); } if (node.N > node.M) { - Emit(node.Type | bits, stringCode, (node.N == int.MaxValue) ? int.MaxValue : node.N - node.M); + Emit((RegexOpcode)node.Kind | bits, stringCode, (node.N == int.MaxValue) ? int.MaxValue : node.N - node.M); } } break; - case RegexNode.Multi: - Emit(node.Type | bits, StringCode(node.Str!)); + case RegexNodeKind.Multi: + Emit((RegexOpcode)node.Kind | bits, StringCode(node.Str!)); break; - case RegexNode.Set: - Emit(node.Type | bits, StringCode(node.Str!)); + case RegexNodeKind.Set: + Emit((RegexOpcode)node.Kind | bits, StringCode(node.Str!)); break; - case RegexNode.Ref: - Emit(node.Type | bits, RegexParser.MapCaptureNumber(node.M, _caps)); + case RegexNodeKind.Backreference: + Emit((RegexOpcode)node.Kind | bits, RegexParser.MapCaptureNumber(node.M, _caps)); break; - case RegexNode.Nothing: - case RegexNode.Bol: - case RegexNode.Eol: - case RegexNode.Boundary: - case RegexNode.NonBoundary: - case RegexNode.ECMABoundary: - case RegexNode.NonECMABoundary: - case RegexNode.Beginning: - case RegexNode.Start: - case RegexNode.EndZ: - case RegexNode.End: - case RegexNode.UpdateBumpalong: - Emit(node.Type); + case RegexNodeKind.Nothing: + case RegexNodeKind.Bol: + case RegexNodeKind.Eol: + case RegexNodeKind.Boundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.ECMABoundary: + case RegexNodeKind.NonECMABoundary: + case RegexNodeKind.Beginning: + case RegexNodeKind.Start: + case RegexNodeKind.EndZ: + case RegexNodeKind.End: + case RegexNodeKind.UpdateBumpalong: + Emit((RegexOpcode)node.Kind); break; default: - throw new ArgumentException(SR.Format(SR.UnexpectedOpcode, nodetype.ToString())); + Debug.Fail($"Unexpected node: {nodeType}"); + break; } } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/RegexNodeToSymbolicConverter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/RegexNodeToSymbolicConverter.cs index 6c299578983d7..cdafb9114882a 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/RegexNodeToSymbolicConverter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/RegexNodeToSymbolicConverter.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.Runtime.CompilerServices; using System.Threading; namespace System.Text.RegularExpressions.Symbolic @@ -212,9 +211,9 @@ public SymbolicRegexNode Convert(RegexNode node, bool topLevel) return StackHelper.CallOnEmptyStack(Convert, node, topLevel); } - switch (node.Type) + switch (node.Kind) { - case RegexNode.Alternate: + case RegexNodeKind.Alternate: { var nested = new SymbolicRegexNode[node.ChildCount()]; for (int i = 0; i < nested.Length; i++) @@ -224,17 +223,17 @@ public SymbolicRegexNode Convert(RegexNode node, bool topLevel) return _builder.MkOr(nested); } - case RegexNode.Beginning: + case RegexNodeKind.Beginning: return _builder._startAnchor; - case RegexNode.Bol: + case RegexNodeKind.Bol: EnsureNewlinePredicateInitialized(); return _builder._bolAnchor; - case RegexNode.Capture when node.N == -1: + case RegexNodeKind.Capture when node.N == -1: return Convert(node.Child(0), topLevel); // treat as non-capturing group (...) - case RegexNode.Concatenate: + case RegexNodeKind.Concatenate: { List nested = FlattenNestedConcatenations(node); var converted = new SymbolicRegexNode[nested.Count]; @@ -245,68 +244,68 @@ public SymbolicRegexNode Convert(RegexNode node, bool topLevel) return _builder.MkConcat(converted, topLevel); } - case RegexNode.Empty: - case RegexNode.UpdateBumpalong: // optional directive that behaves the same as Empty + case RegexNodeKind.Empty: + case RegexNodeKind.UpdateBumpalong: // optional directive that behaves the same as Empty return _builder._epsilon; - case RegexNode.End: // \z anchor + case RegexNodeKind.End: // \z anchor return _builder._endAnchor; - case RegexNode.EndZ: // \Z anchor + case RegexNodeKind.EndZ: // \Z anchor EnsureNewlinePredicateInitialized(); return _builder._endAnchorZ; - case RegexNode.Eol: + case RegexNodeKind.Eol: EnsureNewlinePredicateInitialized(); return _builder._eolAnchor; - case RegexNode.Loop: + case RegexNodeKind.Loop: return _builder.MkLoop(Convert(node.Child(0), topLevel: false), isLazy: false, node.M, node.N); - case RegexNode.Lazyloop: + case RegexNodeKind.Lazyloop: return _builder.MkLoop(Convert(node.Child(0), topLevel: false), isLazy: true, node.M, node.N); - case RegexNode.Multi: + case RegexNodeKind.Multi: return ConvertMulti(node, topLevel); - case RegexNode.Notone: + case RegexNodeKind.Notone: return _builder.MkSingleton(Solver.Not(Solver.CharConstraint(node.Ch, (node.Options & RegexOptions.IgnoreCase) != 0, _culture.Name))); - case RegexNode.Notoneloop: - case RegexNode.Notonelazy: - return ConvertNotoneloop(node, node.Type == RegexNode.Notonelazy); + case RegexNodeKind.Notoneloop: + case RegexNodeKind.Notonelazy: + return ConvertNotoneloop(node, node.Kind == RegexNodeKind.Notonelazy); - case RegexNode.One: + case RegexNodeKind.One: return _builder.MkSingleton(Solver.CharConstraint(node.Ch, (node.Options & RegexOptions.IgnoreCase) != 0, _culture.Name)); - case RegexNode.Oneloop: - case RegexNode.Onelazy: - return ConvertOneloop(node, node.Type == RegexNode.Onelazy); + case RegexNodeKind.Oneloop: + case RegexNodeKind.Onelazy: + return ConvertOneloop(node, node.Kind == RegexNodeKind.Onelazy); - case RegexNode.Set: + case RegexNodeKind.Set: return ConvertSet(node); - case RegexNode.Setloop: - case RegexNode.Setlazy: - return ConvertSetloop(node, node.Type == RegexNode.Setlazy); + case RegexNodeKind.Setloop: + case RegexNodeKind.Setlazy: + return ConvertSetloop(node, node.Kind == RegexNodeKind.Setlazy); // TBD: ECMA case intersect predicate with ascii range ? - case RegexNode.Boundary: - case RegexNode.ECMABoundary: + case RegexNodeKind.Boundary: + case RegexNodeKind.ECMABoundary: EnsureWordLetterPredicateInitialized(); return _builder._wbAnchor; // TBD: ECMA case intersect predicate with ascii range ? - case RegexNode.NonBoundary: - case RegexNode.NonECMABoundary: + case RegexNodeKind.NonBoundary: + case RegexNodeKind.NonECMABoundary: EnsureWordLetterPredicateInitialized(); return _builder._nwbAnchor; - case RegexNode.Nothing: + case RegexNodeKind.Nothing: return _builder._nothing; #if DEBUG - case RegexNode.Testgroup: + case RegexNodeKind.ExpressionConditional: // Try to extract the special case representing complement or intersection if (IsComplementedNode(node)) { @@ -327,19 +326,19 @@ public SymbolicRegexNode Convert(RegexNode node, bool topLevel) #endif default: - throw new NotSupportedException(SR.Format(SR.NotSupported_NonBacktrackingConflictingExpression, node.Type switch + throw new NotSupportedException(SR.Format(SR.NotSupported_NonBacktrackingConflictingExpression, node.Kind switch { - RegexNode.Capture => SR.ExpressionDescription_BalancingGroup, - RegexNode.Testgroup => SR.ExpressionDescription_IfThenElse, - RegexNode.Ref => SR.ExpressionDescription_Backreference, - RegexNode.Testref => SR.ExpressionDescription_Conditional, - RegexNode.Require => SR.ExpressionDescription_PositiveLookaround, - RegexNode.Prevent => SR.ExpressionDescription_NegativeLookaround, - RegexNode.Start => SR.ExpressionDescription_ContiguousMatches, - RegexNode.Atomic or - RegexNode.Setloopatomic or - RegexNode.Oneloopatomic or - RegexNode.Notoneloopatomic => SR.ExpressionDescription_AtomicSubexpressions, + RegexNodeKind.Capture => SR.ExpressionDescription_BalancingGroup, + RegexNodeKind.ExpressionConditional => SR.ExpressionDescription_IfThenElse, + RegexNodeKind.Backreference => SR.ExpressionDescription_Backreference, + RegexNodeKind.BackreferenceConditional => SR.ExpressionDescription_Conditional, + RegexNodeKind.PositiveLookaround => SR.ExpressionDescription_PositiveLookaround, + RegexNodeKind.NegativeLookaround => SR.ExpressionDescription_NegativeLookaround, + RegexNodeKind.Start => SR.ExpressionDescription_ContiguousMatches, + RegexNodeKind.Atomic or + RegexNodeKind.Setloopatomic or + RegexNodeKind.Oneloopatomic or + RegexNodeKind.Notoneloopatomic => SR.ExpressionDescription_AtomicSubexpressions, _ => UnexpectedNodeType(node) })); @@ -347,7 +346,7 @@ static string UnexpectedNodeType(RegexNode node) { // The default should never arise, since other node types are either supported // or have been removed (e.g. Group) from the final parse tree. - string description = $"Unexpected node type ({nameof(RegexNode)}:{node.Type})"; + string description = $"Unexpected node type ({nameof(RegexNode)}:{node.Kind})"; Debug.Fail(description); return description; } @@ -381,7 +380,7 @@ List FlattenNestedConcatenations(RegexNode concat) while (todo.TryPop(out RegexNode? node)) { - if (node.Type == RegexNode.Concatenate) + if (node.Kind == RegexNodeKind.Concatenate) { // Flatten nested concatenations for (int i = node.ChildCount() - 1; i >= 0; i--) @@ -389,7 +388,7 @@ List FlattenNestedConcatenations(RegexNode concat) todo.Push(node.Child(i)); } } - else if (node.Type == RegexNode.Capture) + else if (node.Kind == RegexNodeKind.Capture) { if (node.N == -1) { @@ -413,7 +412,7 @@ List FlattenNestedConcatenations(RegexNode concat) SymbolicRegexNode ConvertMulti(RegexNode node, bool topLevel) { - Debug.Assert(node.Type == RegexNode.Multi); + Debug.Assert(node.Kind == RegexNodeKind.Multi); string? sequence = node.Str; Debug.Assert(sequence is not null); @@ -431,7 +430,7 @@ SymbolicRegexNode ConvertMulti(RegexNode node, bool topLevel) SymbolicRegexNode ConvertOneloop(RegexNode node, bool isLazy) { - Debug.Assert(node.Type is RegexNode.Oneloop or RegexNode.Onelazy); + Debug.Assert(node.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Onelazy); bool ignoreCase = (node.Options & RegexOptions.IgnoreCase) != 0; BDD cond = Solver.CharConstraint(node.Ch, ignoreCase, _culture.Name); @@ -443,7 +442,7 @@ SymbolicRegexNode ConvertOneloop(RegexNode node, bool isLazy) SymbolicRegexNode ConvertNotoneloop(RegexNode node, bool isLazy) { - Debug.Assert(node.Type is RegexNode.Notoneloop or RegexNode.Notonelazy); + Debug.Assert(node.Kind is RegexNodeKind.Notoneloop or RegexNodeKind.Notonelazy); bool ignoreCase = (node.Options & RegexOptions.IgnoreCase) != 0; BDD cond = Solver.Not(Solver.CharConstraint(node.Ch, ignoreCase, _culture.Name)); @@ -455,7 +454,7 @@ SymbolicRegexNode ConvertNotoneloop(RegexNode node, bool isLazy) SymbolicRegexNode ConvertSet(RegexNode node) { - Debug.Assert(node.Type == RegexNode.Set); + Debug.Assert(node.Kind == RegexNodeKind.Set); string? set = node.Str; Debug.Assert(set is not null); @@ -467,7 +466,7 @@ SymbolicRegexNode ConvertSet(RegexNode node) SymbolicRegexNode ConvertSetloop(RegexNode node, bool isLazy) { - Debug.Assert(node.Type is RegexNode.Setloop or RegexNode.Setlazy); + Debug.Assert(node.Kind is RegexNodeKind.Setloop or RegexNodeKind.Setlazy); string? set = node.Str; Debug.Assert(set is not null); @@ -480,11 +479,11 @@ SymbolicRegexNode ConvertSetloop(RegexNode node, bool isLazy) #if DEBUG // TODO-NONBACKTRACKING: recognizing strictly only [] (RegexNode.Nothing), for example [0-[0]] would not be recognized - bool IsNothing(RegexNode node) => node.Type == RegexNode.Nothing || (node.Type == RegexNode.Set && ConvertSet(node).IsNothing); + bool IsNothing(RegexNode node) => node.Kind == RegexNodeKind.Nothing || (node.Kind == RegexNodeKind.Set && ConvertSet(node).IsNothing); - bool IsDotStar(RegexNode node) => node.Type == RegexNode.Setloop && Convert(node, topLevel: false).IsAnyStar; + bool IsDotStar(RegexNode node) => node.Kind == RegexNodeKind.Setloop && Convert(node, topLevel: false).IsAnyStar; - bool IsIntersect(RegexNode node) => node.Type == RegexNode.Testgroup && IsNothing(node.Child(2)); + bool IsIntersect(RegexNode node) => node.Kind == RegexNodeKind.ExpressionConditional && IsNothing(node.Child(2)); bool TryGetIntersection(RegexNode node, [Diagnostics.CodeAnalysis.NotNullWhen(true)] out List? conjuncts) { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs index c6754b8577b0d..5ba715c25ef4c 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs @@ -5,7 +5,7 @@ namespace System.Text.RegularExpressions.Symbolic { - internal readonly struct SymbolicMatch + internal readonly struct SymbolicMatch : IEquatable { /// Indicates failure to find a match. internal static SymbolicMatch NoMatch => new SymbolicMatch(-1, -1); @@ -20,17 +20,21 @@ public SymbolicMatch(int index, int length) } public int Index { get; } + public int Length { get; } + public bool Success => Index >= 0; public static bool operator ==(SymbolicMatch left, SymbolicMatch right) => - left.Index == right.Index && left.Length == right.Length; + left.Equals(right); public static bool operator !=(SymbolicMatch left, SymbolicMatch right) => - !(left == right); + !left.Equals(right); public override bool Equals([NotNullWhen(true)] object? obj) => - obj is SymbolicMatch other && this == other; + obj is SymbolicMatch other && Equals(other); + + public bool Equals(SymbolicMatch other) => Index == other.Index && Length == other.Length; public override int GetHashCode() => HashCode.Combine(Index, Length); } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs index ba522d513392c..4e60696eb0717 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs @@ -4,7 +4,7 @@ namespace System.Text.RegularExpressions.Symbolic { /// Misc information of structural properties of a that is computed bottom up. - internal readonly struct SymbolicRegexInfo + internal readonly struct SymbolicRegexInfo : IEquatable { private const uint IsAlwaysNullableMask = 1; private const uint StartsWithLineAnchorMask = 2; @@ -177,7 +177,9 @@ public static SymbolicRegexInfo Not(SymbolicRegexInfo info) => containsSomeCharacter: info.ContainsSomeCharacter, isLazy: info.IsLazy); - public override bool Equals(object? obj) => obj is SymbolicRegexInfo i && i._info == _info; + public override bool Equals(object? obj) => obj is SymbolicRegexInfo i && Equals(i); + + public bool Equals(SymbolicRegexInfo other) => _info == other._info; public override int GetHashCode() => _info.GetHashCode(); diff --git a/src/libraries/System.Text.RegularExpressions/tests/Regex.Count.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/Regex.Count.Tests.cs new file mode 100644 index 0000000000000..272cbb143d69d --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/tests/Regex.Count.Tests.cs @@ -0,0 +1,120 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading.Tasks; +using Xunit; + +namespace System.Text.RegularExpressions.Tests +{ + public class RegexCountTests + { + [Theory] + [MemberData(nameof(Count_ReturnsExpectedCount_TestData))] + public async Task Count_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, RegexOptions options, int expectedCount) + { + Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options); + Assert.Equal(expectedCount, r.Count(input)); + Assert.Equal(r.Count(input), r.Matches(input).Count); + + if (options == RegexOptions.None && engine == RegexEngine.Interpreter) + { + Assert.Equal(expectedCount, Regex.Count(input, pattern)); + } + + switch (engine) + { + case RegexEngine.Interpreter: + case RegexEngine.Compiled: + case RegexEngine.NonBacktracking: + RegexOptions engineOptions = RegexHelpers.OptionsFromEngine(engine); + Assert.Equal(expectedCount, Regex.Count(input, pattern, options | engineOptions)); + Assert.Equal(expectedCount, Regex.Count(input, pattern, options | engineOptions, Regex.InfiniteMatchTimeout)); + break; + } + } + + public static IEnumerable Count_ReturnsExpectedCount_TestData() + { + foreach (RegexEngine engine in RegexHelpers.AvailableEngines) + { + yield return new object[] { engine, @"", "", RegexOptions.None, 1 }; + yield return new object[] { engine, @"", "a", RegexOptions.None, 2 }; + yield return new object[] { engine, @"", "ab", RegexOptions.None, 3 }; + + yield return new object[] { engine, @"\w", "", RegexOptions.None, 0 }; + yield return new object[] { engine, @"\w", "a", RegexOptions.None, 1 }; + yield return new object[] { engine, @"\w", "ab", RegexOptions.None, 2 }; + + yield return new object[] { engine, @"\b\w+\b", "abc def ghi jkl", RegexOptions.None, 4 }; + + yield return new object[] { engine, @"A", "", RegexOptions.IgnoreCase, 0 }; + yield return new object[] { engine, @"A", "a", RegexOptions.IgnoreCase, 1 }; + yield return new object[] { engine, @"A", "aAaA", RegexOptions.IgnoreCase, 4 }; + + yield return new object[] { engine, @".", "\n\n\n", RegexOptions.None, 0 }; + yield return new object[] { engine, @".", "\n\n\n", RegexOptions.Singleline, 3 }; + } + } + + [Fact] + public void Count_InvalidArguments_Throws() + { + // input is null + AssertExtensions.Throws("input", () => new Regex("pattern").Count(null)); + AssertExtensions.Throws("input", () => Regex.Count(null, @"pattern")); + AssertExtensions.Throws("input", () => Regex.Count(null, @"pattern", RegexOptions.None)); + AssertExtensions.Throws("input", () => Regex.Count(null, @"pattern", RegexOptions.None, TimeSpan.FromMilliseconds(1))); + + // pattern is null + AssertExtensions.Throws("pattern", () => Regex.Count("input", null)); + AssertExtensions.Throws("pattern", () => Regex.Count("input", null, RegexOptions.None)); + AssertExtensions.Throws("pattern", () => Regex.Count("input", null, RegexOptions.None, TimeSpan.FromMilliseconds(1))); + + // pattern is invalid +#pragma warning disable RE0001 // invalid regex pattern + AssertExtensions.Throws(() => Regex.Count("input", @"[abc")); + AssertExtensions.Throws(() => Regex.Count("input", @"[abc", RegexOptions.None)); + AssertExtensions.Throws(() => Regex.Count("input", @"[abc", RegexOptions.None, TimeSpan.FromMilliseconds(1))); +#pragma warning restore RE0001 + + // options is invalid + AssertExtensions.Throws("options", () => Regex.Count("input", @"[abc]", (RegexOptions)(-1))); + AssertExtensions.Throws("options", () => Regex.Count("input", @"[abc]", (RegexOptions)(-1), TimeSpan.FromMilliseconds(1))); + + // matchTimeout is invalid + AssertExtensions.Throws("matchTimeout", () => Regex.Count("input", @"[abc]", RegexOptions.None, TimeSpan.FromMilliseconds(-2))); + } + + [Theory] + [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] + public async Task Count_Timeout_ThrowsAfterTooLongExecution(RegexEngine engine) + { + if (RegexHelpers.IsNonBacktracking(engine)) + { + // Test relies on backtracking taking a long time + return; + } + + const string Pattern = @"^(\w+\s?)*$"; + const string Input = "An input string that takes a very very very very very very very very very very very long time!"; + + Regex r = await RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.None, TimeSpan.FromMilliseconds(1)); + + Stopwatch sw = Stopwatch.StartNew(); + Assert.Throws(() => r.Count(Input)); + Assert.InRange(sw.Elapsed.TotalSeconds, 0, 10); // arbitrary upper bound that should be well above what's needed with a 1ms timeout + + switch (engine) + { + case RegexEngine.Interpreter: + case RegexEngine.Compiled: + sw = Stopwatch.StartNew(); + Assert.Throws(() => Regex.Count(Input, Pattern, RegexHelpers.OptionsFromEngine(engine), TimeSpan.FromMilliseconds(1))); + Assert.InRange(sw.Elapsed.TotalSeconds, 0, 10); // arbitrary upper bound that should be well above what's needed with a 1ms timeout + break; + } + } + } +} diff --git a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs index b010a53c035e2..6cd5dcc3cd316 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs @@ -200,6 +200,16 @@ public static IEnumerable Match_MemberData() yield return (@"((\d{2,3}?)){2}", "1234", RegexOptions.None, 0, 4, true, "1234"); yield return (@"(abc\d{2,3}?){2}", "abc123abc4567", RegexOptions.None, 0, 12, true, "abc123abc45"); + // Testing selected FindOptimizations finds the right prefix + yield return (@"(^|a+)bc", " aabc", RegexOptions.None, 0, 5, true, "aabc"); + yield return (@"(^|($|a+))bc", " aabc", RegexOptions.None, 0, 5, true, "aabc"); + yield return (@"yz(^|a+)bc", " yzaabc", RegexOptions.None, 0, 7, true, "yzaabc"); + yield return (@"(^a|a$) bc", "a bc", RegexOptions.None, 0, 4, true, "a bc"); + yield return (@"(abcdefg|abcdef|abc|a)h", " ah ", RegexOptions.None, 0, 8, true, "ah"); + yield return (@"(^abcdefg|abcdef|^abc|a)h", " abcdefh ", RegexOptions.None, 0, 13, true, "abcdefh"); + yield return (@"(a|^abcdefg|abcdef|^abc)h", " abcdefh ", RegexOptions.None, 0, 13, true, "abcdefh"); + yield return (@"(abcdefg|abcdef)h", " abcdefghij ", RegexOptions.None, 0, 16, true, "abcdefgh"); + if (!RegexHelpers.IsNonBacktracking(engine)) { // Back references not support with NonBacktracking @@ -232,17 +242,61 @@ public static IEnumerable Match_MemberData() yield return (@"(\d{2,3}?)+?", "1234", RegexOptions.None, 0, 4, true, "12"); yield return (@"(\d{2,3}?)*?", "123456", RegexOptions.None, 0, 4, true, ""); - foreach (RegexOptions lineOption in new[] { RegexOptions.None, RegexOptions.Singleline, RegexOptions.Multiline }) + foreach (RegexOptions lineOption in new[] { RegexOptions.None, RegexOptions.Singleline }) { yield return (@".*", "abc", lineOption, 1, 2, true, "bc"); yield return (@".*c", "abc", lineOption, 1, 2, true, "bc"); yield return (@"b.*", "abc", lineOption, 1, 2, true, "bc"); yield return (@".*", "abc", lineOption, 2, 1, true, "c"); + yield return (@"a.*[bc]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*[bc]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*[bc]", "xyza12345d6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*[bcd]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*[bcd]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*[bcd]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*[bcd]", "xyza12345e6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*[bcde]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*[bcde]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*[bcde]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*[bcde]", "xyza12345e6789", lineOption, 0, 14, true, "a12345e"); + yield return (@"a.*[bcde]", "xyza12345f6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*[bcdef]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*[bcdef]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*[bcdef]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*[bcdef]", "xyza12345e6789", lineOption, 0, 14, true, "a12345e"); + yield return (@"a.*[bcdef]", "xyza12345f6789", lineOption, 0, 14, true, "a12345f"); + yield return (@"a.*[bcdef]", "xyza12345g6789", lineOption, 0, 14, false, ""); + yield return (@".*?", "abc", lineOption, 1, 2, true, ""); yield return (@".*?c", "abc", lineOption, 1, 2, true, "bc"); yield return (@"b.*?", "abc", lineOption, 1, 2, true, "b"); yield return (@".*?", "abc", lineOption, 2, 1, true, ""); + + yield return (@"a.*?[bc]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*?[bc]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*?[bc]", "xyza12345d6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*?[bcd]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*?[bcd]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*?[bcd]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*?[bcd]", "xyza12345e6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*?[bcde]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*?[bcde]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*?[bcde]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*?[bcde]", "xyza12345e6789", lineOption, 0, 14, true, "a12345e"); + yield return (@"a.*?[bcde]", "xyza12345f6789", lineOption, 0, 14, false, ""); + + yield return (@"a.*?[bcdef]", "xyza12345b6789", lineOption, 0, 14, true, "a12345b"); + yield return (@"a.*?[bcdef]", "xyza12345c6789", lineOption, 0, 14, true, "a12345c"); + yield return (@"a.*?[bcdef]", "xyza12345d6789", lineOption, 0, 14, true, "a12345d"); + yield return (@"a.*?[bcdef]", "xyza12345e6789", lineOption, 0, 14, true, "a12345e"); + yield return (@"a.*?[bcdef]", "xyza12345f6789", lineOption, 0, 14, true, "a12345f"); + yield return (@"a.*?[bcdef]", "xyza12345g6789", lineOption, 0, 14, false, ""); } // Nested loops @@ -274,8 +328,42 @@ public static IEnumerable Match_MemberData() // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" yield return (@"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzza", RegexOptions.None, 0, 18, false, string.Empty); + // Anchors + foreach (RegexOptions anchorOptions in new[] { RegexOptions.None, RegexOptions.Multiline }) + { + yield return (@"^abc", "abc", anchorOptions, 0, 3, true, "abc"); + yield return (@"^abc", " abc", anchorOptions, 0, 4, false, ""); + yield return (@"^abc|^def", "def", anchorOptions, 0, 3, true, "def"); + yield return (@"^abc|^def", " abc", anchorOptions, 0, 4, false, ""); + yield return (@"^abc|^def", " def", anchorOptions, 0, 4, false, ""); + yield return (@"abc|^def", " abc", anchorOptions, 0, 4, true, "abc"); + yield return (@"abc|^def|^efg", " abc", anchorOptions, 0, 4, true, "abc"); + yield return (@"^abc|def|^efg", " def", anchorOptions, 0, 4, true, "def"); + yield return (@"^abc|def", " def", anchorOptions, 0, 4, true, "def"); + yield return (@"abcd$", "1234567890abcd", anchorOptions, 0, 14, true, "abcd"); + yield return (@"abc{1,4}d$", "1234567890abcd", anchorOptions, 0, 14, true, "abcd"); + yield return (@"abc{1,4}d$", "1234567890abccccd", anchorOptions, 0, 17, true, "abccccd"); + } + if (!RegexHelpers.IsNonBacktracking(engine)) + { + yield return (@"\Gabc", "abc", RegexOptions.None, 0, 3, true, "abc"); + yield return (@"\Gabc", " abc", RegexOptions.None, 0, 4, false, ""); + yield return (@"\Gabc", " abc", RegexOptions.None, 1, 3, true, "abc"); + yield return (@"\Gabc|\Gdef", "def", RegexOptions.None, 0, 3, true, "def"); + yield return (@"\Gabc|\Gdef", " abc", RegexOptions.None, 0, 4, false, ""); + yield return (@"\Gabc|\Gdef", " def", RegexOptions.None, 0, 4, false, ""); + yield return (@"\Gabc|\Gdef", " abc", RegexOptions.None, 1, 3, true, "abc"); + yield return (@"\Gabc|\Gdef", " def", RegexOptions.None, 1, 3, true, "def"); + yield return (@"abc|\Gdef", " abc", RegexOptions.None, 0, 4, true, "abc"); + yield return (@"\Gabc|def", " def", RegexOptions.None, 0, 4, true, "def"); + } + // Anchors and multiline - yield return (@"^A$", "ABC\n", RegexOptions.Multiline, 0, 2, false, string.Empty); + yield return (@"^A$", "A\n", RegexOptions.Multiline, 0, 2, true, "A"); + yield return (@"^A$", "ABC\n", RegexOptions.Multiline, 0, 4, false, string.Empty); + yield return (@"^A$", "123\nA", RegexOptions.Multiline, 0, 5, true, "A"); + yield return (@"^A$", "123\nA\n456", RegexOptions.Multiline, 0, 9, true, "A"); + yield return (@"^A$|^B$", "123\nB\n456", RegexOptions.Multiline, 0, 9, true, "B"); // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" yield return (@"\A(line2\n)line3\Z", "line2\nline3\n", RegexOptions.Multiline, 0, 12, true, "line2\nline3"); @@ -418,6 +506,38 @@ public static IEnumerable Match_MemberData() } // Alternation construct + foreach (string input in new[] { "abc", "def" }) + { + string upper = input.ToUpperInvariant(); + + // Two branches + yield return (@"abc|def", input, RegexOptions.None, 0, input.Length, true, input); + yield return (@"abc|def", upper, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, 0, input.Length, true, upper); + yield return (@"abc|def", upper, RegexOptions.None, 0, input.Length, false, ""); + + // Three branches + yield return (@"abc|agh|def", input, RegexOptions.None, 0, input.Length, true, input); + yield return (@"abc|agh|def", upper, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, 0, input.Length, true, upper); + yield return (@"abc|agh|def", upper, RegexOptions.None, 0, input.Length, false, ""); + + // Four branches + yield return (@"abc|agh|def|aij", input, RegexOptions.None, 0, input.Length, true, input); + yield return (@"abc|agh|def|aij", upper, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, 0, input.Length, true, upper); + yield return (@"abc|agh|def|aij", upper, RegexOptions.None, 0, input.Length, false, ""); + + // Four branches (containing various other constructs) + if (!RegexHelpers.IsNonBacktracking(engine)) + { + yield return (@"abc|(agh)|(?=def)def|(?:(?(aij)aij|(?!)))", input, RegexOptions.None, 0, input.Length, true, input); + yield return (@"abc|(agh)|(?=def)def|(?:(?(aij)aij|(?!)))", upper, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, 0, input.Length, true, upper); + yield return (@"abc|(agh)|(?=def)def|(?:(?(aij)aij|(?!)))", upper, RegexOptions.None, 0, input.Length, false, ""); + } + + // Sets in various positions in each branch + yield return (@"a\wc|\wgh|de\w", input, RegexOptions.None, 0, input.Length, true, input); + yield return (@"a\wc|\wgh|de\w", upper, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, 0, input.Length, true, upper); + yield return (@"a\wc|\wgh|de\w", upper, RegexOptions.None, 0, input.Length, false, ""); + } yield return ("[^a-z0-9]etag|[^a-z0-9]digest", "this string has .digest as a substring", RegexOptions.None, 16, 7, true, ".digest"); if (!RegexHelpers.IsNonBacktracking(engine)) { @@ -440,7 +560,6 @@ public static IEnumerable Match_MemberData() yield return ("(?>(?:a|ab|abc|abcd))d", "abcd", RegexOptions.None, 0, 4, false, string.Empty); yield return ("(?>(?:a|ab|abc|abcd))d", "abcd", RegexOptions.RightToLeft, 0, 4, true, "abcd"); } - yield return ("[^a-z0-9]etag|[^a-z0-9]digest", "this string has .digest as a substring", RegexOptions.None, 16, 7, true, ".digest"); // No Negation yield return ("[abcd-[abcd]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty); @@ -864,7 +983,7 @@ private async Task Match_TestThatTimeoutHappens(RegexEngine engine) } string input = new string(chars); - Regex re = await RegexHelpers.GetRegexAsync(engine, @"a.{20}$", RegexOptions.None, TimeSpan.FromMilliseconds(10)); + Regex re = await RegexHelpers.GetRegexAsync(engine, @"a.{20}^", RegexOptions.None, TimeSpan.FromMilliseconds(10)); Assert.Throws(() => { re.Match(input); }); } @@ -1020,6 +1139,18 @@ public static IEnumerable Match_Advanced_TestData() new CaptureData(string.Empty, 1, 0) } }; + yield return new object[] + { + engine, + "(d+?)(e*?)(f+)", "dddeeefff", RegexOptions.None, 0, 9, + new CaptureData[] + { + new CaptureData("dddeeefff", 0, 9), + new CaptureData("ddd", 0, 3), + new CaptureData("eee", 3, 3), + new CaptureData("fff", 6, 3), + } + }; // Noncapturing group : Actual - "(a+)(?:b*)(ccc)" yield return new object[] diff --git a/src/libraries/System.Text.RegularExpressions/tests/RegexReductionTests.cs b/src/libraries/System.Text.RegularExpressions/tests/RegexReductionTests.cs index c3cd830fbb7b2..705eacb09f5fa 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/RegexReductionTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/RegexReductionTests.cs @@ -6,6 +6,8 @@ namespace System.Text.RegularExpressions.Tests { + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Many of these optimizations don't exist in .NET Framework.")] + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))] public class RegexReductionTests { // These tests depend on using reflection to access internals of Regex in order to validate @@ -18,19 +20,27 @@ public class RegexReductionTests private static readonly FieldInfo s_regexCode; private static readonly FieldInfo s_regexCodeCodes; private static readonly FieldInfo s_regexCodeTree; + private static readonly FieldInfo s_regexCodeFindOptimizations; + private static readonly PropertyInfo s_regexCodeFindOptimizationsMaxPossibleLength; private static readonly FieldInfo s_regexCodeTreeMinRequiredLength; static RegexReductionTests() { - if (PlatformDetection.IsNetFramework) + if (PlatformDetection.IsNetFramework || PlatformDetection.IsBuiltWithAggressiveTrimming) { - // These members may not exist, and the tests won't run. + // These members may not exist or may have been trimmed away, and the tests won't run. return; } s_regexCode = typeof(Regex).GetField("_code", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(s_regexCode); + s_regexCodeFindOptimizations = s_regexCode.FieldType.GetField("FindOptimizations", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull(s_regexCodeFindOptimizations); + + s_regexCodeFindOptimizationsMaxPossibleLength = s_regexCodeFindOptimizations.FieldType.GetProperty("MaxPossibleLength", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull(s_regexCodeFindOptimizationsMaxPossibleLength); + s_regexCodeCodes = s_regexCode.FieldType.GetField("Codes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(s_regexCodeCodes); @@ -71,8 +81,21 @@ private static int GetMinRequiredLength(Regex r) return (int)minRequiredLength; } + private static int? GetMaxPossibleLength(Regex r) + { + object code = s_regexCode.GetValue(r); + Assert.NotNull(code); + + object findOpts = s_regexCodeFindOptimizations.GetValue(code); + Assert.NotNull(findOpts); + + object maxPossibleLength = s_regexCodeFindOptimizationsMaxPossibleLength.GetValue(findOpts); + Assert.True(maxPossibleLength is null || maxPossibleLength is int); + + return (int?)maxPossibleLength; + } + [Theory] - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Many of these optimizations don't exist in .NET Framework.")] // Two greedy one loops [InlineData("a*a*", "a*")] [InlineData("(a*a*)", "(a*)")] @@ -343,6 +366,9 @@ private static int GetMinRequiredLength(Regex r) [InlineData("(?:a{1,2}){4}", "a{4,8}")] // Nested atomic [InlineData("(?>(?>(?>(?>abc*))))", "(?>ab(?>c*))")] + [InlineData("(?>(?>(?>(?>))))", "")] + [InlineData("(?>(?>(?>(?>(?!)))))", "(?!)")] + [InlineData("(?=(?>))", "")] // Alternation reduction [InlineData("a|b", "[ab]")] [InlineData("a|b|c|d|e|g|h|z", "[a-eghz]")] @@ -366,6 +392,11 @@ private static int GetMinRequiredLength(Regex r) [InlineData("hello there|hello again|hello|hello|hello|hello", "hello(?> there| again|)")] [InlineData("hello there|hello again|hello|hello|hello|hello|hello world", "hello(?> there| again|| world)")] [InlineData("hello there|hello again|hello|hello|hello|hello|hello world|hello", "hello(?> there| again|| world)")] + [InlineData("ab|cd|||ef", "ab|cd||ef")] + [InlineData("|ab|cd|e||f", "|ab|cd|ef")] + [InlineData("ab|cd|||||||||||ef", "ab|cd||ef")] + [InlineData("ab|cd|||||||||||e||f|||", "ab|cd||ef")] + [InlineData("ab|cd|(?!)|ef", "ab|cd|ef")] [InlineData("abcd(?:(?i:e)|(?i:f))", "abcd(?i:[ef])")] [InlineData("(?i:abcde)|(?i:abcdf)", "(?i:abcd[ef])")] [InlineData("xyz(?:(?i:abcde)|(?i:abcdf))", "xyz(?i:abcd[ef])")] @@ -376,14 +407,40 @@ private static int GetMinRequiredLength(Regex r) [InlineData("(?(a)a)", "(?(a)a|)")] [InlineData("(?(abc)def)", "(?(abc)def|)")] [InlineData("(?(\\w)\\d)", "(?(\\w)\\d|)")] + // Loops inside alternation constructs + [InlineData("(abc*|def)ghi", "(ab(?>c*)|def)ghi")] + [InlineData("(abc|def*)ghi", "(abc|de(?>f*))ghi")] + [InlineData("(abc*|def*)ghi", "(ab(?>c*)|de(?>f*))ghi")] + [InlineData("(abc*|def*)", "(ab(?>c*)|de(?>f*))")] + [InlineData("(?(\\w)abc*|def*)ghi", "(?(\\w)ab(?>c*)|de(?>f*))ghi")] + [InlineData("(?(\\w)abc*|def*)", "(?(\\w)ab(?>c*)|de(?>f*))")] + [InlineData("(?(xyz*)abc|def)", "(?(xy(?>z*))abc|def)")] + [InlineData("(?(xyz*)abc|def)\\w", "(?(xy(?>z*))abc|def)\\w")] + // Loops followed by alternation constructs + [InlineData("a*(bcd|efg)", "(?>a*)(bcd|efg)")] + [InlineData("a*(?(xyz)bcd|efg)", "(?>a*)(?(xyz)bcd|efg)")] // Auto-atomicity [InlineData("a*b", "(?>a*)b")] - [InlineData("a*b+", "(?>a*)b+")] - [InlineData("a*b{3,4}", "(?>a*)b{3,4}")] + [InlineData("a*b+", "(?>a*)(?>b+)")] + [InlineData("a*b*", "(?>a*)(?>b*)")] + [InlineData("a*b+c*", "(?>a*)(?>b+)(?>c*)")] + [InlineData("a*b*c*", "(?>a*)(?>b*)(?>c*)")] + [InlineData("a*b*c*|d*[ef]*", "(?>a*)(?>b*)(?>c*)|(?>d*)(?>[ef]*)")] + [InlineData("(a*)(b*)(c*)", "((?>a*))((?>b*))((?>c*))")] + [InlineData("a*b{3,4}", "(?>a*)(?>b{3,4})")] + [InlineData("[ab]*[^a]*", "[ab]*(?>[^a]*)")] + [InlineData("[aa]*[^a]*", "(?>a*)(?>[^a]*)")] + [InlineData("a??", "")] + [InlineData("(abc*?)", "(ab)")] + [InlineData("a{1,3}?", "a{1,4}?")] + [InlineData("a{2,3}?", "a{2}")] + [InlineData("bc(a){1,3}?", "bc(a){1,2}?")] + [InlineData("c{3,}?|f{2,}?", "c{3}|f{2}")] + [InlineData("[a-z]*[\x0000-\xFFFF]+", "[a-z]*(?>[\x0000-\xFFFF]+)")] [InlineData("a+b", "(?>a+)b")] [InlineData("a?b", "(?>a?)b")] [InlineData("[^\n]*\n", "(?>[^\n]*)\n")] - [InlineData("[^\n]*\n+", "(?>[^\n]*)\n+")] + [InlineData("[^\n]*\n+", "(?>[^\n]*)(?>\n+)")] [InlineData("(a+)b", "((?>a+))b")] [InlineData("a*(?:bcd|efg)", "(?>a*)(?:bcd|efg)")] [InlineData("\\w*\\b", "(?>\\w*)\\b")] @@ -392,8 +449,8 @@ private static int GetMinRequiredLength(Regex r) [InlineData("(?:a[ce]*|b*)g", "(?:a(?>[ce]*)|(?>b*))g")] [InlineData("(?:a[ce]*|b*)c", "(?:a[ce]*|(?>b*))c")] [InlineData("apple|(?:orange|pear)|grape", "apple|orange|pear|grape")] - [InlineData("(?>(?>(?>(?:abc)*)))", "(?:abc)*")] - [InlineData("(?:w*)+", "(?>w*)+")] + [InlineData("(?:abc)*", "(?>(?>(?>(?:abc)*)))")] + [InlineData("(?:w*)+", "(?>(?>w*)+)")] [InlineData("(?:w*)+\\.", "(?>w*)+\\.")] [InlineData("(a[bcd]e*)*fg", "(a[bcd](?>e*))*fg")] [InlineData("(\\w[bcd]\\s*)*fg", "(\\w[bcd](?>\\s*))*fg")] @@ -418,7 +475,6 @@ public void PatternsReduceIdentically(string pattern1, string pattern2) } [Theory] - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Many of these optimizations don't exist in .NET Framework.")] // Not coalescing loops [InlineData("aa", "a{2}")] [InlineData("a[^a]", "a{2}")] @@ -461,7 +517,7 @@ public void PatternsReduceIdentically(string pattern1, string pattern2) [InlineData("(?i:abcd)|abcd", "abcd|abcd")] [InlineData("abcd|(?i:abcd)", "abcd|abcd")] // Not applying auto-atomicity - [InlineData("a*b*", "(?>a*)b*")] + [InlineData(@"(a*|b*)\w*", @"((?>a*)|(?>b*))\w*")] [InlineData("[ab]*[^a]", "(?>[ab]*)[^a]")] [InlineData("[ab]*[^a]*", "(?>[ab]*)[^a]*")] [InlineData("[ab]*[^a]*?", "(?>[ab]*)[^a]*?")] @@ -477,6 +533,18 @@ public void PatternsReduceIdentically(string pattern1, string pattern2) [InlineData("(w+)+", "((?>w+))+")] [InlineData("(w{1,2})+", "((?>w{1,2}))+")] [InlineData("(?:ab|cd|ae)f", "(?>ab|cd|ae)f")] + // Loops inside alternation constructs + [InlineData("(abc*|def)chi", "(ab(?>c*)|def)chi")] + [InlineData("(abc|def*)fhi", "(abc|de(?>f*))fhi")] + [InlineData("(abc*|def*)\\whi", "(ab(?>c*)|de(?>f*))\\whi")] + [InlineData("(?(\\w)abc*|def*)\\whi", "(?(\\w)ab(?>c*)|de(?>f*))\\whi")] + // Loops followed by alternation constructs + [InlineData("a*(bcd|afg)", "(?>a*)(bcd|afg)")] + [InlineData("(a*)(?(1)bcd|efg)", "((?>a*))(?(1)bcd|efg)")] + [InlineData("a*(?(abc)bcd|efg)", "(?>a*)(?(abc)bcd|efg)")] + [InlineData("a*(?(xyz)acd|efg)", "(?>a*)(?(xyz)acd|efg)")] + [InlineData("a*(?(xyz)bcd|afg)", "(?>a*)(?(xyz)bcd|afg)")] + [InlineData("a*(?(xyz)bcd)", "(?>a*)(?(xyz)bcd)")] public void PatternsReduceDifferently(string pattern1, string pattern2) { string result1 = GetRegexCodes(new Regex(pattern1)); @@ -488,57 +556,99 @@ public void PatternsReduceDifferently(string pattern1, string pattern2) } [Theory] - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Not computed in netfx")] - [InlineData(@"a", 1)] - [InlineData(@"[^a]", 1)] - [InlineData(@"[abcdefg]", 1)] - [InlineData(@"abcd", 4)] - [InlineData(@"a*", 0)] - [InlineData(@"a*?", 0)] - [InlineData(@"a?", 0)] - [InlineData(@"a??", 0)] - [InlineData(@"a+", 1)] - [InlineData(@"a+?", 1)] - [InlineData(@"a{2}", 2)] - [InlineData(@"a{2}?", 2)] - [InlineData(@"a{3,17}", 3)] - [InlineData(@"a{3,17}?", 3)] - [InlineData(@"(abcd){5}", 20)] - [InlineData(@"(abcd|ef){2,6}", 4)] - [InlineData(@"abcef|de", 2)] - [InlineData(@"abc(def|ghij)k", 7)] - [InlineData(@"\d{1,2}-\d{1,2}-\d{2,4}", 6)] - [InlineData(@"1(?=9)\d", 2)] - [InlineData(@"1(?!\d)\w", 2)] - [InlineData(@"a*a*a*a*a*a*a*b*", 0)] - [InlineData(@"((a{1,2}){4}){3,7}", 12)] - [InlineData(@"\b\w{4}\b", 4)] - [InlineData(@"abcd(?=efgh)efgh", 8)] - [InlineData(@"abcd(?<=cd)efgh", 8)] - [InlineData(@"abcd(?!ab)efgh", 8)] - [InlineData(@"abcd(?\d{1,2})-\d{2,4}", RegexOptions.None, 6, 10)] + [InlineData(@"1(?=9)\d", RegexOptions.None, 2, 2)] + [InlineData(@"1(?!\d)\w", RegexOptions.None, 2, 2)] + [InlineData(@"a*a*a*a*a*a*a*b*", RegexOptions.None, 0, null)] + [InlineData(@"((a{1,2}){4}){3,7}", RegexOptions.None, 12, 56)] + [InlineData(@"((a{1,2}){4}?){3,7}", RegexOptions.None, 12, 56)] + [InlineData(@"\b\w{4}\b", RegexOptions.None, 4, 4)] + [InlineData(@"\b\w{4}\b", RegexOptions.ECMAScript, 4, 4)] + [InlineData(@"abcd(?=efgh)efgh", RegexOptions.None, 8, 8)] + [InlineData(@"abcd(?<=cd)efgh", RegexOptions.None, 8, 8)] + [InlineData(@"abcd(?!ab)efgh", RegexOptions.None, 8, 8)] + [InlineData(@"abcd(?
+ diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs index 4ef7a3b721e4d..74ef7ec9e890b 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs @@ -95,10 +95,27 @@ protected override ValueTask WaitAsyncCore(int permitCount, Canc return new ValueTask(lease); } - // Don't queue if queue limit reached - if (_queueCount + permitCount > _options.QueueLimit) + // Avoid integer overflow by using subtraction instead of addition + Debug.Assert(_options.QueueLimit >= _queueCount); + if (_options.QueueLimit - _queueCount < permitCount) { - return new ValueTask(QueueLimitLease); + if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && permitCount <= _options.QueueLimit) + { + // remove oldest items from queue until there is space for the newest request + do + { + RequestRegistration oldestRequest = _queue.DequeueHead(); + _queueCount -= oldestRequest.Count; + Debug.Assert(_queueCount >= 0); + oldestRequest.Tcs.TrySetResult(FailedLease); + } + while (_options.QueueLimit - _queueCount < permitCount); + } + else + { + // Don't queue if queue limit reached and QueueProcessingOrder is OldestFirst + return new ValueTask(QueueLimitLease); + } } TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index bb1ec82f3fff0..6593d895a6810 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -101,10 +101,27 @@ protected override ValueTask WaitAsyncCore(int tokenCount, Cance return new ValueTask(lease); } - // Don't queue if queue limit reached - if (_queueCount + tokenCount > _options.QueueLimit) + // Avoid integer overflow by using subtraction instead of addition + Debug.Assert(_options.QueueLimit >= _queueCount); + if (_options.QueueLimit - _queueCount < tokenCount) { - return new ValueTask(CreateFailedTokenLease(tokenCount)); + if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && tokenCount <= _options.QueueLimit) + { + // remove oldest items from queue until there is space for the newest acquisition request + do + { + RequestRegistration oldestRequest = _queue.DequeueHead(); + _queueCount -= oldestRequest.Count; + Debug.Assert(_queueCount >= 0); + oldestRequest.Tcs.TrySetResult(FailedLease); + } + while (_options.QueueLimit - _queueCount < tokenCount); + } + else + { + // Don't queue if queue limit reached and QueueProcessingOrder is OldestFirst + return new ValueTask(CreateFailedTokenLease(tokenCount)); + } } TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/libraries/System.Threading.RateLimiting/tests/BaseRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/BaseRateLimiterTests.cs index 9d98a5101a33b..a96dc0ba86e63 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/BaseRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/BaseRateLimiterTests.cs @@ -24,11 +24,23 @@ public abstract class BaseRateLimiterTests public abstract Task CanAcquireResourceAsync_QueuesAndGrabsNewest(); [Fact] - public abstract Task FailsWhenQueuingMoreThanLimit(); + public abstract Task FailsWhenQueuingMoreThanLimit_OldestFirst(); + + [Fact] + public abstract Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst(); + + [Fact] + public abstract Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst(); + + [Fact] + public abstract Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst(); [Fact] public abstract Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable(); + [Fact] + public abstract Task LargeAcquiresAndQueuesDoNotIntegerOverflow(); + [Fact] public abstract void ThrowsWhenAcquiringMoreThanLimit(); diff --git a/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs index 22658e07a5c9c..da041ac938aa2 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs @@ -94,9 +94,9 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() } [Fact] - public override async Task FailsWhenQueuingMoreThanLimit() + public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); using var lease = limiter.Acquire(1); var wait = limiter.WaitAsync(1); @@ -105,11 +105,96 @@ public override async Task FailsWhenQueuingMoreThanLimit() } [Fact] - public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() + public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); var lease = limiter.Acquire(1); var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(1); + var lease1 = await wait; + Assert.False(lease1.IsAcquired); + Assert.False(wait2.IsCompleted); + + lease.Dispose(); + + lease = await wait2; + Assert.True(lease.IsAcquired); + } + + [Fact] + public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() + { + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2)); + var lease = limiter.Acquire(2); + Assert.True(lease.IsAcquired); + var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(1); + Assert.False(wait2.IsCompleted); + + var wait3 = limiter.WaitAsync(2); + var lease1 = await wait; + var lease2 = await wait2; + Assert.False(lease1.IsAcquired); + Assert.False(lease2.IsAcquired); + Assert.False(wait3.IsCompleted); + + lease.Dispose(); + + lease = await wait3; + Assert.True(lease.IsAcquired); + } + + [Fact] + public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() + { + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1)); + var lease = limiter.Acquire(2); + Assert.True(lease.IsAcquired); + + // Fill queue + var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var lease1 = await limiter.WaitAsync(2); + Assert.False(lease1.IsAcquired); + + lease.Dispose(); + var lease2 = await wait; + Assert.True(lease2.IsAcquired); + } + + [Fact] + public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() + { + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue)); + var lease = limiter.Acquire(int.MaxValue); + Assert.True(lease.IsAcquired); + + // Fill queue + var wait = limiter.WaitAsync(3); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(int.MaxValue); + Assert.False(wait2.IsCompleted); + + var lease1 = await wait; + Assert.False(lease1.IsAcquired); + + lease.Dispose(); + var lease2 = await wait2; + Assert.True(lease2.IsAcquired); + } + + [Fact] + public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() + { + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var lease = limiter.Acquire(1); + var wait = limiter.WaitAsync(1); var failedLease = await limiter.WaitAsync(1); Assert.False(failedLease.IsAcquired); diff --git a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs index edf05bfe15cce..594bb79be22eb 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs @@ -111,9 +111,9 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() } [Fact] - public override async Task FailsWhenQueuingMoreThanLimit() + public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, TimeSpan.Zero, 1, autoReplenishment: false)); using var lease = limiter.Acquire(1); var wait = limiter.WaitAsync(1); @@ -125,9 +125,77 @@ public override async Task FailsWhenQueuingMoreThanLimit() } [Fact] - public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() + public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, + TimeSpan.Zero, 1, autoReplenishment: false)); + var lease = limiter.Acquire(1); + var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(1); + var lease1 = await wait; + Assert.False(lease1.IsAcquired); + Assert.False(wait2.IsCompleted); + + limiter.TryReplenish(); + + lease = await wait2; + Assert.True(lease.IsAcquired); + } + + [Fact] + public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() + { + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, + TimeSpan.Zero, 1, autoReplenishment: false)); + var lease = limiter.Acquire(2); + Assert.True(lease.IsAcquired); + var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(1); + Assert.False(wait2.IsCompleted); + + var wait3 = limiter.WaitAsync(2); + var lease1 = await wait; + var lease2 = await wait2; + Assert.False(lease1.IsAcquired); + Assert.False(lease2.IsAcquired); + Assert.False(wait3.IsCompleted); + + limiter.TryReplenish(); + limiter.TryReplenish(); + + lease = await wait3; + Assert.True(lease.IsAcquired); + } + + [Fact] + public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() + { + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1, + TimeSpan.Zero, 1, autoReplenishment: false)); + var lease = limiter.Acquire(2); + Assert.True(lease.IsAcquired); + + // Fill queue + var wait = limiter.WaitAsync(1); + Assert.False(wait.IsCompleted); + + var lease1 = await limiter.WaitAsync(2); + Assert.False(lease1.IsAcquired); + + limiter.TryReplenish(); + + lease = await wait; + Assert.True(lease.IsAcquired); + } + + [Fact] + public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() + { + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, TimeSpan.Zero, 1, autoReplenishment: false)); var lease = limiter.Acquire(1); var wait = limiter.WaitAsync(1); @@ -147,6 +215,29 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv Assert.True(lease.IsAcquired); } + [Fact] + public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() + { + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue, + TimeSpan.Zero, int.MaxValue, autoReplenishment: false)); + var lease = limiter.Acquire(int.MaxValue); + Assert.True(lease.IsAcquired); + + // Fill queue + var wait = limiter.WaitAsync(3); + Assert.False(wait.IsCompleted); + + var wait2 = limiter.WaitAsync(int.MaxValue); + Assert.False(wait2.IsCompleted); + + var lease1 = await wait; + Assert.False(lease1.IsAcquired); + + limiter.TryReplenish(); + var lease2 = await wait2; + Assert.True(lease2.IsAcquired); + } + [Fact] public override void ThrowsWhenAcquiringMoreThanLimit() { diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Resources/Strings.resx b/src/libraries/System.Threading.Tasks.Dataflow/src/Resources/Strings.resx index 0c233f2bf9b4f..d8f878ef5201c 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Resources/Strings.resx +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Resources/Strings.resx @@ -93,9 +93,6 @@ This member is not supported on this dataflow block. The block is intended for a specific purpose that does not utilize this member. - - The SyncRoot property may not be used for the synchronization of concurrent collections. - An error occurred while linking up the target or during the cleanup after completion. diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs index 2d59951cad66e..a8b9e355e314e 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs @@ -1762,7 +1762,7 @@ public async Task TestEncapsulate_EncapsulateBoundedTarget() source.Complete(); await encapsulated.Completion; - Assert.Equal(messagesReceived, messagesSent); + Assert.Equal(messagesSent, messagesReceived); } [Fact] diff --git a/src/libraries/System.Threading.Tasks/tests/Task/TaskRtTests.cs b/src/libraries/System.Threading.Tasks/tests/Task/TaskRtTests.cs index e763ae63a43d4..ffb2437aa4b3e 100644 --- a/src/libraries/System.Threading.Tasks/tests/Task/TaskRtTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/Task/TaskRtTests.cs @@ -691,6 +691,24 @@ public static void RunDelayTests_NegativeCases() } } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public static void TaskDelay_Cancellation_ContinuationsInvokedAsynchronously() + { + var cts = new CancellationTokenSource(); + + var tl = new ThreadLocal(); + Task c = Task.Delay(-1, cts.Token).ContinueWith(_ => + { + Assert.Equal(0, tl.Value); + }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + + tl.Value = 42; + cts.Cancel(); + tl.Value = 0; + + c.GetAwaiter().GetResult(); + } + // Test that exceptions are properly wrapped when thrown in various scenarios. // Make sure that "indirect" logic does not add superfluous exception wrapping. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] diff --git a/src/libraries/System.Threading/ref/System.Threading.cs b/src/libraries/System.Threading/ref/System.Threading.cs index 1237c49cecaed..3c5f1268e8873 100644 --- a/src/libraries/System.Threading/ref/System.Threading.cs +++ b/src/libraries/System.Threading/ref/System.Threading.cs @@ -235,7 +235,7 @@ public static partial class LazyInitializer public static T EnsureInitialized([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T? target, System.Func valueFactory) where T : class { throw null; } public static T EnsureInitialized([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T? target, [System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("syncLock")] ref object? syncLock, System.Func valueFactory) where T : class { throw null; } } - public partial struct LockCookie + public partial struct LockCookie : System.IEquatable { private int _dummyPrimitive; public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } diff --git a/src/libraries/System.Threading/src/System/Threading/LockCookie.cs b/src/libraries/System.Threading/src/System/Threading/LockCookie.cs index 6a76ceb023d0a..a9c9011179f8f 100644 --- a/src/libraries/System.Threading/src/System/Threading/LockCookie.cs +++ b/src/libraries/System.Threading/src/System/Threading/LockCookie.cs @@ -9,40 +9,27 @@ namespace System.Threading /// Stores the lock state of a before its lock state is changed, such that the lock state may /// later be restored. /// - public struct LockCookie + public struct LockCookie : IEquatable { internal LockCookieFlags _flags; internal ushort _readerLevel; internal ushort _writerLevel; internal int _threadID; - public override int GetHashCode() - { - return (int)_flags + _readerLevel + _writerLevel + _threadID; - } + public override int GetHashCode() => + (int)_flags + _readerLevel + _writerLevel + _threadID; - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is LockCookie && Equals((LockCookie)obj); - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is LockCookie other && Equals(other); - public bool Equals(LockCookie obj) - { - return - _flags == obj._flags && - _readerLevel == obj._readerLevel && - _writerLevel == obj._writerLevel && - _threadID == obj._threadID; - } + public bool Equals(LockCookie obj) => + _flags == obj._flags && + _readerLevel == obj._readerLevel && + _writerLevel == obj._writerLevel && + _threadID == obj._threadID; - public static bool operator ==(LockCookie a, LockCookie b) - { - return a.Equals(b); - } + public static bool operator ==(LockCookie a, LockCookie b) => a.Equals(b); - public static bool operator !=(LockCookie a, LockCookie b) - { - return !(a == b); - } + public static bool operator !=(LockCookie a, LockCookie b) => !a.Equals(b); } } diff --git a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs index 91804388b42fa..f52ae1ffd8b91 100644 --- a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs +++ b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs @@ -202,12 +202,13 @@ protected TransactionManagerCommunicationException(System.Runtime.Serialization. public TransactionManagerCommunicationException(string? message) { } public TransactionManagerCommunicationException(string? message, System.Exception? innerException) { } } - public partial struct TransactionOptions + public partial struct TransactionOptions : System.IEquatable { - private int _dummyPrimitive; + private readonly int _dummyPrimitive; public System.Transactions.IsolationLevel IsolationLevel { get { throw null; } set { } } public System.TimeSpan Timeout { get { throw null; } set { } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Transactions.TransactionOptions other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) { throw null; } public static bool operator !=(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) { throw null; } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs index 1fa34283bb455..4ce7bb4bd1394 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs @@ -5,7 +5,7 @@ namespace System.Transactions { - public struct TransactionOptions + public struct TransactionOptions : IEquatable { private TimeSpan _timeout; private IsolationLevel _isolationLevel; @@ -26,7 +26,10 @@ public IsolationLevel IsolationLevel public override bool Equals([NotNullWhen(true)] object? obj) => obj is TransactionOptions transactionOptions && Equals(transactionOptions); - private bool Equals(TransactionOptions other) => + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(TransactionOptions other) => _timeout == other._timeout && _isolationLevel == other._isolationLevel; diff --git a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs index 64e88be64f5d0..9ef10f6f68944 100644 --- a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs +++ b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs @@ -7,15 +7,13 @@ namespace System.Web.Util { internal static class UriUtil { - private static readonly char[] s_queryFragmentSeparators = { '?', '#' }; - // Just extracts the query string and fragment from the input path by splitting on the separator characters. // Doesn't perform any validation as to whether the input represents a valid URL. // Concatenating the pieces back together will form the original input string. private static void ExtractQueryAndFragment(string input, out string path, out string? queryAndFragment) { - int queryFragmentSeparatorPos = input.IndexOfAny(s_queryFragmentSeparators); - if (queryFragmentSeparatorPos != -1) + int queryFragmentSeparatorPos = input.AsSpan().IndexOfAny('?', '#'); // query fragment separators + if (queryFragmentSeparatorPos >= 0) { path = input.Substring(0, queryFragmentSeparatorPos); queryAndFragment = input.Substring(queryFragmentSeparatorPos); diff --git a/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj b/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj index 6e587b9c50f8f..2266de2c9476d 100644 --- a/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj +++ b/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj @@ -105,4 +105,7 @@ System.Security.Cryptography.X509Certificates.X509SelectionFlag + + + diff --git a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs index a576ee8439dfe..d894d797c2f46 100644 --- a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs +++ b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs @@ -216,12 +216,12 @@ public XmlConvert() { } public static char ToChar(string s) { throw null; } [System.ObsoleteAttribute("Use XmlConvert.ToDateTime() that accepts an XmlDateTimeSerializationMode instead.")] public static System.DateTime ToDateTime(string s) { throw null; } - public static System.DateTime ToDateTime(string s, string format) { throw null; } - public static System.DateTime ToDateTime(string s, string[] formats) { throw null; } + public static System.DateTime ToDateTime(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format) { throw null; } + public static System.DateTime ToDateTime(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats) { throw null; } public static System.DateTime ToDateTime(string s, System.Xml.XmlDateTimeSerializationMode dateTimeOption) { throw null; } public static System.DateTimeOffset ToDateTimeOffset(string s) { throw null; } - public static System.DateTimeOffset ToDateTimeOffset(string s, string format) { throw null; } - public static System.DateTimeOffset ToDateTimeOffset(string s, string[] formats) { throw null; } + public static System.DateTimeOffset ToDateTimeOffset(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format) { throw null; } + public static System.DateTimeOffset ToDateTimeOffset(string s, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string[] formats) { throw null; } public static decimal ToDecimal(string s) { throw null; } public static double ToDouble(string s) { throw null; } public static System.Guid ToGuid(string s) { throw null; } @@ -236,10 +236,10 @@ public XmlConvert() { } public static string ToString(char value) { throw null; } [System.ObsoleteAttribute("Use XmlConvert.ToString() that accepts an XmlDateTimeSerializationMode instead.")] public static string ToString(System.DateTime value) { throw null; } - public static string ToString(System.DateTime value, string format) { throw null; } + public static string ToString(System.DateTime value, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format) { throw null; } public static string ToString(System.DateTime value, System.Xml.XmlDateTimeSerializationMode dateTimeOption) { throw null; } public static string ToString(System.DateTimeOffset value) { throw null; } - public static string ToString(System.DateTimeOffset value, string format) { throw null; } + public static string ToString(System.DateTimeOffset value, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat)] string format) { throw null; } public static string ToString(decimal value) { throw null; } public static string ToString(double value) { throw null; } public static string ToString(System.Guid value) { throw null; } diff --git a/src/libraries/externals.csproj b/src/libraries/externals.csproj index 969ed9603a2cd..c04d47d9f897e 100644 --- a/src/libraries/externals.csproj +++ b/src/libraries/externals.csproj @@ -9,7 +9,7 @@ true false true - true + true @@ -26,7 +26,8 @@ + AfterTargets="AfterResolveReferences" + Condition="'$(TestNativeAot)' != 'true'"> true @@ -75,7 +76,7 @@ + Condition="'$(RuntimeFlavor)' != 'Mono' and '$(TestNativeAot)' != 'true'"> diff --git a/src/libraries/illink-oob.targets b/src/libraries/illink-oob.targets index 72cecaf3b8bee..4775c20bd9301 100644 --- a/src/libraries/illink-oob.targets +++ b/src/libraries/illink-oob.targets @@ -1,63 +1,78 @@ - - - - $([MSBuild]::NormalizePath('$(ILLinkTrimAssemblyArtifactsRootDir)', 'trimmed-oobs')) + $([MSBuild]::NormalizePath('$(ILLinkTrimAssemblyArtifactsRootDir)', 'trimmed-oobs')) - + + + - <_OOBsToIgnore Include="System.CodeDom" /> - <_OOBsToIgnore Include="System.ComponentModel.Composition" /> - <_OOBsToIgnore Include="System.ComponentModel.Composition.Registration" /> - <_OOBsToIgnore Include="System.Composition.AttributedModel" /> - <_OOBsToIgnore Include="System.Composition.Convention" /> - <_OOBsToIgnore Include="System.Composition.Hosting" /> - <_OOBsToIgnore Include="System.Composition.Runtime" /> - <_OOBsToIgnore Include="System.Composition.TypedParts" /> - <_OOBsToIgnore Include="System.Configuration.ConfigurationManager" /> - <_OOBsToIgnore Include="System.Speech" /> - - <_NetCoreAppRuntimeAssemblies Include="$(NetCoreAppCurrentRuntimePath)*.dll" Exclude="$(NetCoreAppCurrentRuntimePath)*.Generator.dll;$(NetCoreAppCurrentRuntimePath)*.Native.dll;$(NetCoreAppCurrentRuntimePath)*msquic.dll" /> - <_RuntimePackTrimmedAssemblies Include="$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)*.dll" /> - - - <_NetCoreAppRuntimeAssembliesToFileName Include="@(_NetCoreAppRuntimeAssemblies -> '%(FileName)')"> - %(Identity) - - <_RuntimePackAssembliesToFileName Include="@(_RuntimePackTrimmedAssemblies -> '%(FileName)')"> - %(Identity) - - - <_OOBsToTrimFileName Include="@(_NetCoreAppRuntimeAssembliesToFileName)" Exclude="@(_RuntimePackAssembliesToFileName);@(_OOBsToIgnore)" /> - <_OOBReferencesFileName Include="@(_NetCoreAppRuntimeAssembliesToFileName)" Exclude="@(_OOBsToTrimFileName)" /> - <_OOBsToTrim Include="@(_OOBsToTrimFileName -> '%(OriginalIdentity)')" /> - <_OOBReferences Include="@(_OOBReferencesFileName -> '%(OriginalIdentity)')" /> - <_OOBReferences Include="$(SystemPrivateCoreLibPath)" /> + + + + + + + + + + + + + + + + + + + + + + + + - - <_OOBSuppressionsXmls Include="$(ILLinkTrimAssemblyOOBSuppressionsXmlsDir)*.xml" /> + + + + + + + $(ILLinkArgs) - $(OOBILLinkArgs) --link-attributes "@(_OOBSuppressionsXmls->'%(FullPath)', '" --link-attributes "')" + $(OOBILLinkArgs) --link-attributes "@(OOBLibrarySuppressionsXml->'%(FullPath)', '" --link-attributes "')" + + diff --git a/src/libraries/illink-sharedframework.targets b/src/libraries/illink-sharedframework.targets index 77be745765c44..0cc83fb1c7467 100644 --- a/src/libraries/illink-sharedframework.targets +++ b/src/libraries/illink-sharedframework.targets @@ -1,48 +1,60 @@ - - - - $([MSBuild]::NormalizePath('$(ILLinkTrimAssemblyArtifactsRootDir)', 'trimmed-runtimepack')) + $([MSBuild]::NormalizePath('$(ILLinkTrimAssemblyArtifactsRootDir)', 'trimmed-runtimepack')) + + + + + + + + + + + + + + + + + + + + + - $(ILLinkArgs) + $(ILLinkArgs) - $(RuntimePackILLinkArgs) -b true + $(SharedFrameworkILLinkArgs) -b true - <_LibrariesToTrim Include="$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)*.dll" /> - <_LibrariesToTrim Include="$(SystemPrivateCoreLibPath)" /> - - + library - - - <_RuntimePackSuppressionsXmls Include="$(ILLinkTrimAssemblyRuntimePackSuppressionsXmlsDir)*.xml" /> - - - <_RuntimePackSuppressionsXmls Include="$(CoreLibSharedDir)ILLink\ILLink.Suppressions.LibraryBuild.xml" /> - <_RuntimePackSuppressionsXmls Condition="'$(RuntimeFlavor)' == 'CoreCLR'" Include="$(CoreClrProjectRoot)System.Private.CoreLib\$(ProjectILLinkSuppressionsFile).LibraryBuild.xml" /> - - - $(RuntimePackILLinkArgs) --link-attributes "@(_RuntimePackSuppressionsXmls->'%(FullPath)', '" --link-attributes "')" + $(SharedFrameworkILLinkArgs) --link-attributes "@(SharedFrameworkSuppressionsXml->'%(FullPath)', '" --link-attributes "')" + + diff --git a/src/libraries/shims/ApiCompat.proj b/src/libraries/shims/ApiCompat.proj index 70170e5de70b7..e27786ccb1a54 100644 --- a/src/libraries/shims/ApiCompat.proj +++ b/src/libraries/shims/ApiCompat.proj @@ -1,12 +1,5 @@ - - - - - - - @@ -14,95 +7,79 @@ - - + - $(IntermediateOutputPath)apicompat.rsp - $(MSBuildThisFileDirectory)ApiCompatBaseline.netcoreapp.netfx461.txt - $(MSBuildThisFileDirectory)ApiCompatBaseline.netcoreapp.netfx461.ignore.txt $(MSBuildThisFileDirectory)ApiCompatBaseline.netcoreapp.netstandard.txt $(MSBuildThisFileDirectory)ApiCompatBaseline.netcoreapp.netstandardOnly.txt + $(MSBuildThisFileDirectory)ApiCompatBaseline.PreviousNetCoreApp.txt + $(BaseIntermediateOutputPath)marker.txt + + + + - + Inputs="@(NetCoreAppCurrentRefFile);$(ApiCompatNSBaselineFile);$(ApiCompatNSOnlyBaselineFile);$(PreviousNetCoreAppBaselineFile)" + Outputs="$(ApiCompatMarkerFile)"> - $(NetCoreAppCurrentRefPath.TrimEnd('\/')) - $(ApiCompatArgs) --exclude-attributes "$(ApiCompatExcludeAttributeList)" - $(ApiCompatArgs) --impl-dirs "$(ApiCompatImplementationDirs)" - --baseline "$(ApiCompatBaselineIgnoreFile)" + $(BaseIntermediateOutputPath)apicompat.rsp 0 + --impl-dirs "$(NetCoreAppCurrentRefPath.TrimEnd('\/'))" + $(ApiCompatArgs) --exclude-attributes "$(ApiCompatExcludeAttributeList)" - - + - - - - - - - - + - False - <_netStandardLibrary20RefPath>$([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'netstandard.library', '$(NetStandardLibraryVersion)', 'build', 'netstandard2.0', 'ref')) - <_netStandard21OnlyRef>$(NETStandard21RefPath)netstandard.dll - <_netStandard21BaselineModifer>--baseline - <_netStandard21BaselineModifer Condition="$(UpdateNETStandardBaseline)">> + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'netstandard.library', '$(NetStandardLibraryVersion)', 'build', 'netstandard2.0', 'ref')) + $(NETStandard21RefPath)netstandard.dll + --baseline + > - - - - + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.netcore.app.ref', '$(NetCoreAppLatestStablePackageBaselineVersion)', 'ref', '$(NetCoreAppLatestStable)')) - <_previousNetCoreAppBaselineFile>$(MSBuildThisFileDirectory)ApiCompatBaseline.PreviousNetCoreApp.txt - <_previousNetCoreAppBaselineParam>--baseline "$(_previousNetCoreAppBaselineFile)" - <_previousNetCoreAppBaselineParam Condition="'$(UpdatePreviousNetCoreAppBaseline)' == 'true'">> "$(_previousNetCoreAppBaselineFile)" + --baseline + > - - - - - - + + + diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index f408c36427e63..a49a465752eed 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -75,9 +75,11 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSASignaturePadding' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.SignatureDescription' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.TripleDES' in the contract but not the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System: CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System.Core: CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Aes' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.ECCurve' in the contract but not the implementation. @@ -138,4 +140,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSASignaturePadding' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.SignatureDescription' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.TripleDES' in the contract but not the implementation. -Total Issues: 132 +Compat issues with assembly System.Security.Cryptography.X509Certificates: +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +Total Issues: 135 diff --git a/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.ignore.txt b/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.ignore.txt deleted file mode 100644 index b0420059f5aae..0000000000000 --- a/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.ignore.txt +++ /dev/null @@ -1,2709 +0,0 @@ -// HttpVersion changed to static class intentionally. See here: https://github.com/dotnet/standard/issues/91 -CannotMakeTypeAbstract : Type 'System.Net.HttpVersion' is abstract in the implementation but is not abstract in the contract. -CannotSealType : Type 'System.Net.HttpVersion' is sealed in the implementation but not sealed in the contract. -MembersMustExist : Member 'System.Net.HttpVersion..ctor()' does not exist in the implementation but it does exist in the contract. - -// RuntimeEnvironment changed to static class intentionally. See here: https://github.com/dotnet/standard/commit/d5fbcbeeeb7f15102fdac111bc8d7d5d72c32036#diff-2856a41639a1f4feb4e95ae667e069b7R10012 -CannotMakeTypeAbstract : Type 'System.Runtime.InteropServices.RuntimeEnvironment' is abstract in the implementation but is not abstract in the contract. -CannotSealType : Type 'System.Runtime.InteropServices.RuntimeEnvironment' is sealed in the implementation but not sealed in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.RuntimeEnvironment..ctor()' does not exist in the implementation but it does exist in the contract. - -// Activator changed to static class intentionally. See here: https://github.com/dotnet/runtime/issues/18630 -CannotMakeTypeAbstract : Type 'System.Activator' is abstract in the implementation but is not abstract in the contract. - -// System.Drawing types changed to static intentionally. Change is source and binary compatible. https://github.com/dotnet/corefx/commit/ad215be2fa28a7d2f19a90c1ba04c50c3b677253 -CannotMakeTypeAbstract : Type 'System.Drawing.Brushes' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.Pens' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.SystemBrushes' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.SystemColors' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.SystemFonts' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.SystemIcons' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.SystemPens' is abstract in the implementation but is not abstract in the contract. -CannotMakeTypeAbstract : Type 'System.Drawing.BufferedGraphicsManager' is abstract in the implementation but is not abstract in the contract. - -// Won't came back into netcoreapp. See here: https://github.com/dotnet/runtime/issues/20974 -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.ValidationContext.ServiceContainer.get()' does not exist in the implementation but it does exist in the contract. - -// Debugger changed to static class intentionally. See here: https://github.com/dotnet/standard/commit/d5fbcbeeeb7f15102fdac111bc8d7d5d72c32036#diff-2856a41639a1f4feb4e95ae667e069b7R10012 -CannotMakeTypeAbstract : Type 'System.Diagnostics.Debugger' is abstract in the implementation but is not abstract in the contract. -MembersMustExist : Member 'System.Diagnostics.Debugger..ctor()' does not exist in the implementation but it does exist in the contract. - -// IRemotingFormatter won't be implemented in netcore20 -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter' does not implement interface 'System.Runtime.Remoting.Messaging.IRemotingFormatter' in the implementation but it does in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IRemotingFormatter' does not exist in the implementation but it does exist in the contract. - -// SchemaImporter won't be implemented in netcore20 -TypesMustExist : Type 'System.Xml.Serialization.SchemaImporter' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlSchemaImporter' does not inherit from base type 'System.Xml.Serialization.SchemaImporter' in the implementation but it does in the contract. - -// IServiceProvider won't be implemented by SqlClientFactory. See here: https://github.com/dotnet/runtime/issues/20832 -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlClient.SqlClientFactory' does not implement interface 'System.IServiceProvider' in the implementation but it does in the contract. - -// DynData Win9x only. Not going to be implemented in any netcore versions. See here: https://github.com/dotnet/runtime/issues/19972 -MembersMustExist : Member 'Microsoft.Win32.RegistryKey Microsoft.Win32.Registry.DynData' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'Microsoft.Win32.RegistryHive Microsoft.Win32.RegistryHive.DynData' does not exist in the implementation but it does exist in the contract. - -// AppDomain.SetupInformation not going to be implemented in netcore20 as no remoting support: -MembersMustExist : Member 'System.AppDomain.SetupInformation.get()' does not exist in the implementation but it does exist in the contract. - -// SetAccessControl in FileStream not going to be implemented in netcore20 as no ACL support: -MembersMustExist : Member 'System.IO.FileStream.SetAccessControl(System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract. - -// StackTrace ctor deprecated in net472 and won't be implemented in any netcoreapp versions: -MembersMustExist : Member 'System.Diagnostics.StackTrace..ctor(System.Threading.Thread, System.Boolean)' does not exist in the implementation but it does exist in the contract. - -// Dan said there is a reason for those in System.Resrouces to ignore: -MembersMustExist : Member 'System.String System.Resources.ResourceManager.BaseNameField' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Hashtable System.Resources.ResourceSet.Table' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Resources.IResourceReader System.Resources.ResourceSet.Reader' does not exist in the implementation but it does exist in the contract. - -// Thread.CurrentContext is not supported because of remoting: -MembersMustExist : Member 'System.Threading.Thread.CurrentContext.get()' does not exist in the implementation but it does exist in the contract. - -// Debug.Listeners won't be implemented in netstandard20 and netcoreapp20. See here: https://github.com/dotnet/standard/issues/84 -MembersMustExist : Member 'System.Diagnostics.Debug.Listeners.get()' does not exist in the implementation but it does exist in the contract. - -// IsolatedStorage methods won't be implemented in netstandard20 and netcoreapp20. See here: https://github.com/dotnet/runtime/issues/20970 -MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorage.GetPermission(System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorageFile.GetPermission(System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(System.IO.IsolatedStorage.IsolatedStorageScope, System.Security.Policy.Evidence, System.Type, System.Security.Policy.Evidence, System.Type)' does not exist in the implementation but it does exist in the contract. - -// Crypto types and members are sealed in netstandard and netcoreapp because they are sealed in Xamarin. https://github.com/dotnet/runtime/issues/20870 -CannotSealType : Type 'System.Security.Cryptography.SHA1Managed' is sealed in the implementation but not sealed in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract. -CannotSealType : Type 'System.Security.Cryptography.SHA256Managed' is sealed in the implementation but not sealed in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract. -CannotSealType : Type 'System.Security.Cryptography.SHA384Managed' is sealed in the implementation but not sealed in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract. -CannotSealType : Type 'System.Security.Cryptography.SHA512Managed' is sealed in the implementation but not sealed in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract. - -// Can't build WindowsIdentities or WindowsPrincipals on non-Windows OSes. https://github.com/dotnet/runtime/issues/20972 -MembersMustExist : Member 'System.Security.Principal.IdentityReferenceCollection.IsReadOnly.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity..ctor(System.Security.Principal.WindowsIdentity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity..ctor(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity.DeviceClaims.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity.Impersonate()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity.Impersonate(System.IntPtr)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsIdentity.UserClaims.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsPrincipal.DeviceClaims.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WindowsPrincipal.UserClaims.get()' does not exist in the implementation but it does exist in the contract. - -// Reflection.Emit future unclear and won't be implemented till netcoreapp20. See here: https://github.com/dotnet/runtime/issues/20971 -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.AddResourceFile(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.AddResourceFile(System.String, System.String, System.Reflection.ResourceAttributes)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineDynamicModule(System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineDynamicModule(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineDynamicModule(System.String, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineResource(System.String, System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineResource(System.String, System.String, System.String, System.Reflection.ResourceAttributes)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineUnmanagedResource(System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineUnmanagedResource(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineVersionInfoResource()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineVersionInfoResource(System.String, System.String, System.String, System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Evidence.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.PermissionSet.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Save(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Save(System.String, System.Reflection.PortableExecutableKinds, System.Reflection.ImageFileMachine)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.SetEntryPoint(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.SetEntryPoint(System.Reflection.MethodInfo, System.Reflection.Emit.PEFileKinds)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilderAccess System.Reflection.Emit.AssemblyBuilderAccess.ReflectionOnly' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilderAccess System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilderAccess System.Reflection.Emit.AssemblyBuilderAccess.Save' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.AddDeclarativeSecurity(System.Security.Permissions.SecurityAction, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.GetModule()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.GetToken()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.ReturnType.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.SetMethodBody(System.Byte[], System.Int32, System.Byte[], System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.SetSymCustomAttribute(System.String, System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ConstructorBuilder.Signature.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.EnumBuilder.CreateType()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.EnumBuilder.TypeToken.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.EventBuilder.GetEventToken()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.FieldBuilder.GetToken()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.FieldBuilder.SetMarshal(System.Reflection.Emit.UnmanagedMarshal)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ILGenerator.EmitCalli(System.Reflection.Emit.OpCode, System.Runtime.InteropServices.CallingConvention, System.Type, System.Type[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ILGenerator.MarkSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter, System.Int32, System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.AddDeclarativeSecurity(System.Security.Permissions.SecurityAction, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.CreateMethodBody(System.Byte[], System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.GetModule()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.GetToken()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetMarshal(System.Reflection.Emit.UnmanagedMarshal)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetMethodBody(System.Byte[], System.Int32, System.Byte[], System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetSymCustomAttribute(System.String, System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.Signature.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineDocument(System.String, System.Guid, System.Guid, System.Guid)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineManifestResource(System.String, System.IO.Stream, System.Reflection.ResourceAttributes)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefinePInvokeMethod(System.String, System.String, System.Reflection.MethodAttributes, System.Reflection.CallingConventions, System.Type, System.Type[], System.Runtime.InteropServices.CallingConvention, System.Runtime.InteropServices.CharSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefinePInvokeMethod(System.String, System.String, System.String, System.Reflection.MethodAttributes, System.Reflection.CallingConventions, System.Type, System.Type[], System.Runtime.InteropServices.CallingConvention, System.Runtime.InteropServices.CharSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineResource(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineResource(System.String, System.String, System.Reflection.ResourceAttributes)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineUnmanagedResource(System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.DefineUnmanagedResource(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetArrayMethodToken(System.Type, System.String, System.Reflection.CallingConventions, System.Type, System.Type[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetConstructorToken(System.Reflection.ConstructorInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetConstructorToken(System.Reflection.ConstructorInfo, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetFieldToken(System.Reflection.FieldInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetMethodToken(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetMethodToken(System.Reflection.MethodInfo, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetSignatureToken(System.Byte[], System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetSignatureToken(System.Reflection.Emit.SignatureHelper)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetSignerCertificate()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetStringConstant(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetSymWriter()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetTypeToken(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.GetTypeToken(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.IsTransient()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.SetSymCustomAttribute(System.String, System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ModuleBuilder.SetUserEntryPoint(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ParameterBuilder.GetToken()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.ParameterBuilder.SetMarshal(System.Reflection.Emit.UnmanagedMarshal)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.PropertyBuilder.PropertyToken.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.SignatureHelper.GetMethodSigHelper(System.Reflection.Module, System.Runtime.InteropServices.CallingConvention, System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.SignatureHelper.GetMethodSigHelper(System.Runtime.InteropServices.CallingConvention, System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.TypeBuilder.AddDeclarativeSecurity(System.Security.Permissions.SecurityAction, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.TypeBuilder.DefinePInvokeMethod(System.String, System.String, System.Reflection.MethodAttributes, System.Reflection.CallingConventions, System.Type, System.Type[], System.Runtime.InteropServices.CallingConvention, System.Runtime.InteropServices.CharSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.TypeBuilder.DefinePInvokeMethod(System.String, System.String, System.String, System.Reflection.MethodAttributes, System.Reflection.CallingConventions, System.Type, System.Type[], System.Runtime.InteropServices.CallingConvention, System.Runtime.InteropServices.CharSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.TypeBuilder.DefinePInvokeMethod(System.String, System.String, System.String, System.Reflection.MethodAttributes, System.Reflection.CallingConventions, System.Type, System.Type[], System.Type[], System.Type[], System.Type[][], System.Type[][], System.Runtime.InteropServices.CallingConvention, System.Runtime.InteropServices.CharSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Emit.TypeBuilder.TypeToken.get()' does not exist in the implementation but it does exist in the contract. - -// Consciously are not bringing to core -TypesMustExist : Type 'System.Security.Cryptography.CryptoAPITransform' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.HMACRIPEMD160' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.MACTripleDES' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.RijndaelManagedTransform' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.RIPEMD160' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.RIPEMD160Managed' does not exist in the implementation but it does exist in the contract. - -// Too coupled to ACLs -TypesMustExist : Type 'System.Security.AccessControl.CryptoKeyAccessRule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.AccessControl.CryptoKeyAuditRule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.AccessControl.CryptoKeyRights' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.AccessControl.CryptoKeySecurity' does not exist in the implementation but it does exist in the contract. - -// Interfaces were intentional removals -CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Markup.ValueSerializerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.DirectoryServicesCOMException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ServiceProcess.ServiceControllerPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ServiceProcess.ServiceProcessDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'Microsoft.SqlServer.Server.SqlMethodAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.RegexStringValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.RegularExpressions.RegexMatchTimeoutException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'Microsoft.SqlServer.Server.InvalidUdtException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'Microsoft.SqlServer.Server.SqlFunctionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ServiceProcess.TimeoutException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.PingException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.AccessViolationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Activator' does not implement interface 'System.Runtime.InteropServices._Activator' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.AggregateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.AppDomain' does not implement interface 'System._AppDomain' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DataMisalignedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DivideByZeroException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DllNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DuplicateWaitObjectException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.EntryPointNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Exception' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ExecutionEngineException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.FieldAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.FlagsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.FormatException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.AppDomainUnloadedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ApplicationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentNullException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentOutOfRangeException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ArithmeticException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ArrayTypeMismatchException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Attribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.AttributeUsageAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.BadImageFormatException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.CannotUnloadAppDomainException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.CLSCompliantAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ContextMarshalException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ContextStaticAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IndexOutOfRangeException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InsufficientExecutionStackException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InsufficientMemoryException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InvalidCastException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InvalidOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InvalidProgramException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InvalidTimeZoneException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.LoaderOptimizationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MemberAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MethodAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MissingFieldException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MissingMemberException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MissingMethodException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MTAThreadAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.MulticastNotSupportedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.NonSerializedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.NotFiniteNumberException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.NotImplementedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.NotSupportedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.NullReferenceException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ObjectDisposedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ObsoleteAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.OperationCanceledException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.OutOfMemoryException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.OverflowException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ParamArrayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.PlatformNotSupportedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.RankException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.SerializableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.StackOverflowException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.STAThreadAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.SystemException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ThreadStaticAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TimeoutException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Type' does not implement interface 'System.Runtime.InteropServices._Type' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TypeAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TypeInitializationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TypeLoadException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TypeUnloadedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.UnauthorizedAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Collections.Generic.KeyNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.ConditionalAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerBrowsableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerDisplayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerHiddenAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerNonUserCodeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerStepperBoundaryAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerStepThroughAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerTypeProxyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.DebuggerVisualizerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.CodeAnalysis.SuppressMessageAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractAbbreviatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractArgumentValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractClassAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractClassForAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractInvariantMethodAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractOptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.ContractVerificationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Contracts.PureAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventDataAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventFieldAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventIgnoreAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventSourceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventSourceException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.NonEventAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.CultureNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.DirectoryNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.DriveNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.EndOfStreamException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileLoadException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.IOException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.PathTooLongException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.IsolatedStorage.IsolatedStorageException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AmbiguousMatchException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Assembly' does not implement interface 'System.Runtime.InteropServices._Assembly' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyAlgorithmIdAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyCompanyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyConfigurationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyCopyrightAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyCultureAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyDefaultAliasAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyDelaySignAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyFileVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyFlagsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyInformationalVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyKeyFileAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyKeyNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyMetadataAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyName' does not implement interface 'System.Runtime.InteropServices._AssemblyName' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyProductAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblySignatureKeyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyTitleAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyTrademarkAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ConstructorInfo' does not implement interface 'System.Runtime.InteropServices._ConstructorInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.CustomAttributeFormatException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.DefaultMemberAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.EventInfo' does not implement interface 'System.Runtime.InteropServices._EventInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.FieldInfo' does not implement interface 'System.Runtime.InteropServices._FieldInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.InvalidFilterCriteriaException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MemberInfo' does not implement interface 'System.Runtime.InteropServices._MemberInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MethodBase' does not implement interface 'System.Runtime.InteropServices._MethodBase' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MethodInfo' does not implement interface 'System.Runtime.InteropServices._MethodInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Module' does not implement interface 'System.Runtime.InteropServices._Module' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ObfuscateAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ObfuscationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ParameterInfo' does not implement interface 'System.Runtime.InteropServices._ParameterInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.PropertyInfo' does not implement interface 'System.Runtime.InteropServices._PropertyInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ReflectionTypeLoadException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetInvocationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetParameterCountException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TypeDelegator' does not implement interface 'System.Runtime.InteropServices._Type' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TypeInfo' does not implement interface 'System.Runtime.InteropServices._Type' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.AssemblyBuilder' does not implement interface 'System.Runtime.InteropServices._AssemblyBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.ConstructorBuilder' does not implement interface 'System.Runtime.InteropServices._ConstructorBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.CustomAttributeBuilder' does not implement interface 'System.Runtime.InteropServices._CustomAttributeBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.DynamicMethod' does not implement interface 'System.Runtime.InteropServices._MethodInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.EventBuilder' does not implement interface 'System.Runtime.InteropServices._EventBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.FieldBuilder' does not implement interface 'System.Runtime.InteropServices._FieldBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.ILGenerator' does not implement interface 'System.Runtime.InteropServices._ILGenerator' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.LocalBuilder' does not implement interface 'System.Runtime.InteropServices._LocalBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.MethodBuilder' does not implement interface 'System.Runtime.InteropServices._MethodBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.ModuleBuilder' does not implement interface 'System.Runtime.InteropServices._ModuleBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.ParameterBuilder' does not implement interface 'System.Runtime.InteropServices._ParameterBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.PropertyBuilder' does not implement interface 'System.Runtime.InteropServices._PropertyBuilder' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.SignatureHelper' does not implement interface 'System.Runtime.InteropServices._SignatureHelper' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Resources.MissingManifestResourceException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Resources.MissingSatelliteAssemblyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Resources.NeutralResourcesLanguageAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Resources.SatelliteContractVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.AssemblyTargetedPatchBandAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.TargetedPatchingOptOutAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.AccessedThroughPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.AsyncStateMachineAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CallerFilePathAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CallerLineNumberAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CallerMemberNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CompilationRelaxationsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CompilerGlobalScopeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.CustomConstantAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DateTimeConstantAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DecimalConstantAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DefaultDependencyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DependencyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DisablePrivateReflectionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DiscardableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ExtensionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.FixedAddressValueTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.FixedBufferAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.HasCopySemanticsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.IndexerNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.InternalsVisibleToAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.IteratorStateMachineAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.IUnknownConstantAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.MethodImplAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.NativeCppClassAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ReferenceAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.RequiredAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.RuntimeCompatibilityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.RuntimeWrappedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ScopelessEnumAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.SpecialNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.StateMachineAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.StringFreezingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.SuppressIldasmAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.TypeForwardedFromAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.TypeForwardedToAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.UnsafeValueTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.ConstrainedExecution.ReliabilityContractAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.AutomationProxyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.BestFitMappingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ClassInterfaceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.CoClassAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComAliasNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComCompatibleVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComConversionLossAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComDefaultInterfaceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComEventInterfaceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.COMException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComImportAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComRegisterFunctionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComSourceInterfacesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComUnregisterFunctionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComVisibleAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultCharSetAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DispIdAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DllImportAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ExternalException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.FieldOffsetAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.GuidAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.InAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.InterfaceTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.InvalidComObjectException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.InvalidOleVariantTypeException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.LCIDConversionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.MarshalAsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.MarshalDirectiveException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.OptionalAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.OutAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.PreserveSigAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ProgIdAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.SafeArrayRankMismatchException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.SafeArrayTypeMismatchException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.SEHException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.StructLayoutAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeIdentifierAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.WindowsRuntime.DefaultInterfaceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.WindowsRuntime.InterfaceImplementedInVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArrayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.WindowsRuntime.ReturnValueNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.WindowsRuntime.WriteOnlyArrayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.OnDeserializedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.OnDeserializingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.OnSerializedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.OnSerializingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.OptionalFieldAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.SerializationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter' does not implement interface 'System.Runtime.Remoting.Messaging.IRemotingFormatter' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Versioning.ComponentGuaranteesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Versioning.ResourceConsumptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Versioning.ResourceExposureAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Versioning.TargetFrameworkAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.AllowPartiallyTrustedCallersAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.HostProtectionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityCriticalAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityRulesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecuritySafeCriticalAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityTransparentAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityTreatAsSafeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.SuppressUnmanagedCodeSecurityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.UnverifiableCodeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.VerificationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.XmlSyntaxException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.AccessControl.PrivilegeNotHeldException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.CryptographicException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.CryptographicUnexpectedOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.CodeAccessSecurityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.EnvironmentPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.FileDialogPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.FileIOPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.GacIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.HostProtectionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.IsolatedStorageFilePermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.IsolatedStoragePermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.KeyContainerPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.PermissionSetAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.PrincipalPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.PublisherIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.ReflectionPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.RegistryPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.SecurityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.SecurityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.SiteIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.StrongNameIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.UIPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.UrlIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.ZoneIdentityPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Policy.PolicyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Principal.IdentityNotMappedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.DecoderFallbackException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.EncoderFallbackException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.AbandonedMutexException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.LockRecursionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.SemaphoreFullException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.SynchronizationLockException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Thread' does not implement interface 'System.Runtime.InteropServices._Thread' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadAbortException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadInterruptedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadStartException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadStateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.WaitHandleCannotBeOpenedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.TaskCanceledException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.TaskSchedulerException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.UriFormatException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.CodeDom.Compiler.GeneratedCodeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.AmbientValueAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.AttributeProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.BindableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.BrowsableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.CategoryAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ComplexBindingPropertiesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataObjectAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataObjectFieldAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataObjectMethodAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DefaultBindingPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DefaultEventAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DefaultPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DefaultValueAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DesignerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DesignerCategoryAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DesignerSerializationVisibilityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DesignOnlyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DesignTimeVisibleAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DisplayNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.EditorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.EditorBrowsableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ExtenderProvidedPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ImmutableObjectAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.InheritanceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.InitializationEventAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.InstallerTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.InvalidAsynchronousStateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.InvalidEnumArgumentException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.LicenseException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.LicenseProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ListBindableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.LocalizableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.LookupBindingPropertiesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.MergablePropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.NotifyParentPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ParenthesizePropertyNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.PasswordPropertyTextAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.PropertyTabAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ProvidePropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ReadOnlyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.RecommendedAsConfigurableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.RefreshPropertiesAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.RunInstallerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.SettingsBindableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ToolboxItemAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.ToolboxItemFilterAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.TypeConverterAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.TypeDescriptionProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.WarningException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Win32Exception' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Design.CheckoutException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Design.HelpKeywordAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Design.Serialization.DefaultSerializationProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Design.Serialization.DesignerSerializerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.Design.Serialization.RootDesignerSerializerAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ApplicationScopedSettingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ConfigurationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.DefaultSettingValueAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.NoSettingsVersionUpgradeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsGroupDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsGroupNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsManageabilityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsPropertyIsReadOnlyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsPropertyNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsPropertyWrongTypeException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SettingsSerializeAsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SpecialSettingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.UserScopedSettingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.MonitoringDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.SwitchAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.SwitchLevelAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.InternalBufferOverflowException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.InvalidDataException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.CookieException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.HttpListenerException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.ProtocolViolationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.WebException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Mail.SmtpException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Mail.SmtpFailedRecipientException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Mail.SmtpFailedRecipientsException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.NetworkInformationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Sockets.SocketException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.WebSockets.WebSocketException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultParameterValueAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Authentication.AuthenticationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Authentication.InvalidCredentialException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.StorePermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.TypeDescriptorPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.BarrierPostPhaseException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.SemaphoreFullException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Timers.TimersDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.AssociationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.CompareAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.ConcurrencyCheckAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.CreditCardAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.CustomValidationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.DataTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.DisplayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.DisplayColumnAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.DisplayFormatAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.EditableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.EmailAddressAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.EnumDataTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.FileExtensionsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.FilterUIHintAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.KeyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.MaxLengthAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.MinLengthAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.PhoneAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.RangeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.RegularExpressionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.RequiredAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.ScaffoldColumnAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.StringLengthAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.TimestampAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.UIHintAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.UrlAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.ValidationAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.ValidationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.ColumnAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.ComplexTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.InversePropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.ComponentModel.DataAnnotations.Schema.TableAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.InvalidTimeZoneException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.DynamicAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ExtensionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComAwareEventInfo' does not implement interface 'System.Runtime.InteropServices._EventInfo' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.LockRecursionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.ConstraintException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.DataException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.DataSysDescriptionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.DBConcurrencyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.DeletedRowInaccessibleException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.DuplicateNameException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.EvaluateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.InRowChangingEventException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.InvalidConstraintException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.InvalidExpressionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.MissingPrimaryKeyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.NoNullAllowedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.OperationAbortedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.ReadOnlyException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.RowNotInTableException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.StrongTypingException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SyntaxErrorException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.VersionNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.Common.DbException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.Common.DbProviderSpecificTypePropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.Common.DBDataPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.Odbc.OdbcException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlClient.SqlException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlTypes.SqlAlreadyFilledException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlTypes.SqlNotFilledException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlTypes.SqlNullValueException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlTypes.SqlTruncateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlTypes.SqlTypeException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.CookieException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.WebException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Sockets.SocketException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.CollectionDataContractAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.ContractNamespaceAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.DataContractAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.DataMemberAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.EnumMemberAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.IgnoreDataMemberAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.InvalidDataContractException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.KnownTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.TransactionAbortedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.TransactionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.TransactionInDoubtException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.TransactionManagerCommunicationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.TransactionPromotionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.XmlException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Schema.XmlSchemaException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Schema.XmlSchemaInferenceException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Schema.XmlSchemaValidationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapElementAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapEnumAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapIgnoreAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapIncludeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.SoapTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAnyAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAnyElementAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlArrayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlArrayItemAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlChoiceIdentifierAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlElementAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlEnumAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlIgnoreAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlIncludeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlNamespaceDeclarationsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlRootAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlSchemaProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlSerializerAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlSerializerVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlTextAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.XPath.XPathException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Xsl.XsltCompileException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Xsl.XsltException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAnyAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAnyElementAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlArrayAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlArrayItemAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlAttributeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlChoiceIdentifierAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlElementAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlEnumAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlIgnoreAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlIncludeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlNamespaceDeclarationsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlRootAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlSchemaProviderAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlTextAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Serialization.XmlTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ImportedFromTypeLibAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeLibFuncAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeLibImportClassAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeLibTypeAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeLibVarAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.TypeLibVersionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.PerformanceCounterPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.EventLogPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.DnsPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.SocketPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.WebPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Mail.SmtpPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.NetworkInformationPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.Odbc.OdbcPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Printing.PrintingPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.PeerToPeer.PnrpPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.PeerToPeer.Collaboration.PeerCollaborationPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Transactions.DistributedTransactionPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlClient.SqlClientPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.CallbackValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ConfigurationCollectionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ConfigurationErrorsException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ConfigurationPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.ConfigurationValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.IntegerValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.LongValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.PositiveTimeSpanValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.StringValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.SubclassTypeValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.TimeSpanValidatorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Configuration.Provider.ProviderException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.BitmapSuffixInSameAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.BitmapSuffixInSatelliteAssemblyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.ToolboxBitmapAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Printing.InvalidPrinterException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileFormatException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.ActiveDirectoryServerDownException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.ForestTrustCollisionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.ActiveDirectory.SyncFromAllServersOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.DirectoryObjectClassAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.DirectoryPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.DirectoryRdnPrefixAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.MultipleMatchesException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.NoMatchingPrincipalException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.PasswordException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.PrincipalException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.PrincipalExistsException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.PrincipalOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.AccountManagement.PrincipalServerDownException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.Protocols.BerConversionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.Protocols.DirectoryException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.Protocols.DirectoryOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.Protocols.LdapException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.DirectoryServices.Protocols.TlsOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract. - - - -// Types we currently don't plan to port: -TypesMustExist : Type 'System._AppDomain' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ActivationContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.AppDomainInitializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.AppDomainManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.AppDomainManagerInitializationOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.AppDomainSetup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.CrossAppDomainDelegate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IAppDomainSetup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Deployment.Internal.InternalActivationContextHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Deployment.Internal.InternalApplicationIdentityHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Contracts.Internal.ContractHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.DesignerServices.WindowsRuntimeDesignerContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Hosting.ActivationArguments' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Hosting.ApplicationActivator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Activator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Assembly' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._AssemblyBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._AssemblyName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Attribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ConstructorBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ConstructorInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._CustomAttributeBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._EnumBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._EventBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._EventInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Exception' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._FieldBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._FieldInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ILGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._LocalBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._MemberInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._MethodBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._MethodBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._MethodInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._MethodRental' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Module' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ModuleBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ParameterBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._ParameterInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._PropertyBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._PropertyInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._SignatureHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Thread' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._Type' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices._TypeBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.AssemblyRegistrationFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.BIND_OPTS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.BINDPTR' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.CALLCONV' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.CONNECTDATA' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.DESCKIND' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.DISPPARAMS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ELEMDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.EXCEPINFO' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ExporterEventKind' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ExtensibleClassFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.FILETIME' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.FUNCDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.FUNCFLAGS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.FUNCKIND' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IDLDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IDLFLAG' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IMPLTYPEFLAGS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ImporterEventKind' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.INVOKEKIND' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.IRegistrationServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibExporterNameProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibExporterNotifySink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibImporterNotifySink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.LIBFLAGS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ObjectCreationDelegate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.PARAMDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.PARAMFLAG' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationClassContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationConnectionType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.STATSTG' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.SYSKIND' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TYPEATTR' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TYPEDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TYPEFLAGS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TYPEKIND' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TYPELIBATTR' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibExporterFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibImporterFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIBindCtx' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIConnectionPoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIConnectionPointContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIEnumConnectionPoints' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIEnumConnections' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIEnumMoniker' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIEnumString' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIEnumVARIANT' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIMoniker' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIPersistFile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIRunningObjectTable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMIStream' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMITypeComp' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMITypeInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.UCOMITypeLib' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.VARDESC' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.VARFLAGS' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.Expando.IExpando' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.WindowsRuntime.DesignerNamespaceResolveEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.WindowsRuntime.NamespaceResolveEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.ActivatedClientTypeEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.ActivatedServiceTypeEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.CustomErrorsModes' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.IChannelInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.IEnvoyInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.InternalRemotingServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.IObjectHandle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.IRemotingTypeInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.ObjectHandle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.ObjRef' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.RemotingConfiguration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.RemotingException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.RemotingServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.RemotingTimeoutException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.ServerException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.SoapServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.TypeEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.WellKnownClientTypeEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.WellKnownObjectMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.WellKnownServiceTypeEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Activation.ActivatorLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Activation.IActivator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Activation.IConstructionCallMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Activation.IConstructionReturnMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Activation.UrlAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.BaseChannelObjectWithProperties' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.BaseChannelSinkWithProperties' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.BaseChannelWithProperties' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ChannelDataStore' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ChannelServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ClientChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannelDataStore' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannelReceiver' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannelReceiverHook' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannelSender' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IChannelSinkBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientChannelSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientChannelSinkProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientFormatterSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientFormatterSinkProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IClientResponseChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ISecurableChannel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IServerChannelSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IServerChannelSinkProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IServerChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IServerFormatterSinkProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ITransportHeaders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ServerChannelSinkStack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.ServerProcessing' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.SinkProviderData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Channels.TransportHeaders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.Context' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.ContextAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.ContextProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.CrossContextDelegate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContextAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContextProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContextPropertyActivator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContributeClientContextSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContributeDynamicSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContributeEnvoySink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContributeObjectSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IContributeServerContextSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IDynamicMessageSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.IDynamicProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Contexts.SynchronizationAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Lifetime.ClientSponsor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Lifetime.ILease' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Lifetime.ISponsor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Lifetime.LeaseState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Lifetime.LifetimeServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.AsyncResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.CallContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.ConstructionCall' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.ConstructionResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.Header' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.HeaderHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.ILogicalThreadAffinative' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMessageCtrl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMessageSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMethodCallMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMethodMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.IMethodReturnMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.InternalMessageWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.LogicalCallContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.MessageSurrogateFilter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.MethodCall' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.MethodCallMessageWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.MethodResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.MethodReturnMessageWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.OneWayAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.RemotingSurrogateSelector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Messaging.ReturnMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapFieldAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapMethodAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapOption' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapParameterAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.SoapTypeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.XmlFieldOrderOption' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.ISoapXsd' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapAnyUri' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapBase64Binary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDateTime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDay' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDuration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapEntities' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapEntity' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapId' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapIdref' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapIdrefs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapInteger' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapLanguage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapMonth' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapMonthDay' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNcName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNegativeInteger' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNmtoken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNmtokens' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNonNegativeInteger' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNonPositiveInteger' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNormalizedString' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapNotation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapPositiveInteger' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapQName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapTime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapYear' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Metadata.W3cXsd2001.SoapYearMonth' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Proxies.ProxyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Proxies.RealProxy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Services.EnterpriseServicesHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Services.ITrackingHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Remoting.Services.TrackingServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.ReadOnlyPermissionSet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.Win32.IntranetZoneCredentialPolicy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Media.SoundPlayer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Media.SystemSound' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Media.SystemSounds' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Web: -TypesMustExist : Type 'System.Web.ApplicationShutdownReason' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.BeginEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.DefaultHttpHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.EndEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.EventHandlerTaskAsyncHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HtmlString' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpApplication' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpApplicationState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpApplicationStateBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpApplicationStateWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpBrowserCapabilities' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpBrowserCapabilitiesBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpBrowserCapabilitiesWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheability' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCachePolicy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCachePolicyBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCachePolicyWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheRevalidation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheValidateHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheVaryByContentEncodings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheVaryByHeaders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCacheVaryByParams' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpClientCertificate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCompileException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpContextBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpContextWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCookie' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCookieCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpCookieMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpFileCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpFileCollectionBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpFileCollectionWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpModuleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpParseException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpPostedFile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpPostedFileBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpPostedFileWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpRequest' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpRequestBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpRequestValidationException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpRequestWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpResponseBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpResponseSubstitutionCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpResponseWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpRuntime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpServerUtility' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpServerUtilityBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpServerUtilityWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpSessionStateBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpSessionStateWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpStaticObjectsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpStaticObjectsCollectionBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpStaticObjectsCollectionWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpTaskAsyncHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpUnhandledException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpValidationStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpWorkerRequest' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.HttpWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IHtmlString' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IHttpAsyncHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IHttpHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IHttpHandlerFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IHttpModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IisTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.IPartitionResolver' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ISubscriptionToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ITlsTokenBindingInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.MimeMapping' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ParserError' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ParserErrorCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.PreApplicationStartMethodAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ProcessInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ProcessModelInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ProcessShutdownReason' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ProcessStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ReadEntityBodyMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.RequestNotification' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.RequestNotificationStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMap' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapNode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapNodeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapResolveEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SiteMapResolveEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.StaticSiteMapProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TaskEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TraceContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TraceContextEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TraceContextEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TraceContextRecord' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.TraceMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UnvalidatedRequestValues' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UnvalidatedRequestValuesBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UnvalidatedRequestValuesWrapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.VirtualPathUtility' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.WebPageTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.XmlSiteMapProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.AggregateCacheDependency' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.Cache' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheDependency' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheItemPriority' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheItemRemovedCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheItemRemovedReason' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheItemUpdateCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.CacheItemUpdateReason' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.DatabaseNotEnabledForNotificationException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.FileResponseElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.HeaderElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.IOutputCacheEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.MemoryResponseElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.OutputCache' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.OutputCacheProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.OutputCacheProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.ResponseElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.SqlCacheDependency' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.SqlCacheDependencyAdmin' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.SubstitutionResponseElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Caching.TableNotEnabledForNotificationException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.AppSettingsExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.AssemblyBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildDependencySet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildManagerHostUnloadEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildManagerHostUnloadEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildProviderAppliesTo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildProviderAppliesToAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.BuildProviderResultFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ClientBuildManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ClientBuildManagerCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ClientBuildManagerParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.CompilerType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ConnectionStringsExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ControlBuilderInterceptor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.DesignTimeResourceProviderFactoryAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ExpressionBuilderContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ExpressionEditorAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ExpressionPrefixAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.FolderLevelBuildProviderAppliesTo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.FolderLevelBuildProviderAppliesToAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.IAssemblyPostProcessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.IImplicitResourceProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ImplicitResourceKey' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.IResourceProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.LinePragmaCodeInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.PrecompilationFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ResourceExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ResourceExpressionFields' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.ResourceProviderFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.RouteUrlExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Compilation.RouteValueExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AdapterDictionary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AnonymousIdentificationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AssemblyCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AssemblyInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AsyncPreloadModeFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthenticationMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthenticationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthorizationRule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthorizationRuleAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthorizationRuleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.AuthorizationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BrowserCapabilitiesCodeGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BrowserCapabilitiesFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BrowserCapabilitiesFactoryBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BufferModesCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BufferModeSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BuildProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.BuildProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CacheSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ClientTarget' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ClientTargetCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ClientTargetSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CodeSubDirectoriesCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CodeSubDirectory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CompilationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.Compiler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CompilerCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CustomError' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CustomErrorCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CustomErrorsMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CustomErrorsRedirectMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.CustomErrorsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.DeploymentSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.EventMappingSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.EventMappingSettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ExpressionBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ExpressionBuilderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FcnMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FolderLevelBuildProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FolderLevelBuildProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsAuthenticationConfiguration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsAuthenticationCredentials' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsAuthenticationUser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsAuthenticationUserCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsAuthPasswordFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FormsProtectionEnum' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FullTrustAssembliesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FullTrustAssembly' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.FullTrustAssemblyCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.GlobalizationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HealthMonitoringSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HostingEnvironmentSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpCapabilitiesBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpCapabilitiesDefaultProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpCapabilitiesProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpCapabilitiesSectionHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpConfigurationContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpCookiesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpHandlerAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpHandlerActionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpHandlersSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpModuleAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpModuleActionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpModulesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.HttpRuntimeSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IConfigMapPath' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IConfigMapPathFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IdentitySection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IgnoreDeviceFilterElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IgnoreDeviceFilterElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.IRemoteWebConfigurationHostServer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.LowerCaseStringConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.MachineKeyCompatibilityMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.MachineKeySection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.MachineKeyValidation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.MachineKeyValidationConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.MembershipSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.NamespaceCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.NamespaceInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.OutputCacheProfile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.OutputCacheProfileCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.OutputCacheSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.OutputCacheSettingsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PagesEnableSessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PagesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PartialTrustVisibleAssembliesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PartialTrustVisibleAssembly' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PartialTrustVisibleAssemblyCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.PassportAuthentication' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProcessModelComAuthenticationLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProcessModelComImpersonationLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProcessModelLogLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProcessModelSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileGroupSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileGroupSettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileGuidedOptimizationsFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfilePropertySettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfilePropertySettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProfileSettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProtocolCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProtocolElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProtocolsConfigurationHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProtocolsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.ProvidersHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RegexWorker' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RemoteWebConfigurationHostServer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RoleManagerSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RootProfilePropertySettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RuleSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.RuleSettingsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SecurityPolicySection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SerializationMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SessionPageStateSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SessionStateSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SiteMapSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SqlCacheDependencyDatabase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SqlCacheDependencyDatabaseCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SqlCacheDependencySection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SystemWebCachingSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.SystemWebSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TagMapCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TagMapInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TagPrefixCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TagPrefixInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TicketCompatibilityMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TraceDisplayMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TraceSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TransformerInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TransformerInfoCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TrustLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TrustLevelCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.TrustSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.UrlMapping' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.UrlMappingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.UrlMappingsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.UserMapPath' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.VirtualDirectoryMapping' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.VirtualDirectoryMappingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebApplicationLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebConfigurationFileMap' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebConfigurationManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebControlsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebPartsPersonalization' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebPartsPersonalizationAuthorization' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.WebPartsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.XhtmlConformanceMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.XhtmlConformanceSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Configuration.Internal.IInternalConfigWebHost' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Handlers.AssemblyResourceLoader' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Handlers.TraceHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.AppDomainFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.AppDomainInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.AppDomainInfoEnum' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.AppDomainProtocolHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ApplicationHost' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ApplicationInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ApplicationManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.AppManagerAppDomainFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.HostingEnvironment' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.HostSecurityPolicyResolver' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.HostSecurityPolicyResults' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IAdphManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IAppDomainFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IAppDomainInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IAppDomainInfoEnum' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IApplicationHost' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IApplicationPreloadManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IApplicationPreloadUtil' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IAppManagerAppDomainFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IISAPIRuntime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IListenerChannelCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IPphManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessHost' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessHostFactoryHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessHostIdleAndHealthCheck' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessHostPreloadClient' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessHostSupportFunctions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IProcessPingCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IRegisteredObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ISAPIRuntime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.IStopListeningRegisteredObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ISuspendibleRegisteredObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ProcessHost' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ProcessHostFactoryHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.ProcessProtocolHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.SimpleWorkerRequest' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.VirtualDirectory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.VirtualFile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.VirtualFileBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Hosting.VirtualPathProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Instrumentation.PageExecutionContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Instrumentation.PageExecutionListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Instrumentation.PageInstrumentationService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.MailAttachment' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.MailEncoding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.MailFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.MailMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.MailPriority' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Mail.SmtpMail' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.BufferedWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.EventLogWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.EventNotificationType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.IisTraceWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.IRegiisUtility' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.IWebEventCustomEvaluator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.MailEventNotificationInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.MailWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.RegiisUtility' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.RuleFiringRecord' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SessionStateType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SimpleMailWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SqlExecutionException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SqlFeatures' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SqlServices' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.SqlWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.TemplatedMailWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.TraceWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebApplicationInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebApplicationLifetimeEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebAuthenticationFailureAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebAuthenticationSuccessAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebBaseErrorEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebBaseEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebBaseEventCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebErrorEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebEventBufferFlushInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebEventCodes' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebEventFormatter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebFailureAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebHeartbeatEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebManagementEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebProcessInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebProcessStatistics' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebRequestErrorEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebRequestEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebRequestInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebSuccessAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebThreadInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WebViewStateFailureAuditEvent' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Management.WmiWebEventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ArrayModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ArrayModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.AssociatedMetadataProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.AssociatedValidatorProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.BinaryDataModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.BindingBehavior' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.BindingBehaviorAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.BindNeverAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.BindRequiredAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.CollectionModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.CollectionModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ComplexModel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ComplexModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ComplexModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ComplexModelResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ControlAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ControlValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.CookieAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.CookieValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelMetadataProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelValidationFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsModelValidatorProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DataAnnotationsValidatableObjectAdapterFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DefaultModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DictionaryModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DictionaryModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.DictionaryValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.EmptyModelMetadataProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ExtensibleModelBinderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.FormAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.FormValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.GenericModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IMetadataAware' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IModelNameProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IUnvalidatedValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IUnvalidatedValueProviderSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.IValueProviderSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.KeyValuePairModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.KeyValuePairModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderDictionary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderErrorMessageProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderErrorMessageProviders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderProviderOptionsAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinderProviders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBinders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBindingContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelBindingExecutionContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelError' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelErrorCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelMetadataProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelMetadataProviders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelStateDictionary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidatingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidationNode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidationResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidatorProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidatorProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ModelValidatorProviders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.MutableObjectModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.MutableObjectModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.NameValueCollectionValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ProfileAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ProfileValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.QueryStringAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.QueryStringValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.RangeAttributeAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.RegularExpressionAttributeAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.RequiredAttributeAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.RouteDataAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.RouteDataValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.SessionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.SimpleModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.SimpleValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.StringLengthAttributeAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.TypeConverterModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.TypeConverterModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.TypeMatchModelBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.TypeMatchModelBinderProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.UserProfileAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.UserProfileValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ValidatableObjectAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ValueProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ValueProviderResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ValueProviderSourceAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ViewStateAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.ModelBinding.ViewStateValueProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.CustomProviderDataAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.DefaultProfile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileAuthenticationOption' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileAutoSaveEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileAutoSaveEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileGroupBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileInfoCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileMigrateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileMigrateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileProviderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.ProfileProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.SettingsAllowAnonymousAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Profile.SqlProfileProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.HttpMethodConstraint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.IRouteConstraint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.IRouteHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.PageRouteHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RequestContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.Route' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteTable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.RouteValueDictionary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.StopRoutingHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.UrlRoutingHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.UrlRoutingModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Routing.VirtualPathData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.ActiveDirectoryConnectionProtection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.ActiveDirectoryMembershipProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.ActiveDirectoryMembershipUser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AnonymousIdentificationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AnonymousIdentificationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AnonymousIdentificationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AuthorizationStoreRoleProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.CookieProtection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.DefaultAuthenticationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.DefaultAuthenticationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.DefaultAuthenticationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FileAuthorizationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsAuthentication' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsAuthenticationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsAuthenticationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsAuthenticationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsAuthenticationTicket' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.FormsIdentity' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.MachineKey' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.MachineKeyProtection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.Membership' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.MembershipPasswordAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.PassportAuthenticationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.PassportAuthenticationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.PassportAuthenticationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.PassportIdentity' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.PassportPrincipal' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.RoleManagerEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.RoleManagerEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.RoleManagerModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.RolePrincipal' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.RoleProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.Roles' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.SqlMembershipProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.SqlRoleProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.UrlAuthorizationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.WindowsAuthenticationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.WindowsAuthenticationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.WindowsAuthenticationModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.WindowsTokenRoleProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.AntiXssEncoder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.LowerCodeCharts' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.LowerMidCodeCharts' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.MidCodeCharts' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.UpperCodeCharts' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Security.AntiXss.UpperMidCodeCharts' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.HttpSessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.HttpSessionStateContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.IHttpSessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.IPartialSessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.IReadOnlySessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.IRequiresSessionState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.ISessionIDManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.ISessionStateItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.IStateRuntime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionIDManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateActions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateBehavior' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateItemExpireCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateModule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateStoreData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateStoreProviderBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.SessionStateUtility' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.SessionState.StateRuntime' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.AttributeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BaseParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BasePartialCachingControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BaseTemplateParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BindableTemplateBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BoundPropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BuilderPropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BuildMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.BuildTemplateMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ChtmlTextWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ClientIDMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ClientScriptManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CodeBlockType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CodeConstructType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CodeStatementBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CompilationMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CompiledBindableTemplateBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CompiledTemplateBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ComplexPropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ConflictOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ConstructorNeedsTagAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Control' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlBuilderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlCachePolicy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlSkin' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlSkinDelegate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ControlValuePropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CssClassPropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.CssStyleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataBindingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataBindingHandlerAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataBoundLiteralControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataKeyPropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceCacheDurationConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceCacheExpiry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceCapabilities' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceOperation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceSelectArguments' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceViewOperationCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DataSourceViewSelectCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DesignerDataBoundLiteralControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DesignTimeParseData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.DesignTimeTemplateParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.EmptyControlCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.EventEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ExpressionBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ExpressionBindingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ExtractTemplateValuesMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.FileLevelControlBuilderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.FileLevelMasterPageControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.FileLevelPageControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.FileLevelUserControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.FilterableAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HiddenFieldPageStatePersister' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HierarchicalDataSourceControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HierarchicalDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Html32TextWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlTextWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlTextWriterAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlTextWriterStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlTextWriterTag' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IAttributeAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IAutoFieldGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IBindableControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IBindableTemplate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ICallbackEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ICheckBoxControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ICodeBlockTypeAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IControlBuilderAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IControlDesignerAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDataBindingsAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDataItemContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDataKeysControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDataSourceViewSchemaAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IDReferencePropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IEditableTextControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IExpressionsAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IFilterResolutionService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IHierarchicalDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IHierarchicalEnumerable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IHierarchyData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ImageClickEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ImageClickEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.INamingContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.INavigateUIData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IndexedString' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IParserAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IPostBackDataHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IPostBackEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IResourceUrlGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IStateFormatter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IStateManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IStyleSheet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ITemplate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ITextControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IThemeResolutionService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IUrlResolutionService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IUserControlDesignerAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IUserControlTypeResolutionService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.IValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ListSourceHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.LiteralControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.LosFormatter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.MasterPage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.MasterPageControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.NonVisualControlAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ObjectConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ObjectPersistData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ObjectStateFormatter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ObjectTagBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.OutputCacheLocation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.OutputCacheParameters' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Page' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageAsyncTask' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageHandlerFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageParserFilter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageStatePersister' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PageTheme' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Pair' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ParseChildrenAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ParseRecorder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PartialCachingAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PartialCachingControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PersistChildrenAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PersistenceMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PersistenceModeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PostBackOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PropertyConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.PropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.RenderMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.RenderTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.RootBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.SessionPageStatePersister' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.SimplePropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.SimpleWebHandlerParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.SkinBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.StateBag' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.StateItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.StateManagedCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.StaticPartialCachingControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.SupportsEventValidationAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TagPrefixAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateContainerAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateControlParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateInstance' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateInstanceAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplateParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.TemplatePropertyEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ThemeableAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ThemeProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ToolboxDataAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Triplet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.UnobtrusiveValidationMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.UrlPropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.UserControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.UserControlControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ValidateRequestMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ValidationPropertyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ValidationSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ValidatorCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.VerificationAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.VerificationConditionalOperator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.VerificationReportLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.VerificationRule' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ViewStateEncryptionMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ViewStateException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ViewStateMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.ViewStateModeByIdAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.VirtualReferenceType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebResourceAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebServiceParser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.XhtmlMobileDocType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.XhtmlTextWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.XPathBinder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Adapters.ControlAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.Adapters.PageAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlAnchor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlArea' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlAudio' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlContainerControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlEmbed' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlEmptyTagControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlForm' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlGenericControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlHead' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlHeadBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlIframe' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlImage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputCheckBox' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputFile' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputGenericControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputHidden' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputImage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputPassword' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputRadioButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputReset' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputSubmit' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlInputText' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlLink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlMeta' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlSelect' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlSelectBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTableCell' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTableCellCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTableRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTableRowCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTextArea' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTitle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlTrack' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.HtmlControls.HtmlVideo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AccessDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AccessDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AdCreatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AdCreatedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AdRotator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AssociatedControlConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AuthenticateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AuthenticateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AutoCompleteType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AutoFieldsGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AutoGeneratedField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.AutoGeneratedFieldProperties' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BaseCompareValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BaseDataBoundControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BaseDataList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BaseValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BorderStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BoundColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BoundField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BulletedList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BulletedListDisplayMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BulletedListEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BulletedListEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.BulletStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Button' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ButtonColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ButtonColumnType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ButtonField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ButtonFieldBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ButtonType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Calendar' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CalendarDay' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CalendarSelectionMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CallingDataMethodsEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CallingDataMethodsEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ChangePassword' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CheckBox' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CheckBoxField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CheckBoxList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CircleHotSpot' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CommandField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CompareValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CompleteWizardStep' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CompositeControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CompositeDataBoundControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Content' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ContentDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ContentPlaceHolder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ControlIDConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ControlParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ControlPropertyNameConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CookieParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreateUserErrorEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreateUserErrorEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreateUserWizard' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreateUserWizardStep' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreatingModelDataSourceEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CreatingModelDataSourceEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.CustomValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataBoundControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataBoundControlMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlCellType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlCommands' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlFieldCell' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlFieldCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlFieldHeaderCell' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlRowState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataControlRowType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGrid' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridColumnCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridItemEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridItemEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridPageChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridPageChangedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridPagerStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridSortCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataGridSortCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataKey' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataKeyArray' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataKeyCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListItemEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataListItemEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DayNameFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DayRenderEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DayRenderEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewDeletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewDeletedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewDeleteEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewDeleteEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewInsertedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewInsertedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewInsertEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewInsertEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewModeEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewModeEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewPageEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewPageEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewPagerRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewRowCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewRowsGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewUpdatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewUpdatedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewUpdateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DetailsViewUpdateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.DropDownList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.EditCommandColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.EmbeddedMailObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.EmbeddedMailObjectsCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FileUpload' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FirstDayOfWeek' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FontInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FontNamesConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FontSize' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FontUnit' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FontUnitConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewDeletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewDeletedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewDeleteEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewDeleteEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewInsertedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewInsertedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewInsertEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewInsertEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewModeEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewModeEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewPageEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewPageEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewPagerRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewUpdatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewUpdatedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewUpdateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.FormViewUpdateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridLines' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewCancelEditEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewCancelEditEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewColumnsGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewDeletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewDeletedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewDeleteEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewDeleteEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewEditEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewEditEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewPageEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewPageEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewRowCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewRowEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewRowEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewSelectEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewSelectEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewSortEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewSortEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewUpdatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewUpdatedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewUpdateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.GridViewUpdateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HiddenField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HierarchicalDataBoundControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HorizontalAlign' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HotSpot' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HotSpotCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HotSpotMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HyperLink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HyperLinkColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HyperLinkControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.HyperLinkField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IButtonControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ICallbackContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ICompositeControlDesignerAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IDataBoundControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IDataBoundItemControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IDataBoundListControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IFieldControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Image' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageAlign' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageMap' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageMapEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ImageMapEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IPersistedSelector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IPostBackContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.IRepeatInfoUser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Label' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LabelControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LinkButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LinkButtonControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListBox' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListItemControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListItemType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ListSelectionMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Literal' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LiteralControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LiteralMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Localize' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Login' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginCancelEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginCancelEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginFailureAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginTextLayout' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LoginView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.LogoutAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MailDefinition' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MailMessageEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MailMessageEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Menu' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemBindingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemStyleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuItemTemplateContainer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MenuRenderingMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelDataMethodResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelDataSourceMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelErrorMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ModelMethodContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MonthChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MonthChangedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MultiView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.MultiViewControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.NextPrevFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceDisposingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceDisposingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceFilteringEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceFilteringEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceMethodEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceMethodEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceObjectEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceSelectingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceStatusEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ObjectDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Orientation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PagedDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PagerButtons' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PagerMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PagerPosition' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PagerSettings' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Panel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PanelStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Parameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ParameterCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ParsingCulture' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PasswordRecovery' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PathDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PlaceHolder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PlaceHolderControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.PolygonHotSpot' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ProfileParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.QueryExtensions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.QueryStringParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RadioButton' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RadioButtonList' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RangeValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RectangleHotSpot' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RegularExpressionValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeatDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Repeater' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterItemEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeaterItemEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeatInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RepeatLayout' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RequiredFieldValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RoleGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RoleGroupCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.RouteParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ScrollBars' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SelectedDatesCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SelectResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SendMailErrorEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SendMailErrorEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ServerValidateEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ServerValidateEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SessionParameter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapHierarchicalDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapNodeItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapNodeItemEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapNodeItemEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapNodeItemType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SiteMapPath' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SortDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceCommandEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceCommandEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceCommandType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceFilteringEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceFilteringEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceSelectingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceStatusEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceStatusEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SqlDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.StringArrayConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Style' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.StyleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SubMenuStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.SubMenuStyleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Substitution' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Table' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableCaptionAlign' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableCell' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableCellCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableCellControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableFooterRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableHeaderCell' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableHeaderRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableHeaderScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableItemStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableRowCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableRowSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableSectionStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TableStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TargetConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TemplateColumn' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TemplatedWizardStep' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TemplateField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TextAlign' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TextBox' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TextBoxControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TextBoxMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TitleFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeBindingCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeSelectAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeStyleCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeNodeTypes' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.TreeViewImageSet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Unit' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.UnitConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.UnitType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidatedControlConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidationCompareOperator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidationDataType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidationSummary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidationSummaryDisplayMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ValidatorDisplay' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.VerticalAlign' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.View' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.ViewCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebColorConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Wizard' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardNavigationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardNavigationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardStep' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardStepBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardStepCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardStepControlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WizardStepType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Xml' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.XmlBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.XmlDataSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.XmlDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.XmlHierarchicalDataSourceView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Adapters.DataBoundControlAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Adapters.HideDisabledControlAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Adapters.HierarchicalDataBoundControlAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Adapters.MenuAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.Adapters.WebControlAdapter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.AppearanceEditorPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.BehaviorEditorPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.CatalogPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.CatalogPartChrome' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.CatalogPartCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.CatalogZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.CatalogZoneBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConnectionConsumerAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConnectionInterfaceCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConnectionPoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConnectionProviderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConnectionsZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConsumerConnectionPoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ConsumerConnectionPointCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.DeclarativeCatalogPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.EditorPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.EditorPartChrome' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.EditorPartCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.EditorZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.EditorZoneBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ErrorWebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.FieldCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.GenericWebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ImportCatalogPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IPersonalizable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ITrackingPersonalizable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ITransformerConfigurationControl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IVersioningPersonalizable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebActionable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebEditable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebPartField' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebPartParameters' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebPartRow' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.IWebPartTable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.LayoutEditorPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PageCatalogPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ParametersCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.Part' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PartChromeState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PartChromeType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizableAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationAdministration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationDictionary' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationProviderCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationStateInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationStateInfoCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PersonalizationStateQuery' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.PropertyGridEditorPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ProviderConnectionPoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ProviderConnectionPointCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ProxyWebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ProxyWebPartConnectionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ProxyWebPartManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.RowCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.RowToFieldTransformer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.RowToParametersTransformer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.SharedPersonalizationStateInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.TableCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.TitleStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.ToolZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.TransformerTypeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.UnauthorizedWebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.UserPersonalizationStateInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebBrowsableAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebDescriptionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebDisplayNameAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPart' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartAddingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartAddingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartAuthorizationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartAuthorizationEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartCancelEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartCancelEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartChrome' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnectionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnectionsCancelEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnectionsCancelEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnectionsEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartConnectionsEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDescription' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDescriptionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayModeCancelEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayModeCancelEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayModeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayModeEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartDisplayModeEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartExportMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartHelpMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartManagerInternals' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartMenuStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartMovingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartMovingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartPersonalization' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartTracker' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartTransformer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartTransformerAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartTransformerCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartUserCapability' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartVerb' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartVerbCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartVerbRenderMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartVerbsEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartVerbsEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartZoneBase' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebPartZoneCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.UI.WebControls.WebParts.WebZone' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.HttpEncoder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.IWebObjectFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.IWebPropertyAccessor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.RequestValidationSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.RequestValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.TransactedCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.Transactions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.WorkItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.Util.WorkItemCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.WebSockets.AspNetWebSocket' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.WebSockets.AspNetWebSocketContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Web.WebSockets.AspNetWebSocketOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.ValueSerializerAttribute' does not exist in the implementation but it does exist in the contract. - -// Members can't be added because types are on NS20 and the missing members required types that are not on NS20 and we are ignoring those for netcore20: -MembersMustExist : Member 'System.Activator.CreateComInstanceFrom(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateComInstanceFrom(System.String, System.String, System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.ActivationContext)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.ActivationContext, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.AppDomain, System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.AppDomain, System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.AppDomain, System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstance(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.AppDomain, System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.AppDomain, System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.AppDomain, System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.CreateInstanceFrom(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.GetObject(System.Type, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Activator.GetObject(System.Type, System.String, System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ActivationContext.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ApplicationIdentity.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ApplicationTrust.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateComInstanceFrom(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateComInstanceFrom(System.String, System.String, System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateDomain(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateDomain(System.String, System.Security.Policy.Evidence, System.AppDomainSetup)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateDomain(System.String, System.Security.Policy.Evidence, System.AppDomainSetup, System.Security.PermissionSet, System.Security.Policy.StrongName[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateDomain(System.String, System.Security.Policy.Evidence, System.String, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateDomain(System.String, System.Security.Policy.Evidence, System.String, System.String, System.Boolean, System.AppDomainInitializer, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstance(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstance(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstance(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstance(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceAndUnwrap(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceAndUnwrap(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceAndUnwrap(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceAndUnwrap(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFrom(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFrom(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFrom(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFrom(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFromAndUnwrap(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFromAndUnwrap(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFromAndUnwrap(System.String, System.String, System.Boolean, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, System.Object[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.CreateInstanceFromAndUnwrap(System.String, System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.Collections.Generic.IEnumerable, System.Security.SecurityContextSource)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Boolean, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Boolean, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DoCallBack(System.CrossAppDomainDelegate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.DomainManager.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.Evidence.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssembly(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssembly(System.String, System.Security.Policy.Evidence, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssembly(System.String, System.Security.Policy.Evidence, System.String[], System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssemblyByName(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssemblyByName(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.ExecuteAssemblyByName(System.String, System.Security.Policy.Evidence, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.Load(System.Byte[], System.Byte[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.Load(System.Reflection.AssemblyName, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.Load(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.PermissionSet.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.SetAppDomainPolicy(System.Security.Policy.PolicyLevel)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.SetData(System.String, System.Object, System.Security.IPermission)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.AppDomain.SetupInformation.get()' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.Collections.Hashtable System.Resources.ResourceManager.ResourceSets' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Hashtable System.Resources.ResourceSet.Table' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.ComponentModel.AsyncCompletedEventArgs..ctor()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.Common.DbProviderFactory.CreatePermission(System.Security.Permissions.PermissionState)' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.Diagnostics.Debug.Listeners.get()' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.IO.Directory.CreateDirectory(System.String, System.Security.AccessControl.DirectorySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.GetAccessControl(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.GetAccessControl(System.String, System.Security.AccessControl.AccessControlSections)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.SetAccessControl(System.String, System.Security.AccessControl.DirectorySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.Create(System.Security.AccessControl.DirectorySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.CreateSubdirectory(System.String, System.Security.AccessControl.DirectorySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.GetAccessControl(System.Security.AccessControl.AccessControlSections)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.SetAccessControl(System.Security.AccessControl.DirectorySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.Create(System.String, System.Int32, System.IO.FileOptions, System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.GetAccessControl(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.GetAccessControl(System.String, System.Security.AccessControl.AccessControlSections)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.SetAccessControl(System.String, System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileInfo.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileInfo.GetAccessControl(System.Security.AccessControl.AccessControlSections)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileInfo.SetAccessControl(System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, System.Int32, System.IO.FileOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, System.Int32, System.IO.FileOptions, System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileStream.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.FileStream.SetAccessControl(System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile(System.IO.FileStream, System.String, System.Int64, System.IO.MemoryMappedFiles.MemoryMappedFileAccess, System.IO.MemoryMappedFiles.MemoryMappedFileSecurity, System.IO.HandleInheritability, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryMappedFiles.MemoryMappedFile.CreateNew(System.String, System.Int64, System.IO.MemoryMappedFiles.MemoryMappedFileAccess, System.IO.MemoryMappedFiles.MemoryMappedFileOptions, System.IO.MemoryMappedFiles.MemoryMappedFileSecurity, System.IO.HandleInheritability)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpen(System.String, System.Int64, System.IO.MemoryMappedFiles.MemoryMappedFileAccess, System.IO.MemoryMappedFiles.MemoryMappedFileOptions, System.IO.MemoryMappedFiles.MemoryMappedFileSecurity, System.IO.HandleInheritability)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryMappedFiles.MemoryMappedFile.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryMappedFiles.MemoryMappedFile.SetAccessControl(System.IO.MemoryMappedFiles.MemoryMappedFileSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.AnonymousPipeServerStream..ctor(System.IO.Pipes.PipeDirection, System.IO.HandleInheritability, System.Int32, System.IO.Pipes.PipeSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.NamedPipeClientStream..ctor(System.String, System.String, System.IO.Pipes.PipeAccessRights, System.IO.Pipes.PipeOptions, System.Security.Principal.TokenImpersonationLevel, System.IO.HandleInheritability)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.NamedPipeServerStream..ctor(System.String, System.IO.Pipes.PipeDirection, System.Int32, System.IO.Pipes.PipeTransmissionMode, System.IO.Pipes.PipeOptions, System.Int32, System.Int32, System.IO.Pipes.PipeSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.NamedPipeServerStream..ctor(System.String, System.IO.Pipes.PipeDirection, System.Int32, System.IO.Pipes.PipeTransmissionMode, System.IO.Pipes.PipeOptions, System.Int32, System.Int32, System.IO.Pipes.PipeSecurity, System.IO.HandleInheritability)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.NamedPipeServerStream..ctor(System.String, System.IO.Pipes.PipeDirection, System.Int32, System.IO.Pipes.PipeTransmissionMode, System.IO.Pipes.PipeOptions, System.Int32, System.Int32, System.IO.Pipes.PipeSecurity, System.IO.HandleInheritability, System.IO.Pipes.PipeAccessRights)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.PipeStream.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Pipes.PipeStream.SetAccessControl(System.IO.Pipes.PipeSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Expressions.LambdaExpression.CompileToMethod(System.Reflection.Emit.MethodBuilder)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Expressions.LambdaExpression.CompileToMethod(System.Reflection.Emit.MethodBuilder, System.Runtime.CompilerServices.DebugInfoGenerator)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.MarshalByRefObject.CreateObjRef(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpVersion..ctor()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpWebRequest..ctor()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.ServicePointManager.CertificatePolicy.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.ServicePointManager.CertificatePolicy.set(System.Net.ICertificatePolicy)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SocketClientAccessPolicyProtocol.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SocketClientAccessPolicyProtocol.set(System.Net.Sockets.SocketClientAccessPolicyProtocol)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketFlags System.Net.Sockets.SocketFlags.MaxIOVectorLength' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.TransportContext.GetTlsTokenBindings()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebRequest.CreatorInstance.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebRequest.RegisterPortableWebRequestCreator(System.Net.IWebRequestCreate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.Evidence.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Byte[], System.Byte[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Byte[], System.Byte[], System.Security.SecurityContextSource)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Reflection.AssemblyName, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.Load(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.LoadFile(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String, System.Security.Policy.Evidence, System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.LoadWithPartialName(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.PermissionSet.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Module.GetSignerCertificate()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Resources.IResourceReader System.Resources.ResourceSet.Reader' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetActiveObject(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetComInterfaceForObjectInContext(System.Object, System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetComSlotForMethodInfo(System.Reflection.MemberInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetEndComSlot(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetExceptionPointers()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetIDispatchForObjectInContext(System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetITypeInfoForType(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetIUnknownForObjectInContext(System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetManagedThunkForUnmanagedMethodPtr(System.IntPtr, System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetMethodInfoForComSlot(System.Type, System.Int32, System.Runtime.InteropServices.ComMemberType)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetThreadFromFiberCookie(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeForITypeInfo(System.IntPtr)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeInfoName(System.Runtime.InteropServices.UCOMITypeInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibGuid(System.Runtime.InteropServices.ComTypes.ITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibGuid(System.Runtime.InteropServices.UCOMITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibGuidForAssembly(System.Reflection.Assembly)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibLcid(System.Runtime.InteropServices.ComTypes.ITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibLcid(System.Runtime.InteropServices.UCOMITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibName(System.Runtime.InteropServices.ComTypes.ITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibName(System.Runtime.InteropServices.UCOMITypeLib)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibVersionForAssembly(System.Reflection.Assembly, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetUnmanagedThunkForManagedMethodPtr(System.IntPtr, System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.IsTypeVisibleFromCom(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.NumParamBytes(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ReleaseThreadCache()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.RuntimeEnvironment..ctor()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Runtime.Serialization.DataContractResolver)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.String, System.String, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.String, System.String, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Runtime.Serialization.DataContractResolver)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.Xml.XmlDictionaryString, System.Xml.XmlDictionaryString, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer..ctor(System.Type, System.Xml.XmlDictionaryString, System.Xml.XmlDictionaryString, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Runtime.Serialization.DataContractResolver)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializer.DataContractSurrogate.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializerSettings.DataContractSurrogate.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.DataContractSerializerSettings.DataContractSurrogate.set(System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.ExportOptions.DataContractSurrogate.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.ExportOptions.DataContractSurrogate.set(System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.DeserializeMethodResponse(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler, System.Runtime.Remoting.Messaging.IMethodCallMessage)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(System.IO.Stream, System.Object, System.Runtime.Remoting.Messaging.Header[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.UnsafeDeserialize(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.UnsafeDeserializeMethodResponse(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler, System.Runtime.Remoting.Messaging.IMethodCallMessage)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializer..ctor(System.Type, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializer..ctor(System.Type, System.String, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializer..ctor(System.Type, System.Xml.XmlDictionaryString, System.Collections.Generic.IEnumerable, System.Int32, System.Boolean, System.Runtime.Serialization.IDataContractSurrogate, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializer.DataContractSurrogate.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializerSettings.DataContractSurrogate.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.Serialization.Json.DataContractJsonSerializerSettings.DataContractSurrogate.set(System.Runtime.Serialization.IDataContractSurrogate)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CspKeyContainerInfo.CryptoKeySecurity.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CspParameters..ctor(System.Int32, System.String, System.String, System.Security.AccessControl.CryptoKeySecurity, System.IntPtr)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CspParameters..ctor(System.Int32, System.String, System.String, System.Security.AccessControl.CryptoKeySecurity, System.Security.SecureString)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CspParameters.CryptoKeySecurity.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CspParameters.CryptoKeySecurity.set(System.Security.AccessControl.CryptoKeySecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException..ctor(System.String, System.Object, System.Object, System.Reflection.MethodInfo, System.Object, System.Security.IPermission)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException..ctor(System.String, System.Reflection.AssemblyName, System.Security.PermissionSet, System.Security.PermissionSet, System.Reflection.MethodInfo, System.Security.Permissions.SecurityAction, System.Object, System.Security.IPermission, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.Action.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.Action.set(System.Security.Permissions.SecurityAction)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.FirstPermissionThatFailed.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.FirstPermissionThatFailed.set(System.Security.IPermission)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.Zone.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.SecurityException.Zone.set(System.Security.SecurityZone)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Thread.CurrentContext.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String System.Resources.ResourceManager.BaseNameField' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.EventWaitHandle..ctor(System.Boolean, System.Threading.EventResetMode, System.String, System.Boolean, System.Security.AccessControl.EventWaitHandleSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.EventWaitHandle.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.EventWaitHandle.OpenExisting(System.String, System.Security.AccessControl.EventWaitHandleRights)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.EventWaitHandle.SetAccessControl(System.Security.AccessControl.EventWaitHandleSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.EventWaitHandle.TryOpenExisting(System.String, System.Security.AccessControl.EventWaitHandleRights, System.Threading.EventWaitHandle)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Mutex..ctor(System.Boolean, System.String, System.Boolean, System.Security.AccessControl.MutexSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Mutex.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Mutex.OpenExisting(System.String, System.Security.AccessControl.MutexRights)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Mutex.SetAccessControl(System.Security.AccessControl.MutexSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Mutex.TryOpenExisting(System.String, System.Security.AccessControl.MutexRights, System.Threading.Mutex)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Semaphore..ctor(System.Int32, System.Int32, System.String, System.Boolean, System.Security.AccessControl.SemaphoreSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Semaphore.GetAccessControl()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Semaphore.OpenExisting(System.String, System.Security.AccessControl.SemaphoreRights)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Semaphore.SetAccessControl(System.Security.AccessControl.SemaphoreSecurity)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Semaphore.TryOpenExisting(System.String, System.Security.AccessControl.SemaphoreRights, System.Threading.Semaphore)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlMemberMapping.GenerateTypeName(System.CodeDom.Compiler.CodeDomProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSchemaImporter..ctor(System.Xml.Serialization.XmlSchemas, System.Xml.Serialization.CodeGenerationOptions, System.CodeDom.Compiler.CodeDomProvider, System.Xml.Serialization.ImportContext)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSchemaImporter..ctor(System.Xml.Serialization.XmlSchemas, System.Xml.Serialization.CodeGenerationOptions, System.Xml.Serialization.ImportContext)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSchemaImporter..ctor(System.Xml.Serialization.XmlSchemas, System.Xml.Serialization.CodeIdentifiers, System.Xml.Serialization.CodeGenerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSerializer..ctor(System.Type, System.Xml.Serialization.XmlAttributeOverrides, System.Type[], System.Xml.Serialization.XmlRootAttribute, System.String, System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSerializer.FromMappings(System.Xml.Serialization.XmlMapping[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSerializer.GenerateSerializer(System.Type[], System.Xml.Serialization.XmlMapping[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSerializer.GenerateSerializer(System.Type[], System.Xml.Serialization.XmlMapping[], System.CodeDom.Compiler.CompilerParameters)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.XmlSerializerFactory.CreateSerializer(System.Type, System.Xml.Serialization.XmlAttributeOverrides, System.Type[], System.Xml.Serialization.XmlRootAttribute, System.String, System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.XmlReaderSettings..ctor(System.Xml.XmlResolver)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.XmlSecureResolver..ctor(System.Xml.XmlResolver, System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.XmlSecureResolver..ctor(System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.XmlSecureResolver.CreateEvidenceForUrl(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslCompiledTransform.CompileToType(System.Xml.XmlReader, System.Xml.Xsl.XsltSettings, System.Xml.XmlResolver, System.Boolean, System.Reflection.Emit.TypeBuilder, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslCompiledTransform.TemporaryFiles.get()' does not exist in the implementation but it does exist in the contract -MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XmlReader, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XPath.IXPathNavigable, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XPath.XPathNavigator, System.Xml.XmlResolver, Syste - -// Negligible usage, CAS -TypesMustExist : Type 'System.ServiceProcess.ServiceControllerPermission' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceControllerPermissionAccess' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceControllerPermissionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceControllerPermissionEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceControllerPermissionEntryCollection' does not exist in the implementation but it does exist in the contract. - -// CAS -TypesMustExist : Type 'System.Security.Policy.ApplicationSecurityInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Policy.ApplicationSecurityManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Policy.IApplicationTrustManager' does not exist in the implementation but it does exist in the contract. - -// Undesirable dependencies -TypesMustExist : Type 'System.ServiceProcess.Design.ServiceInstallerDialog' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.Design.ServiceInstallerDialogResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceInstaller' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceProcessDescriptionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceProcess.ServiceProcessInstaller' does not exist in the implementation but it does exist in the contract. - -MembersMustExist : Member 'System.Console.Write(System.String, System.Object, System.Object, System.Object, System.Object, __arglist)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Console.WriteLine(System.String, System.Object, System.Object, System.Object, System.Object, __arglist)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Concat(System.Object, System.Object, System.Object, System.Object, __arglist)' does not exist in the implementation but it does exist in the contract. - -// Intentional change in Core -TypeCannotChangeClassification : Type 'System.RuntimeArgumentHandle' is a 'ref struct' in the implementation but is a 'struct' in the contract. -TypeCannotChangeClassification : Type 'System.TypedReference' is a 'ref struct' in the implementation but is a 'struct' in the contract. \ No newline at end of file diff --git a/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.txt b/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.txt deleted file mode 100644 index 4fd3fa2437be4..0000000000000 --- a/src/libraries/shims/ApiCompatBaseline.netcoreapp.netfx461.txt +++ /dev/null @@ -1,614 +0,0 @@ -ApiCompat Error: 0 : Unable to resolve assembly 'Assembly(Name=System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' referenced by the contract assembly 'Assembly(Name=System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)'. -ApiCompat Error: 0 : Unable to resolve assembly 'Assembly(Name=System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)' referenced by the contract assembly 'Assembly(Name=System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)'. -ApiCompat Error: 0 : Unable to resolve assembly 'Assembly(Name=System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' referenced by the contract assembly 'Assembly(Name=System.Xml.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)'. -ApiCompat Error: 0 : Unable to resolve assembly 'Assembly(Name=System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' referenced by the contract assembly 'Assembly(Name=WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)'. -Compat issues with assembly mscorlib: -TypesMustExist : Type 'System.Configuration.Assemblies.AssemblyHash' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.IsolatedStorage.IsolatedStorageSecurityOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.IsolatedStorage.IsolatedStorageSecurityState' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.EventToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ExceptionHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.FieldToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.MethodRental' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.MethodToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ParameterToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.PEFileKinds' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.PropertyToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.SignatureToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.StringToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.TypeToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.UnmanagedMarshal' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.ProfileOptimization' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.InternalRM' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.InternalST' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.ISoapMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.ServerFault' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.SoapFault' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.SoapMessage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Principal.WindowsImpersonationContext' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System: -MembersMustExist : Member 'System.CodeDom.Compiler.CompilerParameters.Evidence.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.CodeDom.Compiler.CompilerParameters.Evidence.set(System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.CodeDom.Compiler.CompilerResults.Evidence.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.CodeDom.Compiler.CompilerResults.Evidence.set(System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.ConsoleTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.DiagnosticsConfigurationHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.EventLogTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.XmlWriterTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.IODescriptionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.ICertificatePolicy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.AuthenticationModuleElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.AuthenticationModuleElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.AuthenticationModulesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.BypassElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.BypassElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ConnectionManagementElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ConnectionManagementElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ConnectionManagementSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.DefaultProxySection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.FtpCachePolicyElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.HttpCachePolicyElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.HttpListenerElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.HttpListenerTimeoutsElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.HttpWebRequestElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.Ipv6Element' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.MailSettingsSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ModuleElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.NetSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.PerformanceCountersElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ProxyElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.RequestCachingSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.ServicePointManagerElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.SettingsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.SmtpNetworkElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.SmtpSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.SmtpSpecifiedPickupDirectoryElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.SocketElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.UnicodeDecodingConformance' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.UnicodeEncodingConformance' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.WebProxyScriptElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.WebRequestModuleElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.WebRequestModuleElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.WebRequestModulesSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Configuration.WebUtilityElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.SocketClientAccessPolicyProtocol' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.ICustomTypeProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.StandardOleMarshalObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.TokenBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.TokenBindingType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Claims.DynamicRoleClaimProvider' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ComponentModel.DataAnnotations: -TypesMustExist : Type 'System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.DataAnnotations.BindableTypeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.DataAnnotations.MetadataTypeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.DataAnnotations.ScaffoldTableAttribute' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Core: -TypesMustExist : Type 'System.Diagnostics.EventSchemaTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.TraceLogRetentionOption' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.UnescapedXmlDiagnosticData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.EventDescriptor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.EventProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.EventProviderTraceListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventBookmark' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventKeyword' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogConfiguration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogInvalidDataException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogIsolation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogLink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogNotFoundException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogPropertySelector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogProviderDisabledException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogQuery' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogReader' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogReadingException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogRecord' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogSession' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventLogWatcher' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventOpcode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventRecord' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.EventTask' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.PathType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.ProviderMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.SessionAuthentication' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.StandardEventKeywords' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.StandardEventLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.StandardEventOpcode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Eventing.Reader.StandardEventTask' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterData' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterSet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterSetInstance' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterSetInstanceCounterDataSet' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterSetInstanceType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PerformanceData.CounterType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.MemoryMappedFiles.MemoryMappedFileSecurity' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.InstanceNotFoundException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.InstrumentationBaseException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.InstrumentationException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementBindAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementCommitAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementConfigurationAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementConfigurationType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementCreateAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementEntityAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementEnumeratorAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementHostingModel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementKeyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementMemberAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementNameAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementNewInstanceAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementProbeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementReferenceAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementRemoveAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.ManagementTaskAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Management.Instrumentation.WmiConfigurationAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.CallSiteOps' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.Closure' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ExecutionScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeOps' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.ManifestKinds' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.ManifestSignatureInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.ManifestSignatureInformationCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.MD5Cng' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SHA1Cng' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SHA256Cng' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SHA384Cng' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SHA512Cng' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SignatureVerificationResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.StrongNameSignatureInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.AuthenticodeSignatureInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.TimestampInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.TrustStatus' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Data: -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlFacetAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlPipe' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlProcedureAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlTriggerAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.SqlTriggerContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'Microsoft.SqlServer.Server.TriggerAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.DataSetSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.PropertyAttributes' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.TypedDataSetGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.TypedDataSetGeneratorException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.Common.DbProviderConfigurationHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.Common.DbProviderFactoriesConfigurationHandler' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.Common.DbProviderFactory.CreatePermission(System.Security.Permissions.PermissionState)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.Odbc.OdbcConnection.EnlistDistributedTransaction(System.EnterpriseServices.ITransaction)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.Odbc.OdbcFactory.CreatePermission(System.Security.Permissions.PermissionState)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.Sql.SqlDataSourceEnumerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlAuthenticationMethod' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlBulkCopyOptions System.Data.SqlClient.SqlBulkCopyOptions.AllowEncryptedValueModifications' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlClientFactory.CreatePermission(System.Security.Permissions.PermissionState)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlColumnEncryptionCertificateStoreProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlColumnEncryptionCngProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlColumnEncryptionCspProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand..ctor(System.String, System.Data.SqlClient.SqlConnection, System.Data.SqlClient.SqlTransaction, System.Data.SqlClient.SqlCommandColumnEncryptionSetting)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.BeginExecuteReader()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.BeginExecuteReader(System.AsyncCallback, System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.BeginExecuteReader(System.AsyncCallback, System.Object, System.Data.CommandBehavior)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.BeginExecuteReader(System.Data.CommandBehavior)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.ColumnEncryptionSetting.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.EndExecuteReader(System.IAsyncResult)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.NotificationAutoEnlist.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlCommand.NotificationAutoEnlist.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlCommandColumnEncryptionSetting' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnection.AccessToken.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnection.AccessToken.set(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnection.EnlistDistributedTransaction(System.EnterpriseServices.ITransaction)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnection.RegisterColumnEncryptionKeyStoreProviders(System.Collections.Generic.IDictionary)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SqlConnectionColumnEncryptionSetting' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.AsynchronousProcessing.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.AsynchronousProcessing.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.Authentication.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.Authentication.set(System.Data.SqlClient.SqlAuthenticationMethod)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ColumnEncryptionSetting.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ColumnEncryptionSetting.set(System.Data.SqlClient.SqlConnectionColumnEncryptionSetting)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ConnectionReset.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ConnectionReset.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ContextConnection.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.ContextConnection.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.NetworkLibrary.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.NetworkLibrary.set(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.TransparentNetworkIPResolution.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.TransparentNetworkIPResolution.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlClient.SQLDebugging' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlParameter.ForceColumnEncryption.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlParameter.ForceColumnEncryption.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Data.SqlClient.SqlParameterCollection.Add(System.String, System.Object)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.SqlFileStream' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.SqlTypesSchemaImporterExtensionHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeBigIntSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeBinarySchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeBitSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeCharSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeDateTimeSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeDecimalSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeFloatSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeIntSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeMoneySchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeNCharSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeNTextSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeNumericSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeNVarCharSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeRealSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeSmallDateTimeSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeSmallIntSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeSmallMoneySchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeTextSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeTinyIntSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeUniqueIdentifierSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeVarBinarySchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeVarCharSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Data.SqlTypes.TypeVarImageSchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.XmlDataDocument' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.DirectoryServices: -TypesMustExist : Type 'System.DirectoryServices.DSDescriptionAttribute' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.DirectoryServices.Protocols: -MembersMustExist : Member 'System.DirectoryServices.Protocols.AddRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -CannotMakeTypeAbstract : Type 'System.DirectoryServices.Protocols.BerConverter' is abstract in the implementation but is not abstract in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.CompareRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.DeleteRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.DirectoryRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.DsmlAuthRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlAuthResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlDirectoryIdentifier' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlDocument' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlDocumentProcessing' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlErrorProcessing' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlErrorResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlInvalidDocumentException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlRequestDocument' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlResponseDocument' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlResponseOrder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlSoapConnection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.DsmlSoapHttpConnection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.ErrorResponseCategory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.DirectoryServices.Protocols.ErrorResponseException' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.ExtendedRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.ModifyDNRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.ModifyRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.SearchRequest..ctor(System.String, System.Xml.XmlDocument, System.DirectoryServices.Protocols.SearchScope, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DirectoryServices.Protocols.SearchRequest.ToXmlNode(System.Xml.XmlDocument)' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Drawing: -CannotMakeTypeAbstract : Type 'System.Drawing.ColorTranslator' is abstract in the implementation but is not abstract in the contract. -TypesMustExist : Type 'System.Drawing.FontConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.IconConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.ImageConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.ImageFormatConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.IPropertyValueUIService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.IToolboxItemProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.IToolboxService' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.IToolboxUser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.PaintValueEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.PropertyValueUIHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.PropertyValueUIItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.PropertyValueUIItemInvokeHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxComponentsCreatedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxComponentsCreatedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxComponentsCreatingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxComponentsCreatingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxItemCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.ToolboxItemCreatorCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.UITypeEditor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Design.UITypeEditorEditStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.Printing.MarginsConverter' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Net: -TypesMustExist : Type 'System.Net.INetworkProgress' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.IPEndPointCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.IUnsafeWebRequestCreate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.NetworkProgressChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.UiSynchronizationContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Cloud' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.CloudCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerName' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerNameRecord' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerNameRecordCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerNameRegistration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerNameResolver' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerNameType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.PeerToPeerException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.ResolveCompletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.ResolveProgressChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.ApplicationChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.ContactManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.CreateContactCompletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.InviteCompletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.NameChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.ObjectChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.Peer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerApplication' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerApplicationCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerApplicationLaunchInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerApplicationRegistrationType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerChangeType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerCollaboration' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerContact' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerContactCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerEndPoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerEndPointCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerInvitationResponse' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerInvitationResponseType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerNearMe' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerNearMeChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerNearMeCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerObjectCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerPresenceInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerPresenceStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PeerScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.PresenceChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.RefreshDataCompletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.SubscribeCompletedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.SubscriptionListChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.PeerToPeer.Collaboration.SubscriptionType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.HttpPolicyDownloaderProtocol' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.SecurityCriticalAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.SocketPolicy' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.UdpAnySourceMulticastClient' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.UdpSingleSourceMulticastClient' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Runtime.Serialization: -TypesMustExist : Type 'System.Runtime.Serialization.IDataContractSurrogate' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.ImportOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.NetDataContractSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.XsdDataContractImporter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.DataContractSerializerSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.DeclaredTypeElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.DeclaredTypeElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.NetDataContractSerializerSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.ParameterElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.ParameterElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.SerializationSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.TypeElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.Serialization.Configuration.TypeElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.IXmlMtomReaderInitializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.IXmlMtomWriterInitializer' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Security: -TypesMustExist : Type 'System.Security.Cryptography.DataProtector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.DpapiDataProtector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.MemoryProtectionScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.ProtectedMemory' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Pkcs.AlgorithmIdentifier.Parameters.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Pkcs.AlgorithmIdentifier.Parameters.set(System.Byte[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Pkcs.EnvelopedCms..ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType, System.Security.Cryptography.Pkcs.ContentInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Pkcs.EnvelopedCms..ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType, System.Security.Cryptography.Pkcs.ContentInfo, System.Security.Cryptography.Pkcs.AlgorithmIdentifier)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Pkcs.EnvelopedCms.Encrypt()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.Pkcs.KeyAgreeKeyChoice' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.X509Certificate2UI' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.X509SelectionFlag' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ServiceModel.Web: -TypesMustExist : Type 'System.ServiceModel.WebHttpBinding' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.WebHttpSecurity' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.WebHttpSecurityMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Activation.WebScriptServiceHostFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Activation.WebServiceHostFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.JavascriptCallbackResponseMessageProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.StreamBodyWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.WebBodyFormatMessageProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.WebContentFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.WebContentTypeMapper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Channels.WebMessageEncodingBindingElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpBindingCollectionElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpBindingElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpEndpointCollectionElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpEndpointElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebHttpSecurityElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebMessageEncodingElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebScriptEnablingElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebScriptEndpointCollectionElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Configuration.WebScriptEndpointElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.JsonFaultDetail' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.WebHttpBehavior' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.WebHttpEndpoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.WebScriptEnablingBehavior' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.WebScriptEndpoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Description.WebServiceEndpoint' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Dispatcher.JsonQueryStringConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Dispatcher.QueryStringConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Dispatcher.WebHttpDispatchOperationSelector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.AspNetCacheProfileAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.IncomingWebRequestContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.IncomingWebResponseContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.JavascriptCallbackBehaviorAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.OutgoingWebRequestContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.OutgoingWebResponseContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebChannelFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebFaultException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebFaultException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebGetAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebInvokeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebMessageBodyStyle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebMessageFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebOperationContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ServiceModel.Web.WebServiceHost' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ServiceProcess: -TypesMustExist : Type 'System.ServiceProcess.ServiceAccount' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Transactions: -TypesMustExist : Type 'System.Transactions.Configuration.DefaultSettingsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Transactions.Configuration.MachineSettingsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Transactions.Configuration.TransactionsSectionGroup' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Xml: -TypesMustExist : Type 'System.Xml.XmlXapResolver' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.CodeExporter' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Serialization.SchemaImporter.Extensions.get()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.SoapCodeExporter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.SoapSchemaExporter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.SoapSchemaImporter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.XmlCodeExporter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Advanced.SchemaImporterExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Advanced.SchemaImporterExtensionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.DateTimeSerializationSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.RootedPathValidator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.SchemaImporterExtensionElement' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.SchemaImporterExtensionElementCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.SchemaImporterExtensionsSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.SerializationSectionGroup' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.Configuration.XmlSerializerSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.XmlConfiguration.XmlReaderSection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.XmlConfiguration.XsltConfigSection' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslCompiledTransform.TemporaryFiles.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XPath.XPathNavigator, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly WindowsBase: -TypesMustExist : Type 'System.Collections.Specialized.CollectionChangedEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.CurrentChangedEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.CurrentChangingEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.CurrentChangingEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.CurrentChangingEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.DependencyPropertyDescriptor' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.ErrorsChangedEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.GroupDescription' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.ICollectionView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.ICollectionViewFactory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.ICollectionViewLiveShaping' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.IEditableCollectionView' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.IEditableCollectionViewAddNewItem' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.IItemProperties' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.ItemPropertyInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.NewItemPlaceholderPosition' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.PropertyChangedEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.PropertyFilterAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.PropertyFilterOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.SortDescription' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ComponentModel.SortDescriptionCollection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PresentationTraceLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.PresentationTraceSources' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.CertificateEmbeddingOption' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.EncryptedPackageEnvelope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.InvalidSignatureEventHandler' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.Package..ctor(System.IO.FileAccess, System.Boolean)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.PackageDigitalSignature' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.PackageDigitalSignatureManager' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.ComparePackUri(System.Uri, System.Uri)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.Create(System.Uri)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.Create(System.Uri, System.Uri)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.Create(System.Uri, System.Uri, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.GetPackageUri(System.Uri)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Packaging.PackUriHelper.GetPartUri(System.Uri)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.RightsManagementInformation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.SignatureVerificationEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.StorageInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.StreamInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Packaging.VerifyResult' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.MediaPermission' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.MediaPermissionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.MediaPermissionAudio' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.MediaPermissionImage' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.MediaPermissionVideo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.WebBrowserPermission' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.WebBrowserPermissionAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Permissions.WebBrowserPermissionLevel' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.AuthenticationType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.ContentGrant' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.ContentRight' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.ContentUser' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.CryptoProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.LocalizedNameDescriptionPair' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.PublishLicense' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.RightsManagementException' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.RightsManagementFailureCode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.SecureEnvironment' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.UnsignedPublishLicense' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.UseLicense' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.RightsManagement.UserActivationMode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.AttachedPropertyBrowsableAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.AttachedPropertyBrowsableForTypeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.AttachedPropertyBrowsableWhenAttributePresentAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.BaseCompatibilityPreferences' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.CoerceValueCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyObjectType' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyPropertyChangedEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyPropertyChangedEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.DependencyPropertyKey' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Expression' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.ExpressionConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Freezable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Int32Rect' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Int32RectConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.IWeakEventListener' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.LocalValueEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.LocalValueEnumerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.NameScope' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Point' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.PointConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.PropertyChangedCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.PropertyMetadata' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Rect' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.RectConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Size' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.SizeConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.SplashScreen' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.ValidateValueCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Vector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.VectorConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.WeakEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.WeakEventManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Converters.Int32RectValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Converters.PointValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Converters.RectValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Converters.SizeValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Converters.VectorValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Data.DataSourceProvider' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.FocusNavigationDirection' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.Key' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.KeyConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.KeyInterop' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.KeyValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.ModifierKeys' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.ModifierKeysConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.ModifierKeysValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Input.TraversalRequest' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Interop.ComponentDispatcher' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Interop.IKeyboardInputSink' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Interop.IKeyboardInputSite' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Interop.MSG' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Interop.ThreadMessageEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.DesignerSerializationOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.DesignerSerializationOptionsAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.InternalTypeHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.IReceiveMarkupExtension' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.ServiceProviders' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.Primitives.MarkupObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Markup.Primitives.MarkupProperty' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Media.DisableDpiAwarenessAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Media.Matrix' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Media.MatrixConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Media.Converters.MatrixValueSerializer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.Dispatcher' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherFrame' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherHookEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherHookEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherHooks' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherObject' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherOperation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherOperation' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherOperationCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherOperationStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherPriority' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherPriorityAwaitable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherPriorityAwaiter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherProcessingDisabled' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherSynchronizationContext' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherTimer' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherUnhandledExceptionEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherUnhandledExceptionEventHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherUnhandledExceptionFilterEventArgs' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Windows.Threading.DispatcherUnhandledExceptionFilterEventHandler' does not exist in the implementation but it does exist in the contract. -Total Issues: 633 diff --git a/src/libraries/shims/ApiCompatBaseline.netfx.netstandard.txt b/src/libraries/shims/ApiCompatBaseline.netfx.netstandard.txt deleted file mode 100644 index e185b0e6f6de7..0000000000000 --- a/src/libraries/shims/ApiCompatBaseline.netfx.netstandard.txt +++ /dev/null @@ -1,102 +0,0 @@ -Compat issues with assembly mscorlib: -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinAccountReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinApplicationPackageAuthoritySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinAnyPackageSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinCertSvcDComAccessGroup' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinCryptoOperatorsSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinDCOMUsersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinEventLogReadersGroup' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinIUsersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCacheablePrincipalsGroupSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityDocumentsLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityEnterpriseAuthenticationSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityInternetClientServerSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityInternetClientSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityMusicLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityPicturesLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityPrivateNetworkClientServerSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityRemovableStorageSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilitySharedUserCertificatesSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityVideosLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinConsoleLogonSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCreatorOwnerRightsSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinEnterpriseReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinHighLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinIUserSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinLocalLogonSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinLowLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinMediumLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinMediumPlusLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinNewEnterpriseReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinNonCacheablePrincipalsGroupSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinSystemLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinThisOrganizationCertificateSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinUntrustedLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinWriteRestrictedCodeSid' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ComponentModel.Annotations: -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.ComponentModel.DataAnnotations.DisplayAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple=false)]' in the implementation. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.DisplayFormatAttribute.GetNullDisplayText()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.DisplayFormatAttribute.NullDisplayTextResourceType.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.DisplayFormatAttribute.NullDisplayTextResourceType.set(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.RangeAttribute.ConvertValueInInvariantCulture.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.RangeAttribute.ConvertValueInInvariantCulture.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.RangeAttribute.ParseLimitsInInvariantCulture.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DataAnnotations.RangeAttribute.ParseLimitsInInvariantCulture.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ComponentModel.Composition: -TypesMustExist : Type 'System.ComponentModel.Composition.AdaptationConstants' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Configuration.ConfigurationManager: -MembersMustExist : Member 'System.Configuration.Internal.DelegatingConfigHost.HasLocalConfig.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Configuration.Internal.DelegatingConfigHost.HasRoamingConfig.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Configuration.Internal.DelegatingConfigHost.IsAppConfigHttp.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Configuration.Internal.DelegatingConfigHost.RefreshConfigPaths()' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Diagnostics.PerformanceCounter: -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Diagnostics.CounterSample' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Diagnostics.CounterSample' is marked as readonly in the contract so it must also be marked readonly in the implementation. -Compat issues with assembly System.Security.Cryptography.OpenSsl: -TypesMustExist : Type 'System.Security.Cryptography.DSAOpenSsl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.ECDsaOpenSsl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.RSAOpenSsl' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.SafeEvpPKeyHandle' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Security.Permissions: -MembersMustExist : Member 'System.Security.Permissions.KeyContainerPermissionAccessEntryCollection..ctor()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Permissions.KeyContainerPermissionAccessEntryCollection.CopyTo(System.Array, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Permissions.KeyContainerPermissionAccessEntryEnumerator..ctor()' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.Security.Principal.Windows: -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinAccountReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinApplicationPackageAuthoritySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinAnyPackageSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinCertSvcDComAccessGroup' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinCryptoOperatorsSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinDCOMUsersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinEventLogReadersGroup' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinBuiltinIUsersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCacheablePrincipalsGroupSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityDocumentsLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityEnterpriseAuthenticationSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityInternetClientServerSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityInternetClientSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityMusicLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityPicturesLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityPrivateNetworkClientServerSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityRemovableStorageSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilitySharedUserCertificatesSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCapabilityVideosLibrarySid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinConsoleLogonSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinCreatorOwnerRightsSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinEnterpriseReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinHighLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinIUserSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinLocalLogonSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinLowLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinMediumLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinMediumPlusLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinNewEnterpriseReadonlyControllersSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinNonCacheablePrincipalsGroupSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinSystemLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinThisOrganizationCertificateSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinUntrustedLabelSid' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Principal.WellKnownSidType System.Security.Principal.WellKnownSidType.WinWriteRestrictedCodeSid' does not exist in the implementation but it does exist in the contract. -Compat issues with assembly System.ServiceProcess.ServiceController: -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.ServiceProcess.SessionChangeDescription' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.ServiceProcess.SessionChangeDescription' is marked as readonly in the contract so it must also be marked readonly in the implementation. -Total Issues: 92 diff --git a/src/libraries/shims/ApiCompatBaseline.netfx.netstandardOnly.txt b/src/libraries/shims/ApiCompatBaseline.netfx.netstandardOnly.txt deleted file mode 100644 index f68769e14f081..0000000000000 --- a/src/libraries/shims/ApiCompatBaseline.netfx.netstandardOnly.txt +++ /dev/null @@ -1,870 +0,0 @@ -Compat issues with assembly netstandard: -MembersMustExist : Member 'System.Array.Fill(T[], T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Array.Fill(T[], T, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Array.Reverse(T[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Array.Reverse(T[], System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.ArraySegment' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.ArraySegment' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.ArraySegment.CopyTo(System.ArraySegment)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.CopyTo(T[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.CopyTo(T[], System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.Empty.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.GetEnumerator()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.Item.get(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.Item.set(System.Int32, T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.op_Implicit(T[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.Slice(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.Slice(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ArraySegment.ToArray()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ArraySegment.Enumerator' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.Int32BitsToSingle(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.SingleToInt32Bits(System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToBoolean(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToChar(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToDouble(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToInt16(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToInt32(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToInt64(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToSingle(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToUInt16(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToUInt32(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.ToUInt64(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Int16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Int64)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.UInt16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.UInt32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.BitConverter.TryWriteBytes(System.Span, System.UInt64)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Boolean' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Boolean' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Boolean.Parse(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Boolean.TryFormat(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Boolean.TryParse(System.ReadOnlySpan, System.Boolean)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Byte' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Byte' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Byte.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Byte.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Byte.TryParse(System.ReadOnlySpan, System.Byte)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Byte.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Byte)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Char' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Char' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.ConsoleKeyInfo' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.ConsoleKeyInfo' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Convert.ToBase64String(System.ReadOnlySpan, System.Base64FormattingOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Convert.TryFromBase64Chars(System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Convert.TryFromBase64String(System.String, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Convert.TryToBase64Chars(System.ReadOnlySpan, System.Span, System.Int32, System.Base64FormattingOptions)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.DateTime' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.DateTime' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.DateTime System.DateTime.UnixEpoch' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.Parse(System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.ParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.ParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.TryParse(System.ReadOnlySpan, System.DateTime)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.TryParse(System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTime)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.TryParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTime)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTime.TryParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTime)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.DateTimeOffset' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.DateTimeOffset' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.DateTimeOffset System.DateTimeOffset.UnixEpoch' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.Parse(System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.ParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.ParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.DateTimeStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.TryParse(System.ReadOnlySpan, System.DateTimeOffset)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.TryParse(System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTimeOffset)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.TryParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTimeOffset)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.DateTimeOffset.TryParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.DateTimeStyles, System.DateTimeOffset)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Decimal' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Decimal' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Decimal.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Decimal.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Decimal.TryParse(System.ReadOnlySpan, System.Decimal)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Decimal.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Decimal)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Double' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Double' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Double.IsFinite(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.IsNegative(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.IsNormal(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.IsSubnormal(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.TryParse(System.ReadOnlySpan, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Double.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Enum.Parse(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Enum.Parse(System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Enum.TryParse(System.Type, System.String, System.Boolean, System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Enum.TryParse(System.Type, System.String, System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.GC.GetAllocatedBytesForCurrentThread()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid..ctor(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.Parse(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.ParseExact(System.ReadOnlySpan, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.TryFormat(System.Span, System.Int32, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.TryParse(System.ReadOnlySpan, System.Guid)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.TryParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.Guid)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Guid.TryWriteBytes(System.Span)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.HashCode' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IAsyncDisposable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Index' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Int16' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Int16' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Int16.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int16.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int16.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Int16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int16.TryParse(System.ReadOnlySpan, System.Int16)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Int32' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Int32' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Int32.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int32.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int32.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int32.TryParse(System.ReadOnlySpan, System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Int64' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Int64' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Int64.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int64.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int64.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Int64)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Int64.TryParse(System.ReadOnlySpan, System.Int64)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.IntPtr' in the contract but not the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.IntPtr' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -TypeCannotChangeClassification : Type 'System.IntPtr' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Lazy..ctor(T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Acosh(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Asinh(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Atanh(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Cbrt(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Byte, System.Byte, System.Byte)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Decimal, System.Decimal, System.Decimal)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Double, System.Double, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Int16, System.Int16, System.Int16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.SByte, System.SByte, System.SByte)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.Single, System.Single, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.UInt16, System.UInt16, System.UInt16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.UInt32, System.UInt32, System.UInt32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Math.Clamp(System.UInt64, System.UInt64, System.UInt64)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.MathF' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Memory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.MemoryExtensions' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Random.NextBytes(System.Span)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Range' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ReadOnlyMemory' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.ReadOnlySpan' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsByRefLikeAttribute' exists on 'System.RuntimeArgumentHandle' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.RuntimeArgumentHandle' is a 'struct' in the implementation but is a 'ref struct' in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.SByte' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.SByte' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.SByte.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.SByte.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.SByte.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.SByte)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.SByte.TryParse(System.ReadOnlySpan, System.SByte)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.SequencePosition' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Single' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Single' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Single.IsFinite(System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.IsNegative(System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.IsNormal(System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.IsSubnormal(System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Single.TryParse(System.ReadOnlySpan, System.Single)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Span' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String..ctor(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Chars.get(System.Index)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Chars.get(System.Range)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Contains(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Contains(System.Char, System.StringComparison)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Contains(System.String, System.StringComparison)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Create(System.Int32, TState, System.Buffers.SpanAction)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.EndsWith(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.GetHashCode(System.StringComparison)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.IndexOf(System.Char, System.StringComparison)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Join(System.Char, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Join(System.Char, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Join(System.Char, System.String[], System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Join(System.Char, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.op_Implicit(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Replace(System.String, System.String, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Replace(System.String, System.String, System.StringComparison)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Split(System.Char, System.Int32, System.StringSplitOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Split(System.Char, System.StringSplitOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Split(System.String, System.Int32, System.StringSplitOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Split(System.String, System.StringSplitOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.StartsWith(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Substring(System.Index)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Substring(System.Range)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.Trim(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.TrimEnd()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.TrimEnd(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.TrimStart()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String.TrimStart(System.Char)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.StringComparer.Create(System.Globalization.CultureInfo, System.Globalization.CompareOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.StringComparer.FromComparison(System.StringComparison)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.TimeSpan' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.TimeSpan' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.TimeSpan.Divide(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.Divide(System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.Multiply(System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.op_Division(System.TimeSpan, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.op_Division(System.TimeSpan, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.op_Multiply(System.Double, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.op_Multiply(System.TimeSpan, System.Double)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.Parse(System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.ParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.TimeSpanStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.ParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.TimeSpanStyles)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParse(System.ReadOnlySpan, System.IFormatProvider, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParse(System.ReadOnlySpan, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.Globalization.TimeSpanStyles, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParseExact(System.ReadOnlySpan, System.ReadOnlySpan, System.IFormatProvider, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.Globalization.TimeSpanStyles, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.TimeSpan.TryParseExact(System.ReadOnlySpan, System.String[], System.IFormatProvider, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.TimeZoneInfo.TransitionTime' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.TimeZoneInfo.TransitionTime' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Type.GetMethod(System.String, System.Int32, System.Reflection.BindingFlags, System.Reflection.Binder, System.Reflection.CallingConventions, System.Type[], System.Reflection.ParameterModifier[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.GetMethod(System.String, System.Int32, System.Reflection.BindingFlags, System.Reflection.Binder, System.Type[], System.Reflection.ParameterModifier[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.GetMethod(System.String, System.Int32, System.Type[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.GetMethod(System.String, System.Int32, System.Type[], System.Reflection.ParameterModifier[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.GetMethodImpl(System.String, System.Int32, System.Reflection.BindingFlags, System.Reflection.Binder, System.Reflection.CallingConventions, System.Type[], System.Reflection.ParameterModifier[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsByRefLike.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsGenericMethodParameter.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsGenericTypeParameter.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsSignatureType.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsSZArray.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsTypeDefinition.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.IsVariableBoundArray.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Type.MakeGenericMethodParameter(System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsByRefLikeAttribute' exists on 'System.TypedReference' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.TypedReference' is a 'struct' in the implementation but is a 'ref struct' in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.UInt16' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.UInt16' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.UInt16.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt16.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt16.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.UInt16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt16.TryParse(System.ReadOnlySpan, System.UInt16)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.UInt32' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.UInt32' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.UInt32.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt32.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt32.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.UInt32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt32.TryParse(System.ReadOnlySpan, System.UInt32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.UInt64' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.UInt64' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.UInt64.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt64.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt64.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.UInt64)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.UInt64.TryParse(System.ReadOnlySpan, System.UInt64)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.UIntPtr' in the contract but not the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.UIntPtr' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -TypeCannotChangeClassification : Type 'System.UIntPtr' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Version.Parse(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Version.TryFormat(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Version.TryFormat(System.Span, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Version.TryParse(System.ReadOnlySpan, System.Version)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.ArrayPool' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.BuffersExtensions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.IBufferWriter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.IMemoryOwner' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.IPinnable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.MemoryHandle' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.MemoryManager' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.MemoryPool' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.OperationStatus' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.ReadOnlySequence' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.ReadOnlySequenceSegment' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.ReadOnlySpanAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.SpanAction' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.StandardFormat' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.Binary.BinaryPrimitives' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.Text.Base64' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.Text.Utf8Formatter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Buffers.Text.Utf8Parser' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.CodeDom.Compiler.IndentedTextWriter' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Collections.BitArray.LeftShift(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.BitArray.RightShift(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.DictionaryEntry.Deconstruct(System.Object, System.Object)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Concurrent.ConcurrentBag.Clear()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Concurrent.ConcurrentQueue.Clear()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Collections.Generic.CollectionExtensions' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary..ctor(System.Collections.Generic.IEnumerable>)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary..ctor(System.Collections.Generic.IEnumerable>, System.Collections.Generic.IEqualityComparer)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary.EnsureCapacity(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary.Remove(TKey, TValue)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary.TrimExcess()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary.TrimExcess(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Dictionary.TryAdd(TKey, TValue)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.HashSet.EnsureCapacity(System.Int32)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Collections.Generic.IAsyncEnumerable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Collections.Generic.IAsyncEnumerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Collections.Generic.KeyValuePair' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Collections.Generic.KeyValuePair' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Collections.Generic.KeyValuePair' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Collections.Generic.KeyValuePair.Deconstruct(TKey, TValue)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Queue.TryDequeue(T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Queue.TryPeek(T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Stack.TryPeek(T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.Generic.Stack.TryPop(T)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Collections.ObjectModel.KeyedCollection.TryGetValue(TKey, TItem)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Collections.Specialized.BitVector32.Section' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Collections.Specialized.BitVector32.Section' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute..ctor(System.SByte)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute..ctor(System.UInt16)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute..ctor(System.UInt32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute..ctor(System.UInt64)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.ComponentModel.Design.Serialization.MemberRelationship' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.ComponentModel.Design.Serialization.MemberRelationship' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Data.Common.DbProviderFactories' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.ArgumentList.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.StandardInputEncoding.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.StandardInputEncoding.set(System.Text.Encoding)' does not exist in the implementation but it does exist in the contract. -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Diagnostics.SymbolStore.SymbolToken' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Diagnostics.SymbolStore.SymbolToken' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.Tracing.EventCounter' does not implement interface 'System.IDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Diagnostics.Tracing.EventCounter.Dispose()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Diagnostics.Tracing.EventSourceCreatedEventArgs' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Drawing.Color' in the contract but not the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Color' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -TypeCannotChangeClassification : Type 'System.Drawing.Color' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Drawing.Color.Equals(System.Drawing.Color)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.ColorConverter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.KnownColor' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Point' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.Point.Equals(System.Drawing.Point)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.PointConverter' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.PointF' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.PointF.Equals(System.Drawing.PointF)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Rectangle' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.Rectangle.Equals(System.Drawing.Rectangle)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.RectangleConverter' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.RectangleF' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.RectangleF.Equals(System.Drawing.RectangleF)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.Size' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.Size.Equals(System.Drawing.Size)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Division(System.Drawing.Size, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Division(System.Drawing.Size, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Multiply(System.Drawing.Size, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Multiply(System.Drawing.Size, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Multiply(System.Int32, System.Drawing.Size)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.Size.op_Multiply(System.Single, System.Drawing.Size)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.SizeConverter' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Drawing.SizeF' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Drawing.SizeF.Equals(System.Drawing.SizeF)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.SizeF.op_Division(System.Drawing.SizeF, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.SizeF.op_Multiply(System.Drawing.SizeF, System.Single)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Drawing.SizeF.op_Multiply(System.Single, System.Drawing.SizeF)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Drawing.SizeFConverter' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Globalization.CharUnicodeInfo.GetUnicodeCategory(System.Int32)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Globalization.ISOWeek' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BinaryReader.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BinaryReader.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.BinaryWriter' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.BinaryWriter.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BinaryWriter.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BinaryWriter.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.BufferedStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.BufferedStream.BufferSize.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BufferedStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.BufferedStream.UnderlyingStream.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.EnumerateDirectories(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.EnumerateFiles(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.EnumerateFileSystemEntries(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.GetDirectories(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.GetFiles(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Directory.GetFileSystemEntries(System.String, System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.EnumerateDirectories(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.EnumerateFiles(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.EnumerateFileSystemInfos(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.GetDirectories(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.GetFiles(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.DirectoryInfo.GetFileSystemInfos(System.String, System.IO.EnumerationOptions)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.EnumerationOptions' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.AppendAllLinesAsync(System.String, System.Collections.Generic.IEnumerable, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.AppendAllLinesAsync(System.String, System.Collections.Generic.IEnumerable, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.AppendAllTextAsync(System.String, System.String, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.AppendAllTextAsync(System.String, System.String, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.ReadAllBytesAsync(System.String, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.ReadAllLinesAsync(System.String, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.ReadAllLinesAsync(System.String, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.ReadAllTextAsync(System.String, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.ReadAllTextAsync(System.String, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.WriteAllBytesAsync(System.String, System.Byte[], System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.WriteAllLinesAsync(System.String, System.Collections.Generic.IEnumerable, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.WriteAllLinesAsync(System.String, System.Collections.Generic.IEnumerable, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.WriteAllTextAsync(System.String, System.String, System.Text.Encoding, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.File.WriteAllTextAsync(System.String, System.String, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotMakeMemberNonVirtual : Member 'System.IO.FileStream.Name' is non-virtual in the implementation but is virtual in the contract. -MembersMustExist : Member 'System.IO.FileStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -CannotMakeMemberNonVirtual : Member 'System.IO.FileStream.Name.get()' is non-virtual in the implementation but is virtual in the contract. -TypesMustExist : Type 'System.IO.MatchCasing' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.MatchType' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.MemoryStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.MemoryStream.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryStream.ReadAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryStream.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.MemoryStream.WriteAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetDirectoryName(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetExtension(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetFileName(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetFileNameWithoutExtension(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetFullPath(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetPathRoot(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.GetRelativePath(System.String, System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.HasExtension(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.IsPathFullyQualified(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.IsPathFullyQualified(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.IsPathRooted(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.Join(System.ReadOnlySpan, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.Join(System.ReadOnlySpan, System.ReadOnlySpan, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.TryJoin(System.ReadOnlySpan, System.ReadOnlySpan, System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Path.TryJoin(System.ReadOnlySpan, System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Stream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotMakeMemberNonVirtual : Member 'System.IO.Stream.CopyTo(System.IO.Stream, System.Int32)' is non-virtual in the implementation but is virtual in the contract. -MembersMustExist : Member 'System.IO.Stream.CopyToAsync(System.IO.Stream, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Stream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Stream.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Stream.ReadAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Stream.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Stream.WriteAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamReader.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamReader.ReadAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamReader.ReadBlock(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamReader.ReadBlockAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.StreamWriter' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.StreamWriter.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamWriter.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamWriter.WriteAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamWriter.WriteLine(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StreamWriter.WriteLineAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringReader.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringReader.ReadAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringReader.ReadBlock(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringReader.ReadBlockAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.StringWriter' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.StringWriter.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringWriter.WriteAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringWriter.WriteLine(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.StringWriter.WriteLineAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextReader.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextReader.ReadAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextReader.ReadBlock(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextReader.ReadBlockAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.TextWriter' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.TextWriter.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextWriter.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextWriter.WriteAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextWriter.WriteLine(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.TextWriter.WriteLineAsync(System.ReadOnlyMemory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.UnmanagedMemoryStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.UnmanagedMemoryStream.Read(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.UnmanagedMemoryStream.Write(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Compression.BrotliDecoder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Compression.BrotliEncoder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Compression.BrotliStream' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Compression.DeflateStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.Compression.DeflateStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Compression.GZipStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.Compression.GZipStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Compression.ZipArchiveEntry.Crc32.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Compression.ZipFile.ExtractToDirectory(System.String, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Compression.ZipFile.ExtractToDirectory(System.String, System.String, System.Text.Encoding, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.IO.Compression.ZipFileExtensions.ExtractToDirectory(System.IO.Compression.ZipArchive, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Enumeration.FileSystemEntry' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Enumeration.FileSystemEnumerable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Enumeration.FileSystemEnumerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.IO.Enumeration.FileSystemName' does not exist in the implementation but it does exist in the contract. -CannotAddAbstractMembers : Member 'System.IO.IsolatedStorage.IsolatedStorage.GetPermission(System.Security.PermissionSet)' is abstract in the implementation but is missing in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.IsolatedStorage.IsolatedStorageFileStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorageFileStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.MemoryMappedFiles.MemoryMappedViewStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Pipes.AnonymousPipeClientStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Pipes.AnonymousPipeServerStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Pipes.NamedPipeClientStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Pipes.NamedPipeServerStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.IO.Pipes.PipeOptions System.IO.Pipes.PipeOptions.CurrentUserOnly' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.IO.Pipes.PipeStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Linq.Enumerable.SkipLast(System.Collections.Generic.IEnumerable, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Enumerable.TakeLast(System.Collections.Generic.IEnumerable, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Queryable.Append(System.Linq.IQueryable, TSource)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Queryable.Prepend(System.Linq.IQueryable, TSource)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Queryable.SkipLast(System.Linq.IQueryable, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Linq.Queryable.TakeLast(System.Linq.IQueryable, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.AlreadyReported' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.EarlyHints' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.FailedDependency' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.IMUsed' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.InsufficientStorage' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.Locked' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.LoopDetected' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.MisdirectedRequest' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.MultiStatus' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.NetworkAuthenticationRequired' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.NotExtended' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.PermanentRedirect' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.PreconditionRequired' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.Processing' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.RequestHeaderFieldsTooLarge' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.TooManyRequests' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.UnavailableForLegalReasons' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.UnprocessableEntity' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.HttpStatusCode System.Net.HttpStatusCode.VariantAlsoNegotiates' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Version System.Net.HttpVersion.Unknown' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Version System.Net.HttpVersion.Version20' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress..ctor(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress..ctor(System.ReadOnlySpan, System.Int64)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress.Parse(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress.TryFormat(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress.TryParse(System.ReadOnlySpan, System.Net.IPAddress)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.IPAddress.TryWriteBytes(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Http.HttpClient.PatchAsync(System.String, System.Net.Http.HttpContent)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Http.HttpClient.PatchAsync(System.String, System.Net.Http.HttpContent, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Http.HttpClient.PatchAsync(System.Uri, System.Net.Http.HttpContent)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Http.HttpClient.PatchAsync(System.Uri, System.Net.Http.HttpContent, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Http.HttpMethod.Patch.get()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Http.ReadOnlyMemoryContent' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String System.Net.Mime.MediaTypeNames.Application.Json' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.String System.Net.Mime.MediaTypeNames.Application.Xml' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Security.AuthenticatedStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Net.Security.AuthenticatedStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Security.NegotiateStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Net.Security.NegotiateStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Security.ServerCertificateSelectionCallback' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Security.SslApplicationProtocol' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Security.SslClientAuthenticationOptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Security.SslServerAuthenticationOptions' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Security.SslStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Net.Security.SslStream.AuthenticateAsClientAsync(System.Net.Security.SslClientAuthenticationOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Security.SslStream.AuthenticateAsServerAsync(System.Net.Security.SslServerAuthenticationOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Security.SslStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Security.SslStream.NegotiatedApplicationProtocol.get()' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Net.Sockets.NetworkStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Receive(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Receive(System.Span, System.Net.Sockets.SocketFlags)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Receive(System.Span, System.Net.Sockets.SocketFlags, System.Net.Sockets.SocketError)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Send(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Send(System.ReadOnlySpan, System.Net.Sockets.SocketFlags)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.Socket.Send(System.ReadOnlySpan, System.Net.Sockets.SocketFlags, System.Net.Sockets.SocketError)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.MemoryBuffer.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SetBuffer(System.Memory)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketTaskExtensions.ReceiveAsync(System.Net.Sockets.Socket, System.Memory, System.Net.Sockets.SocketFlags, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.Sockets.SocketTaskExtensions.SendAsync(System.Net.Sockets.Socket, System.ReadOnlyMemory, System.Net.Sockets.SocketFlags, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.Sockets.UnixDomainSocketEndPoint' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebSockets.ClientWebSocketOptions.RemoteCertificateValidationCallback.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebSockets.ClientWebSocketOptions.RemoteCertificateValidationCallback.set(System.Net.Security.RemoteCertificateValidationCallback)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Net.WebSockets.ValueWebSocketReceiveResult' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebSockets.WebSocket.CreateFromStream(System.IO.Stream, System.Boolean, System.String, System.TimeSpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebSockets.WebSocket.ReceiveAsync(System.Memory, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Net.WebSockets.WebSocket.SendAsync(System.ReadOnlyMemory, System.Net.WebSockets.WebSocketMessageType, System.Boolean, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Numerics.BigInteger' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Numerics.BigInteger' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Numerics.BigInteger..ctor(System.ReadOnlySpan, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.GetByteCount(System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.ToByteArray(System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Numerics.BigInteger)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.TryParse(System.ReadOnlySpan, System.Numerics.BigInteger)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Numerics.BigInteger.TryWriteBytes(System.Span, System.Int32, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Matrix3x2' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Matrix4x4' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Plane' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Quaternion' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Vector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Vector' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Vector2' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Vector3' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Numerics.Vector4' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.Assembly.GetForwardedTypes()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.BindingFlags System.Reflection.BindingFlags.DoNotWrapExceptions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.DispatchProxy' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.MemberInfo.HasSameMetadataDefinitionAs(System.Reflection.MemberInfo)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.MethodBase.IsConstructedGenericMethod.get()' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Reflection.ParameterModifier' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Reflection.ParameterModifier' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsByRefLike.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsGenericMethodParameter.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsGenericTypeParameter.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsSZArray.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsTypeDefinition.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Reflection.TypeDelegator.IsVariableBoundArray.get()' does not exist in the implementation but it does exist in the contract. -CannotSealType : Type 'System.Reflection.TypeInfo' is effectively (has a private constructor) sealed in the implementation but not sealed in the contract. -MembersMustExist : Member 'System.Reflection.TypeInfo..ctor()' does not exist in the implementation but it does exist in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredConstructors' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredEvents' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredFields' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredMembers' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredMethods' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredNestedTypes' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredProperties' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GenericTypeParameters' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.ImplementedInterfaces' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.AsType()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredConstructors.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredEvents.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredFields.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredMembers.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredMethods.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredNestedTypes.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.DeclaredProperties.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GenericTypeParameters.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredEvent(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredField(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredMethod(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredMethods(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredNestedType(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.GetDeclaredProperty(System.String)' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.ImplementedInterfaces.get()' is non-virtual in the implementation but is virtual in the contract. -CannotMakeMemberNonVirtual : Member 'System.Reflection.TypeInfo.IsAssignableFrom(System.Reflection.TypeInfo)' is non-virtual in the implementation but is virtual in the contract. -TypesMustExist : Type 'System.Reflection.Emit.AssemblyBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.AssemblyBuilderAccess' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ConstructorBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.CustomAttributeBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.DynamicILInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.DynamicMethod' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.EnumBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.EventBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.EventToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ExceptionHandler' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.FieldBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.FieldToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.GenericTypeParameterBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ILGenerator' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.Label' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.LocalBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.MethodBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.MethodToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ModuleBuilder' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Reflection.Emit.OpCode' in the contract but not the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.OpCode' does not implement interface 'System.IEquatable' in the implementation but it does in the contract. -TypeCannotChangeClassification : Type 'System.Reflection.Emit.OpCode' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Reflection.Emit.ParameterBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.ParameterToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.PropertyBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.PropertyToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.SignatureHelper' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.SignatureToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.StringToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.TypeBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Reflection.Emit.TypeToken' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.AsyncIteratorMethodBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ConditionalWeakTable' does not implement interface 'System.Collections.Generic.IEnumerable>' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.ConditionalWeakTable.AddOrUpdate(TKey, TValue)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.ConditionalWeakTable.Clear()' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ConfiguredAsyncDisposable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.IsByRefLikeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ITuple' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeFeature' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(T[], System.Range)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(System.Type)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.TryEnsureSufficientExecutionStack()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeWrappedException..ctor(System.Object)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.SwitchExpressionException' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.TaskAwaiter' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.TaskAwaiter' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.TaskAwaiter' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.TaskAwaiter' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Runtime.CompilerServices.ValueTaskAwaiter' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.CompilerServices.ValueTaskAwaiter' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.YieldAwaitable' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.YieldAwaitable' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(System.Exception)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.AutomationProxyAttribute' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.InteropServices.HandleRef' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.InteropServices.HandleRef' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Runtime.InteropServices.ImportedFromTypeLibAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringUTF8(System.IntPtr)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringUTF8(System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.StringToCoTaskMemUTF8(System.String)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ZeroFreeCoTaskMemUTF8(System.IntPtr)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.MemoryMarshal' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.InteropServices.OSPlatform' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.InteropServices.OSPlatform' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Runtime.InteropServices.SequenceMarshal' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibFuncAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibFuncFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibImportClassAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibTypeAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibTypeFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibVarAttribute' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibVarFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Runtime.InteropServices.TypeLibVersionAttribute' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.Serialization.SerializationEntry' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.Serialization.SerializationEntry' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Runtime.Serialization.StreamingContext' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Runtime.Serialization.StreamingContext' is marked as readonly in the contract so it must also be marked readonly in the implementation. -TypesMustExist : Type 'System.Runtime.Serialization.Formatters.IFieldInfo' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.CryptographicOperations' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.CryptoStream' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Security.Cryptography.CryptoStream.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.DSA.TryCreateSignature(System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.DSA.TryHashData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.DSA.TrySignData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.DSA.VerifyData(System.ReadOnlySpan, System.ReadOnlySpan, System.Security.Cryptography.HashAlgorithmName)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.DSA.VerifySignature(System.ReadOnlySpan, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.ECDiffieHellman' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.ECDsa.TryHashData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.ECDsa.TrySignData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.ECDsa.TrySignHash(System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.ECDsa.VerifyData(System.ReadOnlySpan, System.ReadOnlySpan, System.Security.Cryptography.HashAlgorithmName)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.ECDsa.VerifyHash(System.ReadOnlySpan, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.TryComputeHash(System.ReadOnlySpan, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Security.Cryptography.HashAlgorithmName' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Security.Cryptography.HashAlgorithmName' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Security.Cryptography.HMAC.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMAC.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACMD5.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACMD5.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA1.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA1.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA256.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA256.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA384.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA384.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA512.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.HMACSHA512.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.IncrementalHash.AppendData(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.IncrementalHash.TryGetHashAndReset(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.Fill(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.GetBytes(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.GetInt32(System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.GetInt32(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.GetNonZeroBytes(System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.Rfc2898DeriveBytes.HashAlgorithm.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.TryDecrypt(System.ReadOnlySpan, System.Span, System.Security.Cryptography.RSAEncryptionPadding, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.TryEncrypt(System.ReadOnlySpan, System.Span, System.Security.Cryptography.RSAEncryptionPadding, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.TryHashData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.TrySignData(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.TrySignHash(System.ReadOnlySpan, System.Span, System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.VerifyData(System.ReadOnlySpan, System.ReadOnlySpan, System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.RSA.VerifyHash(System.ReadOnlySpan, System.ReadOnlySpan, System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA1Managed.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA1Managed.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA256Managed.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA256Managed.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA384Managed.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA384Managed.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA512Managed.HashCore(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.SHA512Managed.TryHashFinal(System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.CertificateRequest' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.DSACertificateExtensions' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Certificate.GetCertHash(System.Security.Cryptography.HashAlgorithmName)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Certificate.GetCertHashString(System.Security.Cryptography.HashAlgorithmName)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Certificate.TryGetCertHash(System.Security.Cryptography.HashAlgorithmName, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Security.Cryptography.X509Certificates.X509SignatureGenerator' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Store..ctor(System.Security.Cryptography.X509Certificates.StoreName, System.Security.Cryptography.X509Certificates.StoreLocation, System.Security.Cryptography.X509Certificates.OpenFlags)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Store..ctor(System.String, System.Security.Cryptography.X509Certificates.StoreLocation, System.Security.Cryptography.X509Certificates.OpenFlags)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Store.IsOpen.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Decoder.Convert(System.ReadOnlySpan, System.Span, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Decoder.GetCharCount(System.ReadOnlySpan, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Decoder.GetChars(System.ReadOnlySpan, System.Span, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoder.Convert(System.ReadOnlySpan, System.Span, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoder.GetByteCount(System.ReadOnlySpan, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoder.GetBytes(System.ReadOnlySpan, System.Span, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetByteCount(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetByteCount(System.String, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetBytes(System.ReadOnlySpan, System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetBytes(System.String, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetCharCount(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetChars(System.ReadOnlySpan, System.Span)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.GetString(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.Encoding.Preamble.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.Append(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.Append(System.Text.StringBuilder)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.Append(System.Text.StringBuilder, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.Char, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.Char, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.String, System.Object[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.String, System.String[])' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.Char, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.AppendJoin(System.String, System.Collections.Generic.IEnumerable)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.CopyTo(System.Int32, System.Span, System.Int32)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.Equals(System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Text.StringBuilder.Insert(System.Int32, System.ReadOnlySpan)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.RegularExpressions.CaptureCollection' does not implement interface 'System.Collections.Generic.ICollection' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Text.RegularExpressions.CaptureCollection.CopyTo(System.Text.RegularExpressions.Capture[], System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.RegularExpressions.GroupCollection' does not implement interface 'System.Collections.Generic.ICollection' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Text.RegularExpressions.GroupCollection.CopyTo(System.Text.RegularExpressions.Group[], System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Text.RegularExpressions.MatchCollection' does not implement interface 'System.Collections.Generic.ICollection' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Text.RegularExpressions.MatchCollection.CopyTo(System.Text.RegularExpressions.Match[], System.Int32)' does not exist in the implementation but it does exist in the contract. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Threading.AsyncLocalValueChangedArgs' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Threading.AsyncLocalValueChangedArgs' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Threading.CancellationToken' in the contract but not the implementation. -TypeCannotChangeClassification : Type 'System.Threading.CancellationToken' is marked as readonly in the contract so it must also be marked readonly in the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Threading.CancellationTokenRegistration' in the contract but not the implementation. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.CancellationTokenRegistration' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -TypeCannotChangeClassification : Type 'System.Threading.CancellationTokenRegistration' is marked as readonly in the contract so it must also be marked readonly in the implementation. -MembersMustExist : Member 'System.Threading.CancellationTokenRegistration.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.CancellationTokenRegistration.Token.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Interlocked.MemoryBarrierProcessWide()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.LazyInitializer.EnsureInitialized(T, System.Object, System.Func)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Thread.GetCurrentProcessorId()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.ThreadPool.QueueUserWorkItem(System.Action, TState, System.Boolean)' does not exist in the implementation but it does exist in the contract. -CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Timer' does not implement interface 'System.IAsyncDisposable' in the implementation but it does in the contract. -MembersMustExist : Member 'System.Threading.Timer.DisposeAsync()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Tasks.Task.IsCompletedSuccessfully.get()' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Tasks.TaskCanceledException..ctor(System.String, System.Exception, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Tasks.TaskExtensions.ConfigureAwait(System.IAsyncDisposable, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Tasks.TaskExtensions.ConfigureAwait(System.Collections.Generic.IAsyncEnumerable, System.Boolean)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Threading.Tasks.TaskExtensions.WithCancellation(System.Collections.Generic.IAsyncEnumerable, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.ValueTask' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.ValueTask' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.Sources.IValueTaskSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.Sources.IValueTaskSource' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Threading.Tasks.Sources.ValueTaskSourceStatus' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XCData.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XComment.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.IO.Stream, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.IO.TextReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.Xml.XmlReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.IO.Stream, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.IO.TextWriter, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocument.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XDocumentType.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.IO.Stream, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.IO.TextReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.Xml.XmlReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.IO.Stream, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.IO.TextWriter, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XElement.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XNode.ReadFromAsync(System.Xml.XmlReader, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XNode.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XProcessingInstruction.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -MembersMustExist : Member 'System.Xml.Linq.XText.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract. -TypesMustExist : Type 'System.Xml.Serialization.SchemaImporter' does not exist in the implementation but it does exist in the contract. -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Xml.Serialization.XmlAnyAttributeAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple=false)]' in the implementation. -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Xml.Serialization.XmlNamespaceDeclarationsAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple=false)]' in the implementation. -Total Issues: 868 diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index f1698345fcbbf..2e5554df5bc5b 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -47,7 +47,7 @@ Roslyn4.0.Tests.csproj" /> - + @@ -222,8 +222,6 @@ Roslyn4.0.Tests.csproj" /> - - @@ -277,9 +275,6 @@ Roslyn4.0.Tests.csproj" /> - - - @@ -301,9 +296,6 @@ Roslyn4.0.Tests.csproj" /> - - - @@ -346,13 +338,21 @@ Roslyn4.0.Tests.csproj" /> - + + + + + + + + + diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 6b97bae13a95a..909e1f72c19dc 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -9,6 +9,7 @@ project(mono) include(../../eng/native/configurepaths.cmake) include(${CLR_ENG_NATIVE_DIR}/functions.cmake) +set(CROSS_ROOTFS $ENV{ROOTFS_DIR}) set(CMAKE_C_FLAGS_CHECKED "") set(CMAKE_CXX_FLAGS_CHECKED "") set(CMAKE_EXE_LINKER_FLAGS_CHECKED "") @@ -246,6 +247,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "WASI") set(INTERNAL_ZLIB 1) set(DISABLE_EXECUTABLES 1) set(DISABLE_COMPONENTS 1) + + set(WASI_DRIVER_SOURCES + wasi/mono-wasi-driver/driver.c + wasi/mono-wasi-driver/stubs.c + wasi/mono-wasi-driver/synthetic-pthread.c + ) + add_library(mono-wasi-driver STATIC ${WASI_DRIVER_SOURCES}) + target_compile_options(mono-wasi-driver PRIVATE -Wno-missing-prototypes -Wno-strict-prototypes) + install(TARGETS mono-wasi-driver LIBRARY) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(HOST_WIN32 1) set(EXE_SUFFIX ".exe") @@ -411,8 +421,13 @@ elseif(TARGET_ARCH STREQUAL "arm64") elseif(TARGET_ARCH MATCHES "arm") set(TARGET_ARM 1) set(MONO_ARCHITECTURE "\"arm\"") - # FIXME: - add_definitions("-DARM_FPU_VFP=1") + if(MONO_ARM_FPU STREQUAL "none") + add_definitions("-DARM_FPU_NONE=1") + elseif(MONO_ARM_FPU STREQUAL "vfp-hard") + add_definitions("-DARM_FPU_VFP_HARD=1") + else() + add_definitions("-DARM_FPU_VFP=1") + endif() set(TARGET_SIZEOF_VOID_P 4) set(SIZEOF_REGISTER 4) # fixme: use separate defines for host/target @@ -463,8 +478,13 @@ include(configure) ###################################### if(GCC) - # We require C99 with some GNU extensions, e.g. `linux` macro - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + if(HOST_WASI) + # WASI SDK only includes some required definitions if the C version is at least this new + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") + else() + # We require C99 with some GNU extensions, e.g. `linux` macro + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + endif() # The runtime code does not respect ANSI C strict aliasing rules append("-fno-strict-aliasing" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) # We rely on signed overflow to behave @@ -630,6 +650,9 @@ elseif(HOST_ANDROID) set(HAVE_SYS_ICU 1) elseif(HOST_LINUX) include(FindPkgConfig) + if(CROSS_ROOTFS) + set(ENV{PKG_CONFIG_ICU_UC_INCLUDEDIR} "${CROSS_ROOTFS}/usr/include") + endif(CROSS_ROOTFS) pkg_check_modules(ICU icu-uc) set(ICU_FLAGS "-DTARGET_UNIX -DU_DISABLE_RENAMING -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option -Wno-deprecated-declarations") set(HAVE_SYS_ICU 1) diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index cb143f5d381be..d952686ac56b8 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -10,7 +10,7 @@ $(RuntimeBinDir)IL/ Debug;Release;Checked - x64;x86;arm;arm64;s390x;wasm + x64;x86;arm;armv6;arm64;s390x;wasm true @@ -56,6 +56,10 @@ x86 $(DefineConstants);TARGET_X86 + + arm + $(DefineConstants);TARGET_ARMV6 + arm $(DefineConstants);TARGET_ARM @@ -290,6 +294,7 @@ + diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml index 4a8ffce034109..b5f129a8faa84 100644 --- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml +++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml @@ -424,7 +424,6 @@ * ves_icall_System_Reflection_Assembly_GetReferencedAssemblies * fill_reflection_assembly_name * ves_icall_System_Reflection_Assembly_FillName - * ves_icall_System_Reflection_Assembly_InternalGetAssemblyName * ves_icall_System_Reflection_AssemblyName_ParseName --> @@ -647,5 +646,8 @@ + + + diff --git a/src/mono/System.Private.CoreLib/src/Mono/HotReload.cs b/src/mono/System.Private.CoreLib/src/Mono/HotReload.cs new file mode 100644 index 0000000000000..c1cd977ceb6b2 --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/Mono/HotReload.cs @@ -0,0 +1,114 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Mono.HotReload; + +// TODO: this is just a sketch, instance field additions aren't supported by Mono yet until https://github.com/dotnet/runtime/issues/63643 is fixed +#if false +internal class InstanceFieldTable +{ + // Q: Does CoreCLR EnC allow adding fields to a valuetype? + // A: No, see EEClass::AddField - if the type has layout or is a valuetype, you can't add fields to it. + + // See EnCAddedField::Allocate for a description of the CoreCLR version of this. + // + // This is substantially the same design, except instead of using dependent handles + // (ephemerons) directly from native (storing a linked list of ephemerons off the sync block + // of the instance), we use a ConditionalWeakTable from managed that's keyed on the + // instances (so the value dies when the instance dies) and whose value is another + // dictionary, keyed on the fielddef token with values that are storage for the actual field values. + // + // for reference types, the storage just stores it as an object. For valuetypes and + // primitives, the storage stores the value as a boxed value. + // + // The whole thing is basically a ConditionalWeakTable> but + // with locking on the inner dictionary. + // + + // This should behave somewhat like EditAndContinueModule::ResolveOrAddField (and EnCAddedField::Allocate) + // we want to create some storage space that has the same lifetime as the instance object. + + // // TODO: should the linker keep this if Hot Reload stuff is enabled? Hot Reload is predicated on the linker not rewriting user modules, but maybe trimming SPC is ok? + internal static FieldStore GetInstanceFieldFieldStore(object inst, RuntimeTypeHandle type, uint fielddef_token) + => _singleton.GetOrCreateInstanceFields(inst).LookupOrAdd(type, fielddef_token); + + private static InstanceFieldTable _singleton = new(); + + private ConditionalWeakTable _table; + + private InstanceFieldTable() + { + _table = new(); + } + + private InstanceFields GetOrCreateInstanceFields(object key) + => _table.GetOrCreateValue(key); + + private class InstanceFields + { + private Dictionary _fields; + private object _lock; + + public InstanceFields() + { + _fields = new(); + _lock = new(); + } + + public FieldStore LookupOrAdd(RuntimeTypeHandle type, uint key) + { + if (_fields.TryGetValue(key, out FieldStore? v)) + return v; + lock (_lock) + { + if (_fields.TryGetValue (key, out FieldStore? v2)) + return v2; + + FieldStore s = FieldStore.Create(type); + _fields.Add(key, s); + return s; + } + } + } + +} +#endif + +// This is similar to System.Diagnostics.EditAndContinueHelper in CoreCLR, except instead of +// having the allocation logic in native (see EditAndContinueModule::ResolveOrAllocateField, +// and EnCSyncBlockInfo::ResolveOrAllocateField), the logic is in managed. +// +// Additionally Mono uses this for storing added static fields. +[StructLayout(LayoutKind.Sequential)] +internal class FieldStore +{ + // keep in sync with hot_reload-internals.h + private object? _loc; + + private FieldStore (object? loc) + { + _loc = loc; + } + + public object? Location => _loc; + + public static FieldStore Create (RuntimeTypeHandle type) + { + Type t = Type.GetTypeFromHandle(type) ?? throw new ArgumentException(nameof(type), "Type handle was null"); + object? loc; + if (t.IsPrimitive || t.IsValueType) + loc = RuntimeHelpers.GetUninitializedObject(t); + else if (t.IsClass || t.IsInterface) + loc = null; + else + throw new ArgumentException("EnC: Expected a primitive, valuetype, class or interface field"); + /* FIXME: do we want FieldStore to be pinned? */ + return new FieldStore(loc); + } +} diff --git a/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs b/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs index c62dde6612049..90b612313c19d 100644 --- a/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs +++ b/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs @@ -7,7 +7,7 @@ namespace Mono { - internal unsafe struct RuntimeClassHandle + internal unsafe struct RuntimeClassHandle : IEquatable { private readonly RuntimeStructs.MonoClass* value; @@ -125,7 +125,7 @@ private int GetConstraintsCount() } } - internal struct RuntimeEventHandle + internal struct RuntimeEventHandle : IEquatable { private readonly IntPtr value; @@ -165,7 +165,7 @@ public override int GetHashCode() } } - internal struct RuntimePropertyHandle + internal struct RuntimePropertyHandle : IEquatable { private readonly IntPtr value; diff --git a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs index 5a7bab2f73986..cb1bd0d52d26b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs @@ -167,6 +167,7 @@ private static void CopySlow(Array sourceArray, int sourceIndex, Array destinati Type src_type = sourceArray.GetType().GetElementType()!; Type dst_type = destinationArray.GetType().GetElementType()!; + Type dst_elem_type = dst_type; bool dst_type_vt = dst_type.IsValueType && Nullable.GetUnderlyingType(dst_type) == null; bool src_is_enum = src_type.IsEnum; @@ -199,12 +200,9 @@ private static void CopySlow(Array sourceArray, int sourceIndex, Array destinati { object srcval = sourceArray.GetValueImpl(source_pos + i); - if (!src_type.IsValueType && dst_is_enum) + if (dst_type_vt && (srcval == null || (src_type == typeof(object) && !dst_elem_type.IsAssignableFrom (srcval.GetType())))) throw new InvalidCastException(SR.InvalidCast_DownCastArrayElement); - if (dst_type_vt && (srcval == null || (src_type == typeof(object) && srcval.GetType() != dst_type))) - throw new InvalidCastException(); - try { destinationArray.SetValueRelaxedImpl(srcval, dest_pos + i); diff --git a/src/mono/System.Private.CoreLib/src/System/Math.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Math.Mono.cs index b2bf6baadd57c..eb0024f983e64 100644 --- a/src/mono/System.Private.CoreLib/src/System/Math.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Math.Mono.cs @@ -7,12 +7,6 @@ namespace System { public partial class Math { - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern double Abs(double value); - - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern float Abs(float value); - [MethodImpl(MethodImplOptions.InternalCall)] public static extern double Acos(double d); diff --git a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs index 9f73b99fb6db9..c30bf25582a3a 100644 --- a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -6,7 +6,7 @@ namespace System { - public struct ModuleHandle + public struct ModuleHandle : IEquatable { private readonly IntPtr value; diff --git a/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs index 23f7668e73549..c120455199922 100644 --- a/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { public partial struct Nullable diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Assembly.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Assembly.Mono.cs index 7f48f693a2f19..e59446b10a0d4 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Assembly.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Assembly.Mono.cs @@ -95,8 +95,5 @@ internal static uint GetAssemblyCount() [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern Type InternalGetType(Module? module, string name, bool throwOnError, bool ignoreCase); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void InternalGetAssemblyName(string assemblyFile, out Mono.MonoAssemblyName aname, out string codebase); } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/AssemblyName.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/AssemblyName.Mono.cs index 867cf694cb2c4..fe9a331f86145 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/AssemblyName.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/AssemblyName.Mono.cs @@ -12,47 +12,6 @@ namespace System.Reflection { public partial class AssemblyName { - public AssemblyName(string assemblyName) - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if (assemblyName.Length == 0 || assemblyName[0] == '\0') - throw new ArgumentException(SR.Format_StringZeroLength); - - using (SafeStringMarshal name = RuntimeMarshal.MarshalString(assemblyName)) - { - // TODO: Should use CoreRT AssemblyNameParser - if (!ParseAssemblyName(name.Value, out MonoAssemblyName nativeName, out bool isVersionDefined, out bool isTokenDefined)) - throw new FileLoadException("The assembly name is invalid."); - - try - { - unsafe - { - FillName(&nativeName, null, isVersionDefined, false, isTokenDefined); - } - } - finally - { - RuntimeMarshal.FreeAssemblyName(ref nativeName, false); - } - } - } - - private unsafe byte[]? ComputePublicKeyToken() - { - if (_publicKey == null) - return null; - if (_publicKey.Length == 0) - return Array.Empty(); - - var token = new byte[8]; - fixed (byte* pkt = token) - fixed (byte* pk = _publicKey) - get_public_token(pkt, pk, _publicKey.Length); - return token; - } - internal static AssemblyName Create(IntPtr monoAssembly, string? codeBase) { AssemblyName aname = new AssemblyName(); @@ -119,32 +78,7 @@ internal unsafe void FillName(MonoAssemblyName* native, string? codeBase, bool a } } - private static AssemblyName GetFileInformationCore(string assemblyFile) - { - unsafe - { - Assembly.InternalGetAssemblyName(Path.GetFullPath(assemblyFile), out MonoAssemblyName nativeName, out string? codebase); - - var aname = new AssemblyName(); - try - { - aname.FillName(&nativeName, codebase, true, false, true); - return aname; - } - finally - { - RuntimeMarshal.FreeAssemblyName(ref nativeName, false); - } - } - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern unsafe void get_public_token(byte* token, byte* pubkey, int len); - [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern unsafe MonoAssemblyName* GetNativeName(IntPtr assemblyPtr); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool ParseAssemblyName(IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined); } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs index 919015e8567e3..b66f7d9b89704 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs @@ -258,10 +258,7 @@ public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyB public ModuleBuilder DefineDynamicModule(string name) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException("Empty name is not legal.", nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_InvalidName, nameof(name)); @@ -273,15 +270,13 @@ public ModuleBuilder DefineDynamicModule(string name) public ModuleBuilder? GetDynamicModule(string name) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException("Empty name is not legal.", nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (modules != null) for (int i = 0; i < modules.Length; ++i) if (modules[i].name == name) return modules[i]; + return null; } @@ -326,10 +321,7 @@ internal static Type MakeGenericType(Type gtd, Type[] typeArguments) => [RequiresUnreferencedCode("Types might be removed")] public override Type? GetType(string name, bool throwOnError, bool ignoreCase) { - if (name == null) - throw new ArgumentNullException(name); - if (name.Length == 0) - throw new ArgumentException("Name cannot be empty", nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); Type res = InternalGetType(null, name, throwOnError, ignoreCase); if (res is TypeBuilder) @@ -343,10 +335,7 @@ internal static Type MakeGenericType(Type gtd, Type[] typeArguments) => public override Module? GetModule(string name) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException("Name can't be empty"); + ArgumentException.ThrowIfNullOrEmpty(name); if (modules == null) return null; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.Mono.cs index 4d63c64bdb123..8d4d278b65c1d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.Mono.cs @@ -149,9 +149,18 @@ internal override int GetFieldOffset() internal void SetRVAData(byte[] data) { + attrs = attrs | FieldAttributes.HasFieldRVA; rva_data = (byte[])data.Clone(); } + internal static PackingSize RVADataPackingSize(int size) + { + if ((size % 8) == 0) return PackingSize.Size8; + if ((size % 4) == 0) return PackingSize.Size4; + if ((size % 2) == 0) return PackingSize.Size2; + return PackingSize.Size1; + } + public void SetConstant(object? defaultValue) { RejectIfCreated(); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs index 51edf3f644875..64585857fffc0 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs @@ -819,9 +819,6 @@ public virtual void Emit(OpCode opcode, string str) public virtual void Emit(OpCode opcode, Type cls) { - if (cls != null && cls.IsByRef) - throw new ArgumentException("Cannot get TypeToken for a ByRef type."); - make_room(6); ll_emit(opcode); int token = token_gen.GetToken(cls!, opcode != OpCodes.Ldtoken); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 66816f9ce5bbf..1115440ac1f68 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -148,10 +148,7 @@ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttribut Justification = "Reflection.Emit is not subject to trimming")] private FieldBuilder DefineDataImpl(string name, int size, FieldAttributes attributes) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException("name cannot be empty", nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (global_type_created != null) throw new InvalidOperationException("global fields already created"); if ((size <= 0) || (size >= 0x3f0000)) @@ -165,7 +162,7 @@ private FieldBuilder DefineDataImpl(string name, int size, FieldAttributes attri { TypeBuilder tb = DefineType(typeName, TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Sealed, - typeof(ValueType), null, PackingSize.Size1, size); + typeof(ValueType), null, FieldBuilder.RVADataPackingSize(size), size); tb.CreateType(); datablobtype = tb; } @@ -408,10 +405,7 @@ public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type under [ComVisible(true)] public override Type? GetType(string className, bool throwOnError, bool ignoreCase) { - if (className == null) - throw new ArgumentNullException(nameof(className)); - if (className.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(className)); + ArgumentException.ThrowIfNullOrEmpty(className); TypeBuilder? result = null; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs index 1e73f98f1505f..b2ce581c3e5dd 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs @@ -74,6 +74,7 @@ public sealed partial class TypeBuilder : TypeInfo [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private TypeInfo? created; + private bool is_byreflike_set; private int state; #endregion @@ -273,8 +274,7 @@ public void AddInterfaceImplementation([DynamicallyAccessedMembers(DynamicallyAc { if (interfaceType == null) throw new ArgumentNullException(nameof(interfaceType)); - if (interfaceType.IsByRef) - throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); + check_not_created(); if (interfaces != null) @@ -408,8 +408,7 @@ private TypeBuilder DefineNestedType(string name, TypeAttributes attr, [Dynamica { foreach (Type iface in interfaces) { - if (iface == null) - throw new ArgumentNullException(nameof(interfaces)); + ArgumentNullException.ThrowIfNull(iface, nameof(interfaces)); if (iface.IsByRef) throw new ArgumentException(nameof(interfaces)); } @@ -838,7 +837,7 @@ private bool has_ctor_method() if (parent != null) { if (parent.IsByRef) - throw new ArgumentException(); + throw new NotSupportedException(); if (IsInterface) throw new TypeLoadException(); } @@ -877,17 +876,6 @@ private bool has_ctor_method() } } - if (fields != null) - { - foreach (FieldBuilder fb in fields) - { - if (fb == null) - continue; - if (fb.FieldType.IsByRef) - throw new COMException(); - } - } - if (methods != null) { bool is_concrete = !IsAbstract; @@ -1544,6 +1532,10 @@ public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { attrs |= TypeAttributes.HasSecurity; } + else if (attrname == "System.Runtime.CompilerServices.IsByRefLikeAttribute") + { + is_byreflike_set = true; + } if (cattrs != null) { @@ -1571,8 +1563,7 @@ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type ev if (eventtype == null) throw new ArgumentNullException(nameof(eventtype)); check_not_created(); - if (eventtype.IsByRef) - throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); + EventBuilder res = new EventBuilder(this, name, attributes, eventtype); if (events != null) { @@ -1601,10 +1592,7 @@ public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttribu public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException("Empty name is not legal", nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if ((size <= 0) || (size > 0x3f0000)) throw new ArgumentException("Data size must be > 0 and < 0x3f0000"); check_not_created(); @@ -1616,7 +1604,7 @@ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttribut { TypeBuilder tb = DefineNestedType(typeName, TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout | TypeAttributes.Sealed, - typeof(ValueType), null, PackingSize.Size1, size); + typeof(ValueType), null, FieldBuilder.RVADataPackingSize(size), size); tb.CreateType(); datablobtype = tb; } @@ -1706,9 +1694,8 @@ private void check_created() private static void check_name(string argName, string name) { - if (name == null) - throw new ArgumentNullException(argName); - if (name.Length == 0 || name[0] == ((char)0)) + ArgumentException.ThrowIfNullOrEmpty(name, argName); + if (name[0] == '\0') throw new ArgumentException(SR.Argument_EmptyName, argName); } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs index 973eb43d91ca7..afac9bf5e88da 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs @@ -55,7 +55,8 @@ public static void ApplyUpdate(Assembly assembly, ReadOnlySpan metadataDel private static string InitializeApplyUpdateCapabilities() { - return ApplyUpdateEnabled(justComponentCheck: 1) != 0 ? "Baseline" : string.Empty ; + const string caps = "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition"; + return ApplyUpdateEnabled(justComponentCheck: 1) != 0 ? caps : string.Empty ; } [MethodImpl (MethodImplOptions.InternalCall)] diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 5fbe196a1ab08..c1d33f9e061f4 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -228,10 +228,8 @@ private static void AddPublicNestedTypes(Type type, List types, List types, List - + <_MonoCMakeArgs Include="-DCMAKE_TOOLCHAIN_FILE=$(CrossToolchainFile)" /> + <_MonoCMakeArgs Condition="'$(TargetOS)' == 'Linux' and ('$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'armv6')" Include="-DMONO_ARM_FPU=vfp-hard" /> <_MonoBuildEnv Condition="'$(Platform)' == 'arm64'" Include="TARGET_BUILD_ARCH=arm64" /> <_MonoBuildEnv Condition="'$(Platform)' == 'arm'" Include="TARGET_BUILD_ARCH=arm" /> + <_MonoBuildEnv Condition="'$(Platform)' == 'armv6'" Include="TARGET_BUILD_ARCH=armv6" /> <_MonoBuildEnv Condition="'$(Platform)' == 'arm64'" Include="PKG_CONFIG_PATH=$(MonoCrossDir)/usr/lib/aarch64-linux-gnu/pkgconfig" /> <_MonoBuildEnv Condition="'$(Platform)' == 'arm'" Include="PKG_CONFIG_PATH=$(MonoCrossDir)/usr/lib/arm-linux-gnueabihf/pkgconfig" /> + <_MonoBuildEnv Condition="'$(Platform)' == 'armv6'" Include="PKG_CONFIG_PATH=$(MonoCrossDir)/usr/lib/arm-linux-gnueabihf/pkgconfig" /> + <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-march=armv6zk" /> + <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mcpu=arm1176jzf-s" /> + <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mfpu=vfp" /> + <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mfloat-abi=hard" /> + <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-march=armv6zk" /> + <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mcpu=arm1176jzf-s" /> + <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mfpu=vfp" /> + <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'armv6'" Include="-mfloat-abi=hard" /> @@ -514,11 +525,12 @@ <_LinuxFloatAbi Condition="'$(TargetsAndroid)' != 'true'">hf <_Objcopy>objcopy <_Objcopy Condition="'$(Platform)' == 'arm'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 'armv6'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 's390x'">s390x-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'x86'">i686-linux-$(_LinuxAbi)-$(_Objcopy) - <_Objcopy Condition="'$(TargetsAndroid)' == 'true'">$(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(MonoToolchainPrebuiltOS)/bin/$(_Objcopy) + <_Objcopy Condition="'$(TargetsAndroid)' == 'true'">$(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(MonoToolchainPrebuiltOS)/bin/llvm-objcopy diff --git a/src/mono/mono/arch/amd64/amd64-codegen.h b/src/mono/mono/arch/amd64/amd64-codegen.h index f0ae81aa23d0f..2b1cd7eb2d3c3 100644 --- a/src/mono/mono/arch/amd64/amd64-codegen.h +++ b/src/mono/mono/arch/amd64/amd64-codegen.h @@ -8,7 +8,7 @@ * Dietmar Maurer (dietmar@ximian.com) * Patrik Torstensson * Zalman Stern - * + * * Copyright (C) 2000 Intel Corporation. All rights reserved. * Copyright (C) 2001, 2002 Ximian, Inc. * Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -652,7 +652,7 @@ typedef union { #define amd64_call_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); *(inst)++ = (unsigned char)0xff; amd64_membase_emit ((inst),2, (basereg),(disp)); } while (0) #define amd64_jump_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); *(inst)++ = (unsigned char)0xff; amd64_membase_emit ((inst), 4, (basereg), (disp)); } while (0) - + #define amd64_jump_code_size(inst,target,size) do { \ if (amd64_is_imm32 ((gint64)(target) - (gint64)(inst))) { \ x86_jump_code((inst),(target)); \ @@ -777,7 +777,7 @@ typedef union { } while (0) /* specific SSE opcode defines */ - + #define amd64_sse_xorpd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst),(dreg),(reg), 0x66, 0x0f, 0x57) #define amd64_sse_xorpd_reg_membase(inst,dreg,basereg,disp) emit_sse_reg_membase ((inst),(dreg),(basereg), (disp), 0x66, 0x0f, 0x57) @@ -1203,7 +1203,7 @@ typedef union { //#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_imm((inst),(opc),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0) #define amd64_alu_mem_imm_size(inst,opc,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_alu_mem_imm((inst),(opc),(mem),(imm)); amd64_codegen_post(inst); } while (0) #define amd64_alu_membase_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0) -#define amd64_alu_membase8_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase8_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0) +#define amd64_alu_membase8_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase8_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0) #define amd64_alu_mem_reg_size(inst,opc,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_mem_reg((inst),(opc),(mem),((reg)&0x7)); amd64_codegen_post(inst); } while (0) #define amd64_alu_membase_reg_size(inst,opc,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_membase_reg((inst),(opc),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0) //#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg_reg((inst),(opc),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0) @@ -1475,7 +1475,7 @@ typedef union { #define amd64_fucomi(inst,index) amd64_fucomi_size(inst,index,8) #define amd64_fucomip(inst,index) amd64_fucomip_size(inst,index,8) #define amd64_fld(inst,mem,is_double) amd64_fld_size(inst,mem,is_double,8) -#define amd64_fld_membase(inst,basereg,disp,is_double) amd64_fld_membase_size(inst,basereg,disp,is_double,8) +#define amd64_fld_membase(inst,basereg,disp,is_double) amd64_fld_membase_size(inst,basereg,disp,is_double,8) #define amd64_fld80_mem(inst,mem) amd64_fld80_mem_size(inst,mem,8) #define amd64_fld80_membase(inst,basereg,disp) amd64_fld80_membase_size(inst,basereg,disp,8) #define amd64_fild(inst,mem,is_long) amd64_fild_size(inst,mem,is_long,8) diff --git a/src/mono/mono/arch/arm/arm-codegen.h b/src/mono/mono/arch/arm/arm-codegen.h index eb63f596fc3d0..3f0e9a17b3bb9 100644 --- a/src/mono/mono/arch/arm/arm-codegen.h +++ b/src/mono/mono/arch/arm/arm-codegen.h @@ -27,7 +27,7 @@ typedef unsigned int armword_t; #if defined(_MSC_VER) && !defined(ARM_NOIASM) # define ARM_IASM(_expr) __emit (_expr) #else -# define ARM_IASM(_expr) +# define ARM_IASM(_expr) #endif /* even_scale = rot << 1 */ diff --git a/src/mono/mono/arch/arm/arm-wmmx.h b/src/mono/mono/arch/arm/arm-wmmx.h index 6f2fc785dca9a..b9dc023ce5ab6 100644 --- a/src/mono/mono/arch/arm/arm-wmmx.h +++ b/src/mono/mono/arch/arm/arm-wmmx.h @@ -21,7 +21,7 @@ #if defined(ARM_EMIT) # define WM_EMIT(p, i) ARM_EMIT(p, i) #else -# define WM_EMIT(p, i) +# define WM_EMIT(p, i) #endif enum { diff --git a/src/mono/mono/arch/mips/test.c b/src/mono/mono/arch/mips/test.c index 4f5e1adee1f1d..c7b324f08630d 100644 --- a/src/mono/mono/arch/mips/test.c +++ b/src/mono/mono/arch/mips/test.c @@ -15,7 +15,7 @@ int main (int argc, char *argv[]) { guint32 *code, * p; code = p = (guint32 *) malloc (sizeof (guint32) * 1024); - + mips_add (p, 3, 4, 5); mips_addi (p, 3, 4, 5); mips_addu (p, 3, 4, 5); diff --git a/src/mono/mono/arch/ppc/ppc-codegen.h b/src/mono/mono/arch/ppc/ppc-codegen.h index 83d366acc83ab..a52d17ab767f0 100644 --- a/src/mono/mono/arch/ppc/ppc-codegen.h +++ b/src/mono/mono/arch/ppc/ppc-codegen.h @@ -274,7 +274,7 @@ from 18 November 2002 to 19 December 2002. Special thanks to rodo, lupus, dietmar, miguel, and duncan for patience, and motivation. -The macros found in this file are based on the assembler instructions found +The macros found in this file are based on the assembler instructions found in Motorola and Digital DNA's: "Programming Enviornments Manual For 32-bit Implementations of the PowerPC Architecture" @@ -334,7 +334,7 @@ my and Ximian's copyright to this code. ;) #define ppc_andisd(c,S,A,ui) ppc_emit32(c, (29 << 26) | ((S) << 21 ) | ((A) << 16) | ((guint16)(ui))) #define ppc_bcx(c,BO,BI,BD,AA,LK) ppc_emit32(c, (16 << 26) | ((BO) << 21 )| ((BI) << 16) | (BD << 2) | ((AA) << 1) | LK) -#define ppc_bc(c,BO,BI,BD) ppc_bcx(c,BO,BI,BD,0,0) +#define ppc_bc(c,BO,BI,BD) ppc_bcx(c,BO,BI,BD,0,0) #define ppc_bca(c,BO,BI,BD) ppc_bcx(c,BO,BI,BD,1,0) #define ppc_bcl(c,BO,BI,BD) ppc_bcx(c,BO,BI,BD,0,1) #define ppc_bcla(c,BO,BI,BD) ppc_bcx(c,BO,BI,BD,1,1) @@ -400,15 +400,15 @@ my and Ximian's copyright to this code. ;) #define ppc_eqv(c,A,S,B) ppc_eqvx(c,A,S,B,0) #define ppc_eqvd(c,A,S,B) ppc_eqvx(c,A,S,B,1) -#define ppc_extsbx(c,A,S,Rc) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (0 << 11) | (954 << 1) | Rc) +#define ppc_extsbx(c,A,S,Rc) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (0 << 11) | (954 << 1) | Rc) #define ppc_extsb(c,A,S) ppc_extsbx(c,A,S,0) #define ppc_extsbd(c,A,S) ppc_extsbx(c,A,S,1) -#define ppc_extshx(c,A,S,Rc) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (0 << 11) | (922 << 1) | Rc) +#define ppc_extshx(c,A,S,Rc) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (0 << 11) | (922 << 1) | Rc) #define ppc_extsh(c,A,S) ppc_extshx(c,A,S,0) #define ppc_extshd(c,A,S) ppc_extshx(c,A,S,1) -#define ppc_fabsx(c,D,B,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (0 << 16) | (B << 11) | (264 << 1) | Rc) +#define ppc_fabsx(c,D,B,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (0 << 16) | (B << 11) | (264 << 1) | Rc) #define ppc_fabs(c,D,B) ppc_fabsx(c,D,B,0) #define ppc_fabsd(c,D,B) ppc_fabsx(c,D,B,1) @@ -441,11 +441,11 @@ my and Ximian's copyright to this code. ;) #define ppc_fmaddx(c,D,A,B,C,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (A << 16) | (B << 11) | (C << 6) | (29 << 1) | Rc) #define ppc_fmadd(c,D,A,B,C) ppc_fmaddx(c,D,A,B,C,0) -#define ppc_fmaddd(c,D,A,B,C) ppc_fmaddx(c,D,A,B,C,1) +#define ppc_fmaddd(c,D,A,B,C) ppc_fmaddx(c,D,A,B,C,1) #define ppc_fmaddsx(c,D,A,B,C,Rc) ppc_emit32(c, (59 << 26) | (D << 21) | (A << 16) | (B << 11) | (C << 6) | (29 << 1) | Rc) #define ppc_fmadds(c,D,A,B,C) ppc_fmaddsx(c,D,A,B,C,0) -#define ppc_fmaddsd(c,D,A,B,C) ppc_fmaddsx(c,D,A,B,C,1) +#define ppc_fmaddsd(c,D,A,B,C) ppc_fmaddsx(c,D,A,B,C,1) #define ppc_fmrx(c,D,B,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (0 << 16) | (B << 11) | (72 << 1) | Rc) #define ppc_fmr(c,D,B) ppc_fmrx(c,D,B,0) @@ -459,11 +459,11 @@ my and Ximian's copyright to this code. ;) #define ppc_fmsubs(c,D,A,C,B) ppc_fmsubsx(c,D,A,C,B,0) #define ppc_fmsubsd(c,D,A,C,B) ppc_fmsubsx(c,D,A,C,B,1) -#define ppc_fmulx(c,D,A,C,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (A << 16) | (0 << 11) | (C << 6) | (25 << 1) | Rc) +#define ppc_fmulx(c,D,A,C,Rc) ppc_emit32(c, (63 << 26) | (D << 21) | (A << 16) | (0 << 11) | (C << 6) | (25 << 1) | Rc) #define ppc_fmul(c,D,A,C) ppc_fmulx(c,D,A,C,0) #define ppc_fmuld(c,D,A,C) ppc_fmulx(c,D,A,C,1) -#define ppc_fmulsx(c,D,A,C,Rc) ppc_emit32(c, (59 << 26) | (D << 21) | (A << 16) | (0 << 11) | (C << 6) | (25 << 1) | Rc) +#define ppc_fmulsx(c,D,A,C,Rc) ppc_emit32(c, (59 << 26) | (D << 21) | (A << 16) | (0 << 11) | (C << 6) | (25 << 1) | Rc) #define ppc_fmuls(c,D,A,C) ppc_fmulsx(c,D,A,C,0) #define ppc_fmulsd(c,D,A,C) ppc_fmulsx(c,D,A,C,1) @@ -689,9 +689,9 @@ my and Ximian's copyright to this code. ;) #define ppc_stfiwx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (983 << 1) | 0) #define ppc_stfsu(c,S,d,A) ppc_emit32(c, (53 << 26) | (S << 21) | (A << 16) | (guint16)(d)) -#define ppc_stfsux(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (695 << 1) | 0) -#define ppc_stfsx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (663 << 1) | 0) -#define ppc_sthbrx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (918 << 1) | 0) +#define ppc_stfsux(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (695 << 1) | 0) +#define ppc_stfsx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (663 << 1) | 0) +#define ppc_sthbrx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (918 << 1) | 0) #define ppc_sthu(c,S,d,A) ppc_emit32(c, (45 << 26) | (S << 21) | (A << 16) | (guint16)(d)) #define ppc_sthux(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (439 << 1) | 0) #define ppc_sthx(c,S,A,B) ppc_emit32(c, (31 << 26) | (S << 21) | (A << 16) | (B << 11) | (407 << 1) | 0) diff --git a/src/mono/mono/arch/s390x/s390x-codegen.h b/src/mono/mono/arch/s390x/s390x-codegen.h index ec9562a0e0474..cd96c9f2f331f 100644 --- a/src/mono/mono/arch/s390x/s390x-codegen.h +++ b/src/mono/mono/arch/s390x/s390x-codegen.h @@ -254,7 +254,7 @@ typedef struct { short op; short m1 : 4; short ri2 : 12; - short i3; + short i3; } MII_Format; typedef struct { @@ -569,7 +569,7 @@ typedef struct { char op; char l1 : 4; char l2 : 4; - short b1 : 4; + short b1 : 4; short d1 : 12; short b2 : 4; short d2 : 12; @@ -579,21 +579,21 @@ typedef struct { char op; char r1 : 4; char r3 : 4; - short b1 : 4; + short b1 : 4; short d1 : 12; short b2 : 4; short d2 : 12; -} __attribute__ ((__packed__)) SS_Format_3; +} __attribute__ ((__packed__)) SS_Format_3; typedef struct { char op; char r1 : 4; char r3 : 4; - short b2 : 4; + short b2 : 4; short d2 : 12; short b4 : 4; short d4 : 12; -} __attribute__ ((__packed__)) SS_Format_4; +} __attribute__ ((__packed__)) SS_Format_4; typedef struct { short op; @@ -814,7 +814,7 @@ typedef struct { #define S390_RR(c,opc,g1,g2) s390_emit16(c, (opc << 8 | (g1) << 4 | g2)) -#define S390_RRE(c,opc,g1,g2) s390_emit32(c, (opc << 16 | (g1) << 4 | g2)) +#define S390_RRE(c,opc,g1,g2) s390_emit32(c, (opc << 16 | (g1) << 4 | g2)) #define S390_RRF_1(c,opc,g1,g2,g3) s390_emit32(c, (opc << 16 | (g3) << 12 | (g1) << 4 | g2)) @@ -841,7 +841,7 @@ typedef struct { (opc & 0xff))); \ } while (0) -#define S390_RS_1(c,opc,g1,g3,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (g3) << 16 | (s2) << 12 | ((p2) & 0xfff))) +#define S390_RS_1(c,opc,g1,g3,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (g3) << 16 | (s2) << 12 | ((p2) & 0xfff))) #define S390_RS_2(c,opc,g1,k3,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (k3) << 16 | (s2) << 12 | ((p2) & 0xfff))) @@ -1450,7 +1450,7 @@ typedef struct { #define s390_msr(c, r1, r2) S390_RRE(c, 0xb252, r1, r2) #define s390_msrkc(c, r1, r2, r3) S390_RRF_1(c, 0xb9fd, r1, r2, r3) #define s390_mvc(c, l, b1, d1, b2, d2) S390_SS_1(c, 0xd2, l, b1, d1, b2, d2) -#define s390_mvghi(c, b1, d1, i2) S390_SIL(c, 0xe548, b1, d1, i2) +#define s390_mvghi(c, b1, d1, i2) S390_SIL(c, 0xe548, b1, d1, i2) #define s390_mvcl(c, r1, r2) S390_RR(c, 0x0e, r1, r2) #define s390_mvcle(c, r1, r3, d2, b2) S390_RS_1(c, 0xa8, r1, r3, d2, b2) #define s390_mvi(c, b, d, v) S390_SI(c, 0x92, b, d, v) @@ -1459,14 +1459,14 @@ typedef struct { #define s390_ng(c, r, x, b, d) S390_RXY(c, 0xe380, r, x, b, d) #define s390_ngr(c, r1, r2) S390_RRE(c, 0xb980, r1, r2) #define s390_ngrk(c, r1, r2, r3) S390_RRF_1(c, 0xb9e4, r1, r2, r3) -#define s390_ni(c, b, d, v) S390_SI(c, 0x94, b, d, v) +#define s390_ni(c, b, d, v) S390_SI(c, 0x94, b, d, v) #define s390_nihf(c, r, v) S390_RIL_1(c, 0xc0a, r, v) #define s390_nihh(c, r, v) S390_RI(c, 0xa54, r, v) #define s390_nihl(c, r, v) S390_RI(c, 0xa55, r, v) #define s390_nilf(c, r, v) S390_RIL_1(c, 0xc0b, r, v) #define s390_nilh(c, r, v) S390_RI(c, 0xa56, r, v) #define s390_nill(c, r, v) S390_RI(c, 0xa57, r, v) -#define s390_niy(c, b, d, v) S390_SIY(c, 0xeb54, b, d, v) +#define s390_niy(c, b, d, v) S390_SIY(c, 0xeb54, b, d, v) #define s390_nop(c) S390_RR(c, 0x07, 0x0, 0) #define s390_mem(c) S390_RR(c, 0x07, 0xe, 0) #define s390_nr(c, r1, r2) S390_RR(c, 0x14, r1, r2) @@ -1479,7 +1479,7 @@ typedef struct { #define s390_oilf(c, r, v) S390_RIL_1(c, 0xc0d, r, v) #define s390_oilh(c, r, v) S390_RI(c, 0xa5a, r, v) #define s390_oill(c, r, v) S390_RI(c, 0xa5b, r, v) -#define s390_oiy(c, b, d, v) S390_SIY(c, 0xeb56 b, d, v) +#define s390_oiy(c, b, d, v) S390_SIY(c, 0xeb56 b, d, v) #define s390_og(c, r, x, b, d) S390_RXY(c, 0xe381, r, x, b, d) #define s390_ogr(c, r1, r2) S390_RRE(c, 0xb981, r1, r2) #define s390_ogrk(c, r1, r2, r3) S390_RRF_1(c, 0xb9e6, r1, r2, r3) @@ -1497,13 +1497,13 @@ typedef struct { #define s390_sgr(c, r1, r2) S390_RRE(c, 0xb909, r1, r2) #define s390_sgrk(c, r1, r2, r3) S390_RRF_1(c, 0xb9e9, r1, r2, r3) #define s390_sl(c, r, x, b, d) S390_RX(c, 0x5f, r, x, b, d) -#define s390_sla(c, r, b, d) S390_RS_3(c, 0x8b, r, b, d) -#define s390_slag(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0b, r1, r2, b, d) +#define s390_sla(c, r, b, d) S390_RS_3(c, 0x8b, r, b, d) +#define s390_slag(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0b, r1, r2, b, d) #define s390_slbg(c, r, x, b, d) S390_RXY(c, 0xe389, r, x, b, d) #define s390_slbgr(c, r1, r2) S390_RRE(c, 0xb989, r1, r2) #define s390_slbr(c, r1, r2) S390_RRE(c, 0xb999, r1, r2) -#define s390_slda(c, r, b, d) S390_RS_3(c, 0x8f, r, b, d) -#define s390_sldl(c, r, b, d) S390_RS_3(c, 0x8d, r, b, d) +#define s390_slda(c, r, b, d) S390_RS_3(c, 0x8f, r, b, d) +#define s390_sldl(c, r, b, d) S390_RS_3(c, 0x8d, r, b, d) #define s390_slfi(c, r, v) S390_RIL_1(c, 0xc25, r, v) #define s390_slg(c, r, x, b, d) S390_RXY(c, 0xe30b, r, x, b, d) #define s390_slgf(c, r, x, b, d) S390_RXY(c, 0xe31b, r, x, b, d) @@ -1511,20 +1511,20 @@ typedef struct { #define s390_slgfi(c, r, v) S390_RIL_1(c, 0xc24, r, v) #define s390_slgr(c, r1, r2) S390_RRE(c, 0xb90b, r1, r2) #define s390_slgrk(c, r1, r2, r3) S390_RRF_1(c, 0xb9eb, r1, r2, r3) -#define s390_sll(c, r, b, d) S390_RS_3(c, 0x89, r, b, d) -#define s390_sllg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0d, r1, r2, b, d) +#define s390_sll(c, r, b, d) S390_RS_3(c, 0x89, r, b, d) +#define s390_sllg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0d, r1, r2, b, d) #define s390_slr(c, r1, r2) S390_RR(c, 0x1f, r1, r2) #define s390_slrk(c, r1, r2, r3) S390_RRF_1(c, 0xb9fb, r1, r2, r3) #define s390_sqdbr(c, r1, r2) S390_RRE(c, 0xb315, r1, r2) #define s390_sqebr(c, r1, r2) S390_RRE(c, 0xb314, r1, r2) -#define s390_sra(c, r, b, d) S390_RS_3(c, 0x8a, r, b, d) -#define s390_srag(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0a, r1, r2, b, d) +#define s390_sra(c, r, b, d) S390_RS_3(c, 0x8a, r, b, d) +#define s390_srag(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0a, r1, r2, b, d) #define s390_sr(c, r1, r2) S390_RR(c, 0x1b, r1, r2) -#define s390_srda(c, r, b, d) S390_RS_3(c, 0x8e, r, b, d) -#define s390_srdl(c, r, b, d) S390_RS_3(c, 0x8c, r, b, d) +#define s390_srda(c, r, b, d) S390_RS_3(c, 0x8e, r, b, d) +#define s390_srdl(c, r, b, d) S390_RS_3(c, 0x8c, r, b, d) #define s390_srk(c, r1, r2, r3) S390_RRF_1(c, 0xb9f9, r1, r2, r3) -#define s390_srl(c, r, b, d) S390_RS_3(c, 0x88, r, b, d) -#define s390_srlg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0c, r1, r2, b, d) +#define s390_srl(c, r, b, d) S390_RS_3(c, 0x88, r, b, d) +#define s390_srlg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0c, r1, r2, b, d) #define s390_st(c, r, x, b, d) S390_RX(c, 0x50, r, x, b, d) #define s390_stam(c, r1, r2, b, d) S390_RS_1(c, 0x9b, r1, r2, b, d) #define s390_stamy(c, r1, r2, b, d) S390_RSY_1(c, 0xeb9b, r1, r2, b, d) diff --git a/src/mono/mono/arch/s390x/tramp.c b/src/mono/mono/arch/s390x/tramp.c index 376970c4ab60b..9d38d9380b93e 100644 --- a/src/mono/mono/arch/s390x/tramp.c +++ b/src/mono/mono/arch/s390x/tramp.c @@ -59,7 +59,7 @@ typedef struct { local_size, code_size, retStruct; -} size_data; +} size_data; /*========================= End of Typedefs ========================*/ @@ -78,14 +78,14 @@ add_general (guint *gr, size_data *sz, gboolean simple) if (simple) { if (*gr >= GENERAL_REGS) { sz->stack_size += sizeof(long); - sz->code_size += 12; + sz->code_size += 12; } else { - sz->code_size += 8; + sz->code_size += 8; } } else { if (*gr >= GENERAL_REGS - 1) { sz->stack_size += 8 + (sz->stack_size % 8); - sz->code_size += 10; + sz->code_size += 10; } else { sz->code_size += 8; } @@ -108,7 +108,7 @@ add_general (guint *gr, size_data *sz, gboolean simple) /*------------------------------------------------------------------*/ static void inline -calculate_sizes (MonoMethodSignature *sig, size_data *sz, +calculate_sizes (MonoMethodSignature *sig, size_data *sz, gboolean string_ctor) { guint i, fr, gr, size; @@ -166,7 +166,7 @@ calculate_sizes (MonoMethodSignature *sig, size_data *sz, goto enum_retvalue; } gr++; - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (sig->ret->data.klass, &align); else size = mono_class_value_size (sig->ret->data.klass, &align); @@ -235,7 +235,7 @@ calculate_sizes (MonoMethodSignature *sig, size_data *sz, simpletype = sig->params [i]->data.klass->enum_basetype->type; goto enum_calc_size; } - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (sig->params [i]->data.klass, &align); else size = mono_class_value_size (sig->params [i]->data.klass, &align); @@ -290,9 +290,9 @@ calculate_sizes (MonoMethodSignature *sig, size_data *sz, /* align stack size to 8 */ DEBUG (printf (" stack size: %d (%d)\n" - " code size: %d\n" + " code size: %d\n" " local size: %d\n", - (sz->stack_size + 8) & ~8, sz->stack_size, + (sz->stack_size + 8) & ~8, sz->stack_size, (sz->code_size),(sz->local_size + 8) & ~8)); sz->stack_size = (sz->stack_size + 8) & ~8; sz->local_size = (sz->local_size + 8) & ~8; @@ -342,7 +342,7 @@ emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz) /* */ /* Name - emit_save_parameters */ /* */ -/* Function - Create the instructions that load registers with */ +/* Function - Create the instructions that load registers with */ /* parameters, place others on the stack according */ /* to the S/390 ABI. */ /* */ @@ -355,12 +355,12 @@ emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz) inline static guint8* emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) { - guint i, fr, gr, act_strs, align, + guint i, fr, gr, act_strs, align, stack_par_pos, size, local_pos; guint32 simpletype; /*----------------------------------------------------------*/ - /* If a structure on stack is being returned, reserve r2 */ + /* If a structure on stack is being returned, reserve r2 */ /* to point to an area where it can be passed. */ /*----------------------------------------------------------*/ if (sz->retStruct) @@ -423,7 +423,7 @@ emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) simpletype = sig->params [i]->data.klass->enum_basetype->type; goto enum_calc_size; } - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (sig->params [i]->data.klass, &align); else size = mono_class_value_size (sig->params [i]->data.klass, &align); @@ -455,7 +455,7 @@ emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, s390_r10, 0); stack_par_pos += sizeof(long long); } - break; + break; default: if (size <= 256) { local_pos += (local_pos % align); @@ -488,12 +488,12 @@ emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) break; case MONO_TYPE_I8: if (gr < GENERAL_REGS) { - s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); + s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); gr += 2; } else { *(guint32 *) p += 7; *(guint32 *) p &= ~7; - s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG); + s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG); stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long)); } break; @@ -523,7 +523,7 @@ emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) } /*----------------------------------------------------------*/ - /* If we're returning a structure but not in a register */ + /* If we're returning a structure but not in a register */ /* then point the result area for the called routine */ /*----------------------------------------------------------*/ if (sz->retStruct) { @@ -574,14 +574,14 @@ alloc_code_memory (guint code_size) /*------------------------------------------------------------------*/ static guint8 * -emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, +emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, size_data *sz, gboolean string_ctor) { guint32 simpletype; guint retSize, align; /* call "callme" */ - s390_basr (p, s390_r14, s390_r9); + s390_basr (p, s390_r14, s390_r9); /* get return value */ if (m_type_is_byref (sig->ret) || string_ctor) { @@ -625,7 +625,7 @@ emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, simpletype = sig->ret->data.klass->enum_basetype->type; goto enum_retvalue; } - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) retSize = mono_class_native_size (sig->ret->data.klass, &align); else retSize = mono_class_value_size (sig->ret->data.klass, &align); @@ -655,7 +655,7 @@ printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke); case MONO_TYPE_VOID: break; default: - g_error ("Can't handle as return value 0x%x", + g_error ("Can't handle as return value 0x%x", sig->ret->type); } } @@ -803,12 +803,12 @@ mono_arch_create_method_pointer (MonoMethod *method) p = code_buffer = g_malloc (sz.code_size); - DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", + DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", method->name,p)); - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* prolog */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS); s390_lgr (p, s390_r0, STK_BASE); @@ -820,9 +820,9 @@ mono_arch_create_method_pointer (MonoMethod *method) s390_lghi(p, s390_r11, 0); s390_mvcl(p, s390_r8, s390_r10); - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* Let's fill MonoInvocation - first zero some fields */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_lghi (p, s390_r0, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex))); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler))); @@ -830,15 +830,15 @@ mono_arch_create_method_pointer (MonoMethod *method) s390_lghi (p, s390_r0, 1); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap))); - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* set method pointer */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, method); s390_lg (p, s390_r0, 0, s390_r13, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method))); - local_start = local_pos = MINV_POS + + local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); this_flag = (sig->hasthis ? 1 : 0); @@ -848,7 +848,7 @@ mono_arch_create_method_pointer (MonoMethod *method) /* area. If necessary save this hidden parameter for later */ /*----------------------------------------------------------*/ if (MONO_TYPE_ISSTRUCT(sig->ret)) { - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) retSize = mono_class_native_size (sig->ret->data.klass, &align); else retSize = mono_class_value_size (sig->ret->data.klass, &align); @@ -870,13 +870,13 @@ mono_arch_create_method_pointer (MonoMethod *method) } if (this_flag) { - s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, + s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); reg_param++; } else { s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos); local_pos += sizeof(int); - s390_stg (p, s390_r0, 0, STK_BASE, + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); } @@ -888,9 +888,9 @@ mono_arch_create_method_pointer (MonoMethod *method) s390_std (p, s390_f2, 0, STK_BASE, local_pos); local_pos += sizeof(double); - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* prepare space for valuetypes */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ vt_cur = local_pos; vtbuf = alloca (sizeof(int)*sig->param_count); cpos = 0; @@ -904,7 +904,10 @@ mono_arch_create_method_pointer (MonoMethod *method) if (klass->enumtype) continue; - size = mono_class_native_size (klass, &align); + if (sig->pinvoke && !sig->marshalling_disabled) + size = mono_class_native_size (sig->ret->data.klass, &align); + else + size = mono_class_value_size (sig->ret->data.klass, &align); cpos += align - 1; cpos &= ~(align - 1); vtbuf [i] = cpos; @@ -916,16 +919,16 @@ mono_arch_create_method_pointer (MonoMethod *method) local_pos += cpos; - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* set MonoInvocation::stack_args */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args))); - /*----------------------------------------------------------*/ - /* add stackval arguments */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ + /* add stackval arguments */ + /*----------------------------------------------------------*/ for (i = 0; i < sig->param_count; ++i) { if (m_type_is_byref (sig->params [i])) { ADD_ISTACK_PARM(0, 1); @@ -947,7 +950,7 @@ mono_arch_create_method_pointer (MonoMethod *method) simple_type = sig->params [i]->data.klass->enum_basetype->type; goto enum_savechk; } - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) parSize = mono_class_native_size (sig->params [i]->data.klass, &align); else parSize = mono_class_value_size (sig->params [i]->data.klass, &align); @@ -969,7 +972,7 @@ mono_arch_create_method_pointer (MonoMethod *method) ADD_ISTACK_PARM(0, 1); } } - + if (vtbuf [i] >= 0) { s390_la (p, s390_r3, 0, STK_BASE, vt_cur); s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos); @@ -996,17 +999,17 @@ mono_arch_create_method_pointer (MonoMethod *method) /* fixme: alignment */ DEBUG (printf ("arg_pos %d --> ", arg_pos)); - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) arg_pos += mono_type_native_stack_size (sig->params [i], &align); else arg_pos += mono_type_stack_size (sig->params [i], &align); - + DEBUG (printf ("%d\n", stackval_arg_pos)); } - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* Set return area pointer. */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos); s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); if (sig->ret->type == MONO_TYPE_VALUETYPE && !m_type_is_byref (sig->ret)) { @@ -1018,18 +1021,18 @@ mono_arch_create_method_pointer (MonoMethod *method) } } - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* call ves_exec_method */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, ves_exec_method); s390_lg (p, s390_r1, 0, s390_r13, 0); s390_la (p, s390_r2, 0, STK_BASE, MINV_POS); s390_basr (p, s390_r14, s390_r1); - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* move retval from stackval to proper place (r3/r4/...) */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,m_type_is_byref (sig->ret))); if (m_type_is_byref (sig->ret)) { DEBUG (printf ("ret by ref\n")); @@ -1081,15 +1084,15 @@ mono_arch_create_method_pointer (MonoMethod *method) s390_llong(p, stackval_to_data); s390_lg (p, s390_r2, 0, s390_r13, 0); s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); - if (sz.retStruct) { + if (sz.retStruct) { /*------------------------------------------*/ /* Get stackval_to_data to set result area */ /*------------------------------------------*/ s390_lgr (p, s390_r4, s390_r8); - } else { + } else { /*------------------------------------------*/ /* Give stackval_to_data a temp result area */ - /*------------------------------------------*/ + /*------------------------------------------*/ s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos); } s390_lg (p, s390_r5, 0,s390_r13, 4); @@ -1118,15 +1121,15 @@ mono_arch_create_method_pointer (MonoMethod *method) } break; default: - g_error ("Type 0x%x not handled yet in thunk creation", + g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); break; } } - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ /* epilog */ - /*----------------------------------------------------------*/ + /*----------------------------------------------------------*/ s390_lg (p, STK_BASE, 0, STK_BASE, 0); s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); diff --git a/src/mono/mono/arch/sparc/sparc-codegen.h b/src/mono/mono/arch/sparc/sparc-codegen.h index eb421bbcf9a6f..b8c478c473bbd 100644 --- a/src/mono/mono/arch/sparc/sparc-codegen.h +++ b/src/mono/mono/arch/sparc/sparc-codegen.h @@ -224,7 +224,7 @@ typedef enum { sparc_membar_store_load = 0x2, sparc_membar_load_store = 0x4, sparc_membar_store_store = 0x8, - + sparc_membar_lookaside = 0x10, sparc_membar_memissue = 0x20, sparc_membar_sync = 0x40, @@ -680,9 +680,9 @@ typedef struct { #define sparc_faddd(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_faddd_val, r2, dest ) #define sparc_faddq(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_faddq_val, r2, dest ) -#define sparc_fsubs(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubs_val, r2, dest ) -#define sparc_fsubd(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubd_val, r2, dest ) -#define sparc_fsubq(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubq_val, r2, dest ) +#define sparc_fsubs(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubs_val, r2, dest ) +#define sparc_fsubd(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubd_val, r2, dest ) +#define sparc_fsubq(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubq_val, r2, dest ) #define sparc_fmuls( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fmuls_val, r2, dest ) #define sparc_fmuld( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fmuld_val, r2, dest ) @@ -735,7 +735,7 @@ typedef struct { #define sparc_fcmpq( ins, r1, r2 ) sparc_fcmp( ins, r1, sparc_fcmpq_val, r2 ) #define sparc_fcmpes( ins, r1, r2 ) sparc_fcmpes( ins, r1, sparc_fcmpes_val, r2 ) #define sparc_fcmped( ins, r1, r2 ) sparc_fcmped( ins, r1, sparc_fcmped_val, r2 ) -#define sparc_fcmpeq( ins, r1, r2 ) sparc_fcmpeq( ins, r1, sparc_fcmpeq_val, r2 ) +#define sparc_fcmpeq( ins, r1, r2 ) sparc_fcmpeq( ins, r1, sparc_fcmpeq_val, r2 ) /* logical */ diff --git a/src/mono/mono/arch/sparc/test.c b/src/mono/mono/arch/sparc/test.c index 0d4ad1869b99e..8bfeb56544c57 100644 --- a/src/mono/mono/arch/sparc/test.c +++ b/src/mono/mono/arch/sparc/test.c @@ -35,8 +35,8 @@ main () ++cur_out_reg; sparc_ld_imm (p, sparc_i3, arg_pos+4, cur_out_reg); ++cur_out_reg; - /* - * Insert call to function + /* + * Insert call to function */ sparc_jmpl (p, sparc_i0, 0, sparc_callsite); sparc_nop (p); diff --git a/src/mono/mono/arch/x86/x86-codegen.h b/src/mono/mono/arch/x86/x86-codegen.h index 86a051cbcc939..c4edb3c1e2d62 100644 --- a/src/mono/mono/arch/x86/x86-codegen.h +++ b/src/mono/mono/arch/x86/x86-codegen.h @@ -7,7 +7,7 @@ * Sergey Chaban (serge@wildwestsoftware.com) * Dietmar Maurer (dietmar@ximian.com) * Patrik Torstensson - * + * * Copyright (C) 2000 Intel Corporation. All rights reserved. * Copyright (C) 2001, 2002 Ximian, Inc. * Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -151,7 +151,7 @@ enum { typedef enum { X86_LOCK_PREFIX = 0xF0, X86_REPNZ_PREFIX = 0xF2, - X86_REPZ_PREFIX = 0xF3, + X86_REPZ_PREFIX = 0xF3, X86_REP_PREFIX = 0xF3, X86_CS_PREFIX = 0x2E, X86_SS_PREFIX = 0x36, @@ -165,7 +165,7 @@ typedef enum { X86_ADDRESS_PREFIX = 0x67 } X86_Prefix; -static const unsigned char +static const unsigned char x86_cc_unsigned_map [X86_NCC] = { 0x74, /* eq */ 0x75, /* ne */ @@ -181,7 +181,7 @@ x86_cc_unsigned_map [X86_NCC] = { 0x71, /* no */ }; -static const unsigned char +static const unsigned char x86_cc_signed_map [X86_NCC] = { 0x74, /* eq */ 0x75, /* ne */ @@ -239,10 +239,10 @@ typedef union { // | var[n_arg] | // | var[n_arg+1] | local variables area // | . . . | -// | var[n_var-1] | +// | var[n_var-1] | // +--------------------------------+ // | | -// | | +// | | // | spill area | area for spilling mimic stack // | | // +--------------------------------| @@ -453,7 +453,7 @@ mono_x86_patch_inline (guchar* code, gpointer target) x86_byte (inst, 0xb1); \ x86_reg_emit ((inst), (reg), (dreg)); \ } while (0) - + #define x86_cmpxchg_mem_reg(inst,mem,reg) \ do { \ x86_codegen_pre(&(inst), 7); \ @@ -461,7 +461,7 @@ mono_x86_patch_inline (guchar* code, gpointer target) x86_byte (inst, 0xb1); \ x86_mem_emit ((inst), (reg), (mem)); \ } while (0) - + #define x86_cmpxchg_membase_reg(inst,basereg,disp,reg) \ do { \ x86_codegen_pre(&(inst), 2 + kMaxMembaseEmitPadding); \ @@ -659,7 +659,7 @@ mono_x86_patch_inline (guchar* code, gpointer target) x86_imm_emit32 ((inst), (imm)); \ } \ } while (0) - + #define x86_alu_membase8_imm(inst,opc,basereg,disp,imm) \ do { \ x86_codegen_pre(&(inst), 2 + kMaxMembaseEmitPadding); \ @@ -1597,7 +1597,7 @@ mono_x86_patch_inline (guchar* code, gpointer target) } while (0) #define x86_push_imm_template(inst) x86_push_imm (inst, 0xf0f0f0f0) - + #define x86_push_imm(inst,imm) \ do { \ int _imm = (int) (imm); \ @@ -1952,7 +1952,7 @@ mono_x86_patch_inline (guchar* code, gpointer target) x86_imm_emit16 ((inst), (framesize)); \ x86_byte(inst, 0); \ } while (0) - + #define x86_leave(inst) do { x86_byte (inst, 0xc9); } while (0) #define x86_sahf(inst) do { x86_byte (inst, 0x9e); } while (0) @@ -2040,16 +2040,16 @@ typedef enum { X86_SSE_MOVSHDUP = 0x16, X86_SSE_MOVSLDUP = 0x12, X86_SSE_MOVDDUP = 0x12, - + X86_SSE_PAND = 0xDB, X86_SSE_POR = 0xEB, X86_SSE_PXOR = 0xEF, - + X86_SSE_PADDB = 0xFC, X86_SSE_PADDW = 0xFD, X86_SSE_PADDD = 0xFE, X86_SSE_PADDQ = 0xD4, - + X86_SSE_PSUBB = 0xF8, X86_SSE_PSUBW = 0xF9, X86_SSE_PSUBD = 0xFA, @@ -2064,7 +2064,7 @@ typedef enum { X86_SSE_PMAXUD = 0x3F, /*sse41*/ X86_SSE_PMINSB = 0x38, /*sse41*/ - X86_SSE_PMINSW = 0xEA, + X86_SSE_PMINSW = 0xEA, X86_SSE_PMINSD = 0x39,/*sse41*/ X86_SSE_PMINUB = 0xDA, @@ -2085,9 +2085,9 @@ typedef enum { X86_SSE_PCMPGTQ = 0x37, /*sse42*/ X86_SSE_PSADBW = 0xf6, - + X86_SSE_PSHUFD = 0x70, - + X86_SSE_PUNPCKLBW = 0x60, X86_SSE_PUNPCKLWD = 0x61, X86_SSE_PUNPCKLDQ = 0x62, @@ -2121,14 +2121,14 @@ typedef enum { X86_SSE_PMULUDQ = 0xF4, X86_SSE_PMOVMSKB = 0xD7, - + X86_SSE_PSHIFTW = 0x71, X86_SSE_PSHIFTD = 0x72, X86_SSE_PSHIFTQ = 0x73, X86_SSE_SHR = 2, X86_SSE_SAR = 4, X86_SSE_SHL = 6, - + X86_SSE_PSRLW_REG = 0xD1, X86_SSE_PSRAW_REG = 0xE1, X86_SSE_PSLLW_REG = 0xF1, @@ -2136,7 +2136,7 @@ typedef enum { X86_SSE_PSRLD_REG = 0xD2, X86_SSE_PSRAD_REG = 0xE2, X86_SSE_PSLLD_REG = 0xF2, - + X86_SSE_PSRLQ_REG = 0xD3, X86_SSE_PSLLQ_REG = 0xF3, @@ -2156,7 +2156,7 @@ typedef enum { X86_SSE_PEXTRW = 0xC5, X86_SSE_PEXTRD = 0x16,/*sse41*/ - X86_SSE_SHUFP = 0xC6, + X86_SSE_SHUFP = 0xC6, X86_SSE_CVTDQ2PD = 0xE6, X86_SSE_CVTDQ2PS = 0x5B, diff --git a/src/mono/mono/component/CMakeLists.txt b/src/mono/mono/component/CMakeLists.txt index 595f6d889442b..faab69a9b68e9 100644 --- a/src/mono/mono/component/CMakeLists.txt +++ b/src/mono/mono/component/CMakeLists.txt @@ -41,6 +41,7 @@ list(APPEND components ) set(${MONO_HOT_RELOAD_COMPONENT_NAME}-sources ${MONO_COMPONENT_PATH}/hot_reload.c + ${MONO_COMPONENT_PATH}/hot_reload-internals.h ${MONO_COMPONENT_PATH}/hot_reload.h ) set(${MONO_HOT_RELOAD_COMPONENT_NAME}-stub-sources diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index f9712c5b77e38..d558691594751 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -7012,6 +7012,29 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) buffer_add_assemblyid (buf, mono_get_root_domain (), assembly); break; } + case MDBGPROT_CMD_GET_MODULE_BY_GUID: { + int len = 0; + uint8_t* guid = m_dbgprot_decode_byte_array (p, &p, end, &len); + MonoAssembly *assembly = NULL; + GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies (); + for (int i = 0; i < assemblies->len; ++i) { + MonoAssembly *assemblyOnALC = (MonoAssembly*)g_ptr_array_index (assemblies, i); + if (!memcmp(assemblyOnALC->image->heap_guid.data, guid, len)) { + assembly = assemblyOnALC; + break; + } + } + g_ptr_array_free (assemblies, TRUE); + if (!assembly) { + PRINT_DEBUG_MSG (1, "Could not resolve guid\n"); + g_free (guid); + buffer_add_int (buf, -1); + break; + } + g_free (guid); + buffer_add_moduleid (buf, mono_get_root_domain (), assembly->image); + break; + } default: return ERR_NOT_IMPLEMENTED; } diff --git a/src/mono/mono/component/debugger-agent.h b/src/mono/mono/component/debugger-agent.h index ad5a0cb1d0b1d..8ff34438d54da 100644 --- a/src/mono/mono/component/debugger-agent.h +++ b/src/mono/mono/component/debugger-agent.h @@ -12,7 +12,7 @@ void debugger_agent_add_function_pointers (MonoComponentDebugger* fn_table); -void +void mono_ss_calculate_framecount (void *the_tls, MonoContext *ctx, gboolean force_use_ctx, DbgEngineStackFrame ***frames, int *nframes); void @@ -22,10 +22,10 @@ mono_ss_discard_frame_context (void *the_tls); DebuggerTlsData* mono_wasm_get_tls (void); -void +void mono_init_debugger_agent_for_wasm (int log_level, MonoProfilerHandle *prof); -void +void mono_wasm_save_thread_context (void); #endif @@ -33,10 +33,10 @@ mono_wasm_save_thread_context (void); void mini_wasm_debugger_add_function_pointers (MonoComponentDebugger* fn_table); -MdbgProtErrorCode +MdbgProtErrorCode mono_do_invoke_method (DebuggerTlsData *tls, MdbgProtBuffer *buf, InvokeData *invoke, guint8 *p, guint8 **endp); -MdbgProtErrorCode +MdbgProtErrorCode mono_process_dbg_packet (int id, MdbgProtCommandSet command_set, int command, gboolean *no_reply, guint8 *p, guint8 *end, MdbgProtBuffer *buf); void @@ -45,12 +45,12 @@ mono_dbg_process_breakpoint_events (void *_evts, MonoMethod *method, MonoContext void* mono_dbg_create_breakpoint_events (GPtrArray *ss_reqs, GPtrArray *bp_reqs, MonoJitInfo *ji, MdbgProtEventKind kind); -int +int mono_ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *args); -void +void mono_ss_args_destroy (SingleStepArgs *ss_args); -int +int mono_de_frame_async_id (DbgEngineStackFrame *frame); #endif diff --git a/src/mono/mono/component/debugger-engine.c b/src/mono/mono/component/debugger-engine.c index 5083e3b68c819..ce0cc5eb65745 100644 --- a/src/mono/mono/component/debugger-engine.c +++ b/src/mono/mono/component/debugger-engine.c @@ -807,7 +807,7 @@ mono_de_process_single_step (void *tls, gboolean from_signal) if (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD) goto exit; - /* + /* * FIXME: * Stopping in memset makes half-initialized vtypes visible. * Stopping in memcpy makes half-copied vtypes visible. @@ -999,7 +999,7 @@ mono_de_ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, void *tls, hit = FALSE; } } - + if (loc) { req->last_method = method; req->last_line = loc->row; @@ -1498,7 +1498,7 @@ mono_de_ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, S err = rt_callbacks.handle_multiple_ss_requests (); if (err == DE_ERR_NOT_IMPLEMENTED) { - PRINT_DEBUG_MSG (0, "Received a single step request while the previous one was still active.\n"); + PRINT_DEBUG_MSG (0, "Received a single step request while the previous one was still active.\n"); return DE_ERR_NOT_IMPLEMENTED; } } @@ -1596,7 +1596,7 @@ get_class_to_get_builder_field (DbgEngineStackFrame *frame) if (!this_obj) return NULL; - + context = mono_get_generic_context_from_stack_frame (frame->ji, mono_get_generic_info_from_stack_frame (frame->ji, &the_frame->ctx)); inflated_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (original_class), &context, error); mono_error_assert_ok (error); /* FIXME don't swallow the error */ diff --git a/src/mono/mono/component/debugger-engine.h b/src/mono/mono/component/debugger-engine.h index a3c30d6d995cc..e6e47280e50b0 100644 --- a/src/mono/mono/component/debugger-engine.h +++ b/src/mono/mono/component/debugger-engine.h @@ -107,7 +107,7 @@ #define CMD_TYPE_GET_VALUE_SIZE MDBGPROT_CMD_TYPE_GET_VALUE_SIZE #define CMD_METHOD_GET_NAME MDBGPROT_CMD_METHOD_GET_NAME -#define CMD_METHOD_GET_DECLARING_TYPE MDBGPROT_CMD_METHOD_GET_DECLARING_TYPE +#define CMD_METHOD_GET_DECLARING_TYPE MDBGPROT_CMD_METHOD_GET_DECLARING_TYPE #define CMD_METHOD_GET_DEBUG_INFO MDBGPROT_CMD_METHOD_GET_DEBUG_INFO #define CMD_METHOD_GET_PARAM_INFO MDBGPROT_CMD_METHOD_GET_PARAM_INFO #define CMD_METHOD_GET_LOCALS_INFO MDBGPROT_CMD_METHOD_GET_LOCALS_INFO @@ -263,7 +263,7 @@ #define FRAME_FLAG_DEBUGGER_INVOKE MDBGPROT_FRAME_FLAG_DEBUGGER_INVOKE #define FRAME_FLAG_NATIVE_TRANSITION MDBGPROT_FRAME_FLAG_NATIVE_TRANSITION -/* +/* * Contains information about an inserted breakpoint. */ typedef struct { @@ -284,7 +284,7 @@ typedef struct { /* Unique id used in the wire protocol to refer to objects */ int id; /* - * A weakref gc handle pointing to the object. The gc handle is used to + * A weakref gc handle pointing to the object. The gc handle is used to * detect if the object was garbage collected. */ MonoGCHandle handle; @@ -403,5 +403,5 @@ void win32_debugger_log(FILE *stream, const gchar *format, ...); #define PRINT_MSG(...) g_print (__VA_ARGS__) #endif -void +void mono_de_init(DebuggerEngineCallbacks* cbs); diff --git a/src/mono/mono/component/debugger-mono-compat.h b/src/mono/mono/component/debugger-mono-compat.h index 0492a71f3468c..565dc81b2fb93 100644 --- a/src/mono/mono/component/debugger-mono-compat.h +++ b/src/mono/mono/component/debugger-mono-compat.h @@ -18,4 +18,4 @@ dbg_rt_atomic_inc_int32_t (volatile int32_t *value) return (int32_t)mono_atomic_inc_i32 ((volatile gint32 *)value); } -#endif \ No newline at end of file +#endif diff --git a/src/mono/mono/component/debugger-protocol.c b/src/mono/mono/component/debugger-protocol.c index 2fe3096608a51..a63b92d1ee381 100644 --- a/src/mono/mono/component/debugger-protocol.c +++ b/src/mono/mono/component/debugger-protocol.c @@ -11,7 +11,7 @@ static int32_t packet_id = 0; /* * Functions to decode protocol data */ -int +int m_dbgprot_buffer_add_command_header (MdbgProtBuffer *data, int command_set, int command, MdbgProtBuffer *out) { int id = dbg_rt_atomic_inc_int32_t ((volatile int32_t *)&packet_id); @@ -27,7 +27,7 @@ m_dbgprot_buffer_add_command_header (MdbgProtBuffer *data, int command_set, int return id; } -void +void m_dbgprot_decode_command_header (MdbgProtBuffer *recvbuf, MdbgProtHeader *header) { header->len = m_dbgprot_decode_int (recvbuf->p, &recvbuf->p, recvbuf->end); diff --git a/src/mono/mono/component/debugger-protocol.h b/src/mono/mono/component/debugger-protocol.h index 6bce7c5ff2ec1..af28674c42d52 100644 --- a/src/mono/mono/component/debugger-protocol.h +++ b/src/mono/mono/component/debugger-protocol.h @@ -6,7 +6,7 @@ #define HEADER_LENGTH 11 #define REPLY_PACKET 0x80 -/* +/* * Wire Protocol definitions */ @@ -35,7 +35,8 @@ typedef enum { MDBGPROT_CMD_VM_STOP_BUFFERING = 15, MDBGPROT_CMD_VM_READ_MEMORY = 16, MDBGPROT_CMD_VM_WRITE_MEMORY = 17, - MDBGPROT_CMD_GET_ASSEMBLY_BY_NAME = 18 + MDBGPROT_CMD_GET_ASSEMBLY_BY_NAME = 18, + MDBGPROT_CMD_GET_MODULE_BY_GUID = 19 } MdbgProtCmdVM; typedef enum { @@ -150,7 +151,7 @@ typedef enum { typedef enum { MDBGPROT_CMD_MODULE_GET_INFO = 1, - MDBGPROT_CMD_MODULE_APPLY_CHANGES = 2, + MDBGPROT_CMD_MODULE_APPLY_CHANGES = 2 } MdbgProtCmdModule; typedef enum { diff --git a/src/mono/mono/component/debugger-state-machine.h b/src/mono/mono/component/debugger-state-machine.h index 5002467b93264..9a549401dc699 100644 --- a/src/mono/mono/component/debugger-state-machine.h +++ b/src/mono/mono/component/debugger-state-machine.h @@ -66,4 +66,4 @@ mono_debugger_state (JsonWriter *writer); char * mono_debugger_state_str (void); -#endif // __MONO_DEBUGGER_STATE_MACHINE__ +#endif // __MONO_DEBUGGER_STATE_MACHINE__ diff --git a/src/mono/mono/component/debugger-stub.c b/src/mono/mono/component/debugger-stub.c index 4235a97eb5017..c6a6a445b41d7 100644 --- a/src/mono/mono/component/debugger-stub.c +++ b/src/mono/mono/component/debugger-stub.c @@ -54,7 +54,7 @@ stub_debugger_single_step_from_context (MonoContext *ctx); static void stub_debugger_breakpoint_from_context (MonoContext *ctx); -static gboolean +static gboolean stub_debugger_transport_handshake (void); static void @@ -63,13 +63,13 @@ stub_mono_wasm_breakpoint_hit (void); static void stub_mono_wasm_single_step_hit (void); -static void +static void stub_send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len); static MonoComponentDebugger fn_table = { { MONO_COMPONENT_ITF_VERSION, &debugger_avaliable }, &stub_debugger_init, - &stub_debugger_user_break, + &stub_debugger_user_break, &stub_debugger_parse_options, &stub_debugger_breakpoint_hit, &stub_debugger_single_step_event, @@ -183,7 +183,7 @@ stub_debugger_breakpoint_from_context (MonoContext *ctx) g_assert_not_reached (); } -static gboolean +static gboolean stub_debugger_transport_handshake (void) { g_assert_not_reached(); @@ -199,7 +199,7 @@ stub_mono_wasm_single_step_hit (void) { } -static void +static void stub_send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len) { } @@ -217,13 +217,13 @@ EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command_with_parms (int id, int G_END_DECLS -EMSCRIPTEN_KEEPALIVE gboolean +EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command_with_parms (int id, int command_set, int command, guint8* data, unsigned int size, int valtype, char* newvalue) { return false; } -EMSCRIPTEN_KEEPALIVE gboolean +EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command (int id, int command_set, int command, guint8* data, unsigned int size) { return false; diff --git a/src/mono/mono/component/debugger.c b/src/mono/mono/component/debugger.c index 2ebb4f46aae91..5187d70a8954c 100644 --- a/src/mono/mono/component/debugger.c +++ b/src/mono/mono/component/debugger.c @@ -28,8 +28,8 @@ MonoComponentDebugger * mono_component_debugger_init (void) { debugger_agent_add_function_pointers (&fn_table); -#ifdef TARGET_WASM +#ifdef TARGET_WASM mini_wasm_debugger_add_function_pointers (&fn_table); -#endif +#endif return &fn_table; } diff --git a/src/mono/mono/component/hot_reload-internals.h b/src/mono/mono/component/hot_reload-internals.h new file mode 100644 index 0000000000000..36d3606e17e4a --- /dev/null +++ b/src/mono/mono/component/hot_reload-internals.h @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#ifndef _MONO_COMPONENT_HOT_RELOAD_INTERNALS_H +#define _MONO_COMPONENT_HOT_RELOAD_INTERNALS_H + +#include +#include "mono/metadata/object-forward.h" +#include "mono/metadata/metadata-internals.h" +#include "mono/metadata/class-internals.h" + +/* Execution-time info for an updated class. */ +typedef struct _MonoClassRuntimeMetadataUpdateInfo { + MonoCoopMutex static_fields_lock; /* protects the static_fields hashtable. Values can be used outside the lock (since they're allocated pinned). */ + MonoGHashTable *static_fields; /* key is field token, value is a pinned managed object: either a boxed valuetype (the static field address is the value address) or a Mono.HotReload.FieldStore object (in which case the static field address is the address of the _loc field in the object.) */ + gboolean inited; +} MonoClassRuntimeMetadataUpdateInfo; + +/* Class-specific metadata update info. See + * mono_class_get_metadata_update_info() Note that this info is associated with + * class _definitions_ that can be edited, so primitives, generic instances, + * arrays, pointers, etc do not have this info. + */ +struct _MonoClassMetadataUpdateInfo { + /* FIXME: use a struct that allocates out of the MonoClass mempool! or maybe add the GArray + * to the BaselineInfo for the image and cleanup from there. */ + GSList *added_members; /* a set of Method or Field table tokens of any methods or fields added to this class, allocated from the MonoClass mempool */ + + GPtrArray *added_fields; /* a set of MonoClassMetadataUpdateField* values for every added field. */ + + MonoClassRuntimeMetadataUpdateInfo runtime; +}; + + +/* Keep in sync with Mono.HotReload.FieldStore in managed */ +typedef struct _MonoHotReloadFieldStoreObject { + MonoObject object; + MonoObject *_loc; +} MonoHotReloadFieldStoreObject; + +typedef struct _MonoClassMetadataUpdateField { + MonoClassField field; + uint32_t generation; /* when this field was added */ + uint32_t token; /* the Field table token where this field was defined. (this won't make + * sense for generic instances, once EnC is supported there) */ + /* if non-zero the EnC update came before the parent class was initialized. The field is + * stored in the instance at this offset. MonoClassField:offset is -1. Not used for static + * fields. */ + int before_init_instance_offset; +} MonoClassMetadataUpdateField; + +#endif/*_MONO_COMPONENT_HOT_RELOAD_INTERNALS_H*/ diff --git a/src/mono/mono/component/hot_reload-stub.c b/src/mono/mono/component/hot_reload-stub.c index 6064a6a78f875..2377b948a7b0a 100644 --- a/src/mono/mono/component/hot_reload-stub.c +++ b/src/mono/mono/component/hot_reload-stub.c @@ -65,12 +65,27 @@ hot_reload_stub_has_modified_rows (const MonoTableInfo *table); static int hot_reload_stub_table_num_rows_slow (MonoImage *image, int table_index); -static GArray* -hot_reload_stub_get_added_methods (MonoClass *klass); - static uint32_t hot_reload_stub_method_parent (MonoImage *image, uint32_t method_index); +static void* +hot_reload_stub_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer); + +static uint32_t +hot_reload_stub_field_parent (MonoImage *image, uint32_t field_index); + +static uint32_t +hot_reload_stub_get_field_idx (MonoClassField *field); + +static MonoClassField * +hot_reload_stub_get_field (MonoClass *klass, uint32_t fielddef_token); + +static gpointer +hot_reload_stub_get_static_field_addr (MonoClassField *field); + +static MonoMethod * +hot_reload_stub_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error); + static MonoComponentHotReload fn_table = { { MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available }, &hot_reload_stub_set_fastpath_data, @@ -89,8 +104,13 @@ static MonoComponentHotReload fn_table = { &hot_reload_stub_get_updated_method_ppdb, &hot_reload_stub_has_modified_rows, &hot_reload_stub_table_num_rows_slow, - &hot_reload_stub_get_added_methods, &hot_reload_stub_method_parent, + &hot_reload_stub_metadata_linear_search, + &hot_reload_stub_field_parent, + &hot_reload_stub_get_field_idx, + &hot_reload_stub_get_field, + &hot_reload_stub_get_static_field_addr, + &hot_reload_stub_find_method_by_name, }; static bool @@ -200,18 +220,49 @@ hot_reload_stub_table_num_rows_slow (MonoImage *image, int table_index) g_assert_not_reached (); /* should always take the fast path */ } -static GArray* -hot_reload_stub_get_added_methods (MonoClass *klass) +static uint32_t +hot_reload_stub_method_parent (MonoImage *image, uint32_t method_index) +{ + return 0; +} + + +static void* +hot_reload_stub_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer) { return NULL; } static uint32_t -hot_reload_stub_method_parent (MonoImage *image, uint32_t method_index) +hot_reload_stub_field_parent (MonoImage *image, uint32_t field_index) { return 0; } +static uint32_t +hot_reload_stub_get_field_idx (MonoClassField *field) +{ + return 0; +} + +static MonoClassField * +hot_reload_stub_get_field (MonoClass *klass, uint32_t fielddef_token) +{ + return NULL; +} + +static gpointer +hot_reload_stub_get_static_field_addr (MonoClassField *field) +{ + return NULL; +} + +static MonoMethod * +hot_reload_stub_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error) +{ + return NULL; +} + MONO_COMPONENT_EXPORT_ENTRYPOINT MonoComponentHotReload * diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index bd8c3db635c88..155dcdf6f2c9a 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -8,8 +8,11 @@ #include #include "mono/utils/mono-compiler.h" +#include "mono/component/hot_reload-internals.h" + #include #include "mono/metadata/assembly-internals.h" +#include "mono/metadata/mono-hash-internals.h" #include "mono/metadata/metadata-internals.h" #include "mono/metadata/metadata-update.h" #include "mono/metadata/object-internals.h" @@ -22,14 +25,18 @@ #include "mono/metadata/debug-internals.h" #include "mono/metadata/mono-debug.h" #include "mono/metadata/debug-mono-ppdb.h" +#include "mono/utils/bsearch.h" #include #include -#undef ALLOW_METHOD_ADD +#define ALLOW_CLASS_ADD +#define ALLOW_METHOD_ADD +#define ALLOW_FIELD_ADD +typedef struct _BaselineInfo BaselineInfo; typedef struct _DeltaInfo DeltaInfo; static void @@ -80,7 +87,7 @@ hot_reload_table_bounds_check (MonoImage *base_image, int table_index, int token static gboolean hot_reload_delta_heap_lookup (MonoImage *base_image, MetadataHeapGetterFunc get_heap, uint32_t orig_index, MonoImage **image_out, uint32_t *index_out); -static gpointer +static gpointer hot_reload_get_updated_method_ppdb (MonoImage *base_image, uint32_t idx); static gboolean @@ -89,12 +96,32 @@ hot_reload_has_modified_rows (const MonoTableInfo *table); static int hot_reload_table_num_rows_slow (MonoImage *image, int table_index); -static GArray* -hot_reload_get_added_methods (MonoClass *klass); +static GSList* +hot_reload_get_added_members (MonoClass *klass); static uint32_t hot_reload_method_parent (MonoImage *base, uint32_t method_token); +static void* +hot_reload_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer); + +static uint32_t +hot_reload_field_parent (MonoImage *base, uint32_t field_token); + +static uint32_t +hot_reload_get_field_idx (MonoClassField *field); + +static MonoClassField * +hot_reload_get_field (MonoClass *klass, uint32_t fielddef_token); + +static gpointer +hot_reload_get_static_field_addr (MonoClassField *field); + +static MonoMethod * +hot_reload_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error); + +static MonoClassMetadataUpdateField * +metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, MonoError *error); static MonoComponentHotReload fn_table = { { MONO_COMPONENT_ITF_VERSION, &hot_reload_available }, @@ -114,8 +141,13 @@ static MonoComponentHotReload fn_table = { &hot_reload_get_updated_method_ppdb, &hot_reload_has_modified_rows, &hot_reload_table_num_rows_slow, - &hot_reload_get_added_methods, &hot_reload_method_parent, + &hot_reload_metadata_linear_search, + &hot_reload_field_parent, + &hot_reload_get_field_idx, + &hot_reload_get_field, + &hot_reload_get_static_field_addr, + &hot_reload_find_method_by_name, }; MonoComponentHotReload * @@ -156,14 +188,14 @@ static MonoNativeTlsKey exposed_generation_id; * In each delta, the physical tables contain the rows that modify existing rows of a prior generation, * followed by inserted rows. * https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataAggregator.cs#L324 - * + * * The total logical number of rows in a table for a particular generation is * prev_gen_rows + inserted_rows. */ typedef struct _delta_row_count { guint32 prev_gen_rows; guint32 modified_rows; - guint32 inserted_rows; + guint32 inserted_rows; } delta_row_count; /* Additional informaiton for MonoImages representing deltas */ @@ -180,7 +212,7 @@ struct _DeltaInfo { // for each table, the row in the EncMap table that has the first token for remapping it? uint32_t enc_recs [MONO_TABLE_NUM]; delta_row_count count [MONO_TABLE_NUM]; - + MonoPPDBFile *ppdb_file; MonoMemPool *pool; /* mutated tables are allocated here */ @@ -190,7 +222,7 @@ struct _DeltaInfo { /* Additional informaiton for baseline MonoImages */ -typedef struct _BaselineInfo { +struct _BaselineInfo { /* List of DeltaInfos of deltas*/ GList *delta_info; /* Tail of delta_info for fast appends */ @@ -202,9 +234,12 @@ typedef struct _BaselineInfo { /* TRUE if any published update modified an existing row */ gboolean any_modified_rows [MONO_TABLE_NUM]; - GHashTable *added_methods; /* maps each MonoClass to a GArray of added method tokens */ - GHashTable *method_parent; /* maps added methoddef tokens to typedef tokens */ -} BaselineInfo; + /* A list of MonoClassMetadataUpdateInfo* that need to be cleaned up */ + GSList *klass_info; + + /* Parents for added methods, fields, etc */ + GHashTable *member_parent; /* maps added methoddef or fielddef tokens to typedef tokens */ +}; #define DOTNET_MODIFIABLE_ASSEMBLIES "DOTNET_MODIFIABLE_ASSEMBLIES" @@ -312,11 +347,34 @@ baseline_info_init (MonoImage *image_base) return baseline_info; } +static void +klass_info_destroy (gpointer value, gpointer user_data G_GNUC_UNUSED) +{ + MonoClassMetadataUpdateInfo *info = (MonoClassMetadataUpdateInfo *)value; + /* added_members is allocated from the class mempool, don't free it here */ + /* The MonoClassMetadataUpdateField is allocated from the class mempool, don't free it here */ + g_ptr_array_free (info->added_fields, TRUE); + + if (info->runtime.static_fields) { + mono_g_hash_table_destroy (info->runtime.static_fields); + info->runtime.static_fields = NULL; + } + + mono_coop_mutex_destroy (&info->runtime.static_fields_lock); + + /* The MonoClassMetadataUpdateInfo itself is allocated from the class mempool, don't free it here */ +} + static void baseline_info_destroy (BaselineInfo *info) { if (info->method_table_update) g_hash_table_destroy (info->method_table_update); + + if (info->klass_info) { + g_slist_foreach (info->klass_info, klass_info_destroy, NULL); + g_slist_free (info->klass_info); + } g_free (info); } @@ -515,9 +573,15 @@ image_open_dmeta_from_data (MonoImage *base_image, uint32_t generation, gconstpo static DeltaInfo* image_append_delta (MonoImage *base, BaselineInfo *base_info, MonoImage *delta, DeltaInfo *delta_info); +/* common method, don't use directly, use add_method_to_baseline, add_field_to_baseline, etc */ +static void +add_member_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t member_token); + static void add_method_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t method_token, MonoDebugInformationEnc* pdb_address); +static void +add_field_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t field_token); void hot_reload_init (void) @@ -660,6 +724,33 @@ hot_reload_update_cancel (uint32_t generation) publish_unlock (); } +static void +add_class_info_to_baseline (MonoClass *klass, MonoClassMetadataUpdateInfo *klass_info) +{ + MonoImage *image = m_class_get_image (klass); + BaselineInfo *baseline_info = baseline_info_lookup (image); + baseline_info->klass_info = g_slist_prepend (baseline_info->klass_info, klass_info); +} + +static MonoClassMetadataUpdateInfo * +mono_class_get_or_add_metadata_update_info (MonoClass *klass) +{ + MonoClassMetadataUpdateInfo *info = NULL; + info = mono_class_get_metadata_update_info (klass); + if (info) + return info; + mono_loader_lock (); + info = mono_class_get_metadata_update_info (klass); + if (!info) { + info = mono_class_alloc0 (klass, sizeof (MonoClassMetadataUpdateInfo)); + add_class_info_to_baseline (klass, info); + mono_class_set_metadata_update_info (klass, info); + } + mono_loader_unlock (); + g_assert (info); + return info; +} + /* * Given a baseline and an (optional) previous delta, allocate space for new tables for the current delta. * @@ -695,12 +786,6 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i guint32 rows = count->prev_gen_rows + count->inserted_rows; - MonoTableInfo *tbl = &delta->mutants [i]; - tbl->row_size = base->tables[i].row_size; - tbl->size_bitfield = base->tables[i].size_bitfield; - tbl->rows_ = rows; - - tbl->base = mono_mempool_alloc (delta->pool, tbl->row_size * rows); const MonoTableInfo *prev_table; if (!prev_delta || prev_delta->mutants [i].base == NULL) prev_table = &base->tables [i]; @@ -708,6 +793,21 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i prev_table = &prev_delta->mutants [i]; g_assert (prev_table != NULL); + + MonoTableInfo *tbl = &delta->mutants [i]; + if (prev_table->rows_ == 0) { + /* table was empty in the baseline and it was empty in the prior generation, but now we have some rows. Use the format of the mutant table. */ + g_assert (prev_table->row_size == 0); + tbl->row_size = delta->delta_image->tables [i].row_size; + tbl->size_bitfield = delta->delta_image->tables [i].size_bitfield; + } else { + tbl->row_size = prev_table->row_size; + tbl->size_bitfield = prev_table->size_bitfield; + } + tbl->rows_ = rows; + g_assert (tbl->rows_ > 0 && tbl->row_size != 0); + + tbl->base = mono_mempool_alloc (delta->pool, tbl->row_size * rows); g_assert (table_info_get_rows (prev_table) == count->prev_gen_rows); /* copy the old rows and zero out the new ones */ @@ -877,8 +977,13 @@ dump_update_summary (MonoImage *image_base, MonoImage *image_dmeta) } +/* + * Finds the latest mutated version of the table given by tbl_index + * + * On success returns TRUE, modifies *t and optionally updates *delta_out + */ static gboolean -effective_table_mutant (MonoImage *base, BaselineInfo *info, int tbl_index, const MonoTableInfo **t, int idx) +effective_table_mutant (MonoImage *base, BaselineInfo *info, int tbl_index, const MonoTableInfo **t, DeltaInfo **delta_out) { GList *ptr =info->delta_info_last; uint32_t exposed_gen = hot_reload_get_thread_generation (); @@ -899,6 +1004,8 @@ effective_table_mutant (MonoImage *base, BaselineInfo *info, int tbl_index, cons g_assert (delta_info != NULL); *t = &delta_info->mutants [tbl_index]; + if (delta_out) + *delta_out = delta_info; return TRUE; } @@ -917,7 +1024,7 @@ hot_reload_effective_table_slow (const MonoTableInfo **t, int idx) if (!info) return; - gboolean success = effective_table_mutant (base, info, tbl_index, t, idx); + gboolean success = effective_table_mutant (base, info, tbl_index, t, NULL); g_assert (success); } @@ -1129,7 +1236,7 @@ funccode_to_str (int func_code) * */ static void -delta_info_mutate_row (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log_token) +delta_info_mutate_row (MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log_token) { int token_table = mono_metadata_token_table (log_token); int token_index = mono_metadata_token_index (log_token); /* 1-based */ @@ -1139,16 +1246,16 @@ delta_info_mutate_row (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo int delta_index = hot_reload_relative_delta_index (image_dmeta, cur_delta, log_token); /* The complication here is that we want the mutant table to look like the table in - * image_base with respect to column widths, but the delta tables are generally coming in + * the baseline image with respect to column widths, but the delta tables are generally coming in * uncompressed (4-byte columns). So we have to copy one column at a time and adjust the * widths as we go. */ - guint32 dst_bitfield = image_base->tables [token_table].size_bitfield; + guint32 dst_bitfield = cur_delta->mutants [token_table].size_bitfield; guint32 src_bitfield = image_dmeta->tables [token_table].size_bitfield; const char *src_base = image_dmeta->tables [token_table].base + (delta_index - 1) * image_dmeta->tables [token_table].row_size; - char *dst_base = (char*)cur_delta->mutants [token_table].base + (token_index - 1) * image_base->tables [token_table].row_size; + char *dst_base = (char*)cur_delta->mutants [token_table].base + (token_index - 1) * cur_delta->mutants [token_table].row_size; guint32 src_offset = 0, dst_offset = 0; for (int col = 0; col < mono_metadata_table_count (dst_bitfield); ++col) { @@ -1190,12 +1297,11 @@ delta_info_mutate_row (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo default: g_assert_not_reached (); } - } src_offset += src_col_size; dst_offset += dst_col_size; } - g_assert (dst_offset == image_base->tables [token_table].row_size); + g_assert (dst_offset == cur_delta->mutants [token_table].row_size); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "mutate: table=0x%02x row=0x%04x delta row=0x%04x %s", token_table, token_index, delta_index, modified ? "Mod" : "Add"); } @@ -1215,7 +1321,7 @@ prepare_mutated_rows (const MonoTableInfo *table_enclog, MonoImage *image_base, if (func_code != ENC_FUNC_DEFAULT) continue; - delta_info_mutate_row (image_base, image_dmeta, delta_info, log_token); + delta_info_mutate_row (image_dmeta, delta_info, log_token); } } @@ -1248,7 +1354,10 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de int token_table = mono_metadata_token_table (log_token); int token_index = mono_metadata_token_index (log_token); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x (%s idx=0x%02x) (base table has 0x%04x rows)\tfunc=0x%02x (\"%s\")\n", i, log_token, mono_meta_table_name (token_table), token_index, table_info_get_rows (&image_base->tables [token_table]), func_code, funccode_to_str (func_code)); + gboolean is_addition = token_index-1 >= delta_info->count[token_table].prev_gen_rows ; + + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x (%s idx=0x%02x) (base table has 0x%04x rows; prev gen had 0x%04x rows)\t%s\tfunc=0x%02x (\"%s\")\n", i, log_token, mono_meta_table_name (token_table), token_index, table_info_get_rows (&image_base->tables [token_table]), delta_info->count[token_table].prev_gen_rows, (is_addition ? "ADD" : "UPDATE"), func_code, funccode_to_str (func_code)); if (token_table != MONO_TABLE_METHOD) @@ -1256,7 +1365,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de #ifndef ALLOW_METHOD_ADD - if (token_index > table_info_get_rows (&image_base->tables [token_table])) { + if (is_addition) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "\tcannot add new method with token 0x%08x", log_token); mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: cannot add new method with token 0x%08x", log_token); unsupported_edits = TRUE; @@ -1266,8 +1375,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de #ifdef ALLOW_METHOD_ADD /* adding a new parameter to a new method is ok */ - /* FIXME: total rows, not just the baseline rows */ - if (func_code == ENC_FUNC_ADD_PARAM && token_index > table_info_get_rows (&image_base->tables [token_table])) + if (func_code == ENC_FUNC_ADD_PARAM && is_addition) continue; #endif @@ -1284,6 +1392,8 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de int token_table = mono_metadata_token_table (log_token); int token_index = mono_metadata_token_index (log_token); + gboolean is_addition = token_index-1 >= delta_info->count[token_table].prev_gen_rows ; + switch (token_table) { case MONO_TABLE_ASSEMBLYREF: /* okay, supported */ @@ -1295,9 +1405,20 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de #endif /* handled above */ break; + case MONO_TABLE_FIELD: +#ifdef ALLOW_FIELD_ADD + if (func_code == ENC_FUNC_DEFAULT) + continue; /* ok, allowed */ +#else + /* adding or modifying a field */ + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support adding or modifying fields.", i, log_token); + mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support adding or modifying fields. token=0x%08x", log_token); + unsupported_edits = TRUE; + break; +#endif case MONO_TABLE_PROPERTY: { /* modifying a property, ok */ - if (token_index <= table_info_get_rows (&image_base->tables [token_table])) + if (!is_addition) break; /* adding a property */ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support adding new properties.", i, log_token); @@ -1306,8 +1427,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de continue; } case MONO_TABLE_METHODSEMANTICS: { - /* FIXME: this should get the current table size, not the base stable size */ - if (token_index > table_info_get_rows (&image_base->tables [token_table])) { + if (is_addition) { /* new rows are fine, as long as they point at existing methods */ guint32 sema_cols [MONO_METHOD_SEMA_SIZE]; int mapped_token = hot_reload_relative_delta_index (image_dmeta, delta_info, mono_metadata_make_token (token_table, token_index)); @@ -1319,7 +1439,8 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de case METHOD_SEMANTIC_SETTER: { int prop_method_index = sema_cols [MONO_METHOD_SEMA_METHOD]; /* ok, if it's pointing to an existing getter/setter */ - if (prop_method_index < table_info_get_rows (&image_base->tables [MONO_TABLE_METHOD])) + gboolean is_prop_method_add = prop_method_index-1 >= delta_info->count[MONO_TABLE_METHOD].prev_gen_rows; + if (!is_prop_method_add) break; mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x adding new getter/setter method 0x%08x to a property is not supported", i, log_token, prop_method_index); mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support adding a new getter or setter to a property, token=0x%08x", log_token); @@ -1340,8 +1461,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de } } case MONO_TABLE_CUSTOMATTRIBUTE: { - /* FIXME: this should get the current table size, not the base stable size */ - if (token_index <= table_info_get_rows (&image_base->tables [token_table])) { + if (!is_addition) { /* modifying existing rows is ok, as long as the parent and ctor are the same */ guint32 ca_upd_cols [MONO_CUSTOM_ATTR_SIZE]; guint32 ca_base_cols [MONO_CUSTOM_ATTR_SIZE]; @@ -1375,8 +1495,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de } } case MONO_TABLE_PARAM: { - /* FIXME: this should get the current table size, not the base stable size */ - if (token_index <= table_info_get_rows (&image_base->tables [token_table])) { + if (!is_addition) { /* We only allow modifications where the parameter name doesn't change. */ uint32_t base_param [MONO_PARAM_SIZE]; uint32_t upd_param [MONO_PARAM_SIZE]; @@ -1401,11 +1520,14 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de break; /* added a row. ok */ } case MONO_TABLE_TYPEDEF: { + gboolean new_class G_GNUC_UNUSED = is_addition; #ifdef ALLOW_METHOD_ADD - /* FIXME: wrong for cumulative updates - need to look at DeltaInfo:count.prev_gen_rows */ - gboolean new_class = token_index > table_info_get_rows (&image_base->tables [token_table]); /* only allow adding methods to existing classes for now */ - if (!new_class && func_code == ENC_FUNC_ADD_METHOD) { + if ( +#ifndef ALLOW_CLASS_ADD + !new_class && +#endif + func_code == ENC_FUNC_ADD_METHOD) { /* next record should be a MONO_TABLE_METHOD addition (func == default) */ g_assert (i + 1 < rows); guint32 next_cols [MONO_ENCLOG_SIZE]; @@ -1415,7 +1537,29 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de int next_table = mono_metadata_token_table (next_token); int next_index = mono_metadata_token_index (next_token); g_assert (next_table == MONO_TABLE_METHOD); - g_assert (next_index > table_info_get_rows (&image_base->tables [next_table])); + /* expecting an added method */ + g_assert (next_index-1 >= delta_info->count[next_table].prev_gen_rows); + i++; /* skip the next record */ + continue; + } +#endif +#ifdef ALLOW_FIELD_ADD + if ( +#ifndef ALLOW_CLASS_ADD + !new_class && +#endif + func_code == ENC_FUNC_ADD_FIELD) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x AddField to klass 0x%08x, skipping next EnClog record", i, log_token, token_index); + g_assert (i + 1 < rows); + guint32 next_cols [MONO_ENCLOG_SIZE]; + mono_metadata_decode_row (table_enclog, i + 1, next_cols, MONO_ENCLOG_SIZE); + g_assert (next_cols [MONO_ENCLOG_FUNC_CODE] == ENC_FUNC_DEFAULT); + int next_token = next_cols [MONO_ENCLOG_TOKEN]; + int next_table = mono_metadata_token_table (next_token); + int next_index = mono_metadata_token_index (next_token); + g_assert (next_table == MONO_TABLE_FIELD); + /* expecting an added field */ + g_assert (next_index-1 >= delta_info->count[next_table].prev_gen_rows); i++; /* skip the next record */ continue; } @@ -1423,8 +1567,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de /* fallthru */ } default: - /* FIXME: this bounds check is wrong for cumulative updates - need to look at the DeltaInfo:count.prev_gen_rows */ - if (token_index <= table_info_get_rows (&image_base->tables [token_table])) { + if (!is_addition) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support patching of existing table cols.", i, log_token); mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support patching of existing table cols. token=0x%08x", log_token); unsupported_edits = TRUE; @@ -1464,7 +1607,7 @@ set_update_method (MonoImage *image_base, BaselineInfo *base_info, uint32_t gene /* FIXME: this is a race if other threads are doing a lookup. */ g_hash_table_insert (base_info->method_table_update, GUINT_TO_POINTER (token_index), GUINT_TO_POINTER (generation)); g_hash_table_insert (delta_info->method_table_update, GUINT_TO_POINTER (token_index), (gpointer) il_address); - set_delta_method_debug_info (delta_info, token_index, pdb_address); + set_delta_method_debug_info (delta_info, token_index, pdb_address); } static MonoDebugInformationEnc * @@ -1544,9 +1687,12 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen * have it in writable memory (and not mmap-ed pages), so we can rewrite the table values. */ + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Pass 2 begin: base '%s' delta image=%p", image_base->name, image_dmeta); +#if defined(ALLOW_METHOD_ADD) || defined(ALLOW_FIELD_ADD) + MonoClass *add_member_klass = NULL; +#endif #ifdef ALLOW_METHOD_ADD - MonoClass *add_method_klass = NULL; uint32_t add_param_method_index = 0; #endif @@ -1560,7 +1706,11 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen int token_table = mono_metadata_token_table (log_token); int token_index = mono_metadata_token_index (log_token); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "enclog i=%d: token=0x%08x (table=%s): %d", i, log_token, mono_meta_table_name (token_table), func_code); + + gboolean is_addition = token_index-1 >= delta_info->count[token_table].prev_gen_rows ; + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "enclog i=%d: token=0x%08x (table=%s): %d:\t%s", i, log_token, mono_meta_table_name (token_table), func_code, (is_addition ? "ADD" : "UPDATE")); + /* TODO: See CMiniMdRW::ApplyDelta for how to drive this. */ @@ -1570,14 +1720,12 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen #ifdef ALLOW_METHOD_ADD case ENC_FUNC_ADD_METHOD: { g_assert (token_table == MONO_TABLE_TYPEDEF); - /* FIXME: this bounds check is wrong for cumulative updates - need to look at the DeltaInfo:count.prev_gen_rows */ - /* should've been caught by pass1 if we're adding a new method to a new class. */ MonoClass *klass = mono_class_get_checked (image_base, log_token, error); if (!is_ok (error)) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Can't get class with token 0x%08x due to: %s", log_token, mono_error_get_message (error)); return FALSE; } - add_method_klass = klass; + add_member_klass = klass; break; } @@ -1586,6 +1734,18 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen add_param_method_index = token_index; break; } +#endif +#ifdef ALLOW_FIELD_ADD + case ENC_FUNC_ADD_FIELD: { + g_assert (token_table == MONO_TABLE_TYPEDEF); + MonoClass *klass = mono_class_get_checked (image_base, log_token, error); + if (!is_ok (error)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Can't get class with token 0x%08x due to: %s", log_token, mono_error_get_message (error)); + return FALSE; + } + add_member_klass = klass; + break; + } #endif default: g_error ("EnC: unsupported FuncCode, should be caught by pass1"); @@ -1637,14 +1797,14 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen if (func_code == ENC_FUNC_ADD_PARAM) break; - if (token_index > table_info_get_rows (&image_base->tables [token_table])) { - if (!add_method_klass) + if (is_addition) { + if (!add_member_klass) g_error ("EnC: new method added but I don't know the class, should be caught by pass1"); - g_assert (add_method_klass); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Adding new method 0x%08x to class %s.%s", token_index, m_class_get_name_space (add_method_klass), m_class_get_name (add_method_klass)); + g_assert (add_member_klass); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Adding new method 0x%08x to class %s.%s", log_token, m_class_get_name_space (add_member_klass), m_class_get_name (add_member_klass)); MonoDebugInformationEnc *method_debug_information = hot_reload_get_method_debug_information (delta_info->ppdb_file, token_index); - add_method_to_baseline (base_info, delta_info, add_method_klass, token_index, method_debug_information); - add_method_klass = NULL; + add_method_to_baseline (base_info, delta_info, add_member_klass, log_token, method_debug_information); + add_member_klass = NULL; } #endif @@ -1653,7 +1813,7 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen if (!delta_info->method_table_update) delta_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); if (!delta_info->method_ppdb_table_update) - + delta_info->method_ppdb_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); int mapped_token = hot_reload_relative_delta_index (image_dmeta, delta_info, mono_metadata_make_token (token_table, token_index)); @@ -1666,17 +1826,78 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen /* rva points probably into image_base IL stream. can this ever happen? */ g_print ("TODO: this case is still a bit contrived. token=0x%08x with rva=0x%04x\n", log_token, rva); } -#ifdef ALLOW_METHOD_ADD - add_method_klass = NULL; +#if defined(ALLOW_METHOD_ADD) || defined(ALLOW_FIELD_ADD) + add_member_klass = NULL; #endif break; } - case MONO_TABLE_TYPEDEF: { - /* TODO: throw? */ - /* TODO: happens changing the class (adding field or method). we ignore it, but dragons are here */ + case MONO_TABLE_FIELD: { +#ifdef ALLOW_FIELD_ADD + g_assert (is_addition); + g_assert (add_member_klass); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Adding new field 0x%08x to class %s.%s", log_token, m_class_get_name_space (add_member_klass), m_class_get_name (add_member_klass)); + + uint32_t mapped_token = hot_reload_relative_delta_index (image_dmeta, delta_info, log_token); + uint32_t field_flags = mono_metadata_decode_row_col (&image_dmeta->tables [MONO_TABLE_FIELD], mapped_token - 1, MONO_FIELD_FLAGS); + + if ((field_flags & FIELD_ATTRIBUTE_STATIC) == 0) { + /* TODO: implement instance (and literal?) fields */ + mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_METADATA_UPDATE, "Adding non-static fields isn't implemented yet (token 0x%08x, class %s.%s)", log_token, m_class_get_name_space (add_member_klass), m_class_get_name (add_member_klass)); + mono_error_set_not_implemented (error, "Adding non-static fields isn't implemented yet (token 0x%08x, class %s.%s)", log_token, m_class_get_name_space (add_member_klass), m_class_get_name (add_member_klass)); + return FALSE; + } - /* existing entries are supposed to be patched */ - g_assert (token_index <= table_info_get_rows (&image_base->tables [token_table])); + add_field_to_baseline (base_info, delta_info, add_member_klass, log_token); + + /* This actually does more than mono_class_setup_basic_field_info and + * resolves MonoClassField:type and sets MonoClassField:offset to -1 to make + * it easier to spot that the field is special. + */ + metadata_update_field_setup_basic_info_and_resolve (image_base, base_info, generation, delta_info, add_member_klass, log_token, error); + if (!is_ok (error)) { + mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_METADATA_UPDATE, "Could not setup field (token 0x%08x) due to: %s", log_token, mono_error_get_message (error)); + return FALSE; + } + + add_member_klass = NULL; +#else + g_assert_not_reached (); +#endif + break; + } + case MONO_TABLE_TYPEDEF: { +#ifdef ALLOW_CLASS_ADD + if (is_addition) { + /* Adding a new class. ok */ + switch (func_code) { + case ENC_FUNC_DEFAULT: + /* ok, added a new class */ + /* TODO: do things here */ + break; + case ENC_FUNC_ADD_METHOD: + case ENC_FUNC_ADD_FIELD: + /* ok, adding a new field or method to a new class */ + /* TODO: do we need to do anything special? Conceptually + * this is the same as modifying an existing class - + * especially since from the next generation's point of view + * that's what adding a field/method will be. */ + break; + case ENC_FUNC_ADD_PROPERTY: + case ENC_FUNC_ADD_EVENT: + g_assert_not_reached (); /* FIXME: implement me */ + default: + g_assert_not_reached (); /* unknown func_code */ + } + break; + } +#endif + /* modifying an existing class by adding a method or field, etc. */ + g_assert (!is_addition); +#if !defined(ALLOW_METHOD_ADD) && !defined(ALLOW_FIELD_ADD) + g_assert_not_reached (); +#else + g_assert (func_code != ENC_FUNC_DEFAULT); +#endif break; } case MONO_TABLE_PROPERTY: { @@ -1709,7 +1930,7 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen * * So by the time we see the param additions, the methods are already in. * - * FIXME: we need a lookaside table (like method_parent) for every place + * FIXME: we need a lookaside table (like member_parent) for every place * that looks at MONO_METHOD_PARAMLIST */ break; @@ -1868,7 +2089,7 @@ get_method_update_rva (MonoImage *image_base, BaselineInfo *base_info, uint32_t gpointer loc = NULL; uint32_t cur = hot_reload_get_thread_generation (); int generation = -1; - + /* Go through all the updates that the current thread can see and see * if they updated the method. Keep the latest visible update */ for (GList *ptr = base_info->delta_info; ptr != NULL; ptr = ptr->next) { @@ -1896,7 +2117,7 @@ get_method_update_rva (MonoImage *image_base, BaselineInfo *base_info, uint32_t return loc; } -gpointer +gpointer hot_reload_get_updated_method_ppdb (MonoImage *base_image, uint32_t idx) { BaselineInfo *info = baseline_info_lookup (base_image); @@ -1909,8 +2130,9 @@ hot_reload_get_updated_method_ppdb (MonoImage *base_image, uint32_t idx) if (G_UNLIKELY (gen > 0)) { loc = get_method_update_rva (base_image, info, idx, TRUE); } - /* Check the method_parent table as a way of checking if the method was added by a later generation. If so, still look for its PPDB info in our update tables */ - if (G_UNLIKELY (loc == 0 && info->method_parent && GPOINTER_TO_UINT (g_hash_table_lookup (info->method_parent, GUINT_TO_POINTER (idx))) > 0)) { + /* Check the member_parent table as a way of checking if the method was added by a later generation. If so, still look for its PPDB info in our update tables */ + uint32_t token = mono_metadata_make_token (MONO_TABLE_METHOD, mono_metadata_token_index (idx)); + if (G_UNLIKELY (loc == 0 && info->member_parent && GPOINTER_TO_UINT (g_hash_table_lookup (info->member_parent, GUINT_TO_POINTER (token))) > 0)) { loc = get_method_update_rva (base_image, info, idx, TRUE); } } @@ -2039,52 +2261,321 @@ hot_reload_table_num_rows_slow (MonoImage *base, int table_index) } static void -add_method_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t method_token, MonoDebugInformationEnc* pdb_address) +add_member_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t member_token) { - if (!base_info->added_methods) { - base_info->added_methods = g_hash_table_new (g_direct_hash, g_direct_equal); - } - if (!base_info->method_parent) { - base_info->method_parent = g_hash_table_new (g_direct_hash, g_direct_equal); - } - /* FIXME: locking for readers/writers of the GArray */ - GArray *arr = g_hash_table_lookup (base_info->added_methods, klass); - if (!arr) { - arr = g_array_new (FALSE, FALSE, sizeof(uint32_t)); - g_hash_table_insert (base_info->added_methods, klass, arr); + /* Check they really passed a table token, not just a table row index */ + g_assert (mono_metadata_token_table (member_token) != 0); + + if (!base_info->member_parent) { + base_info->member_parent = g_hash_table_new (g_direct_hash, g_direct_equal); } - g_array_append_val (arr, method_token); - g_hash_table_insert (base_info->method_parent, GUINT_TO_POINTER (method_token), GUINT_TO_POINTER (m_class_get_type_token (klass))); + MonoClassMetadataUpdateInfo *klass_info = mono_class_get_or_add_metadata_update_info (klass); + GSList *members = klass_info->added_members; + klass_info->added_members = g_slist_prepend_mem_manager (m_class_get_mem_manager (klass), members, GUINT_TO_POINTER (member_token)); + g_hash_table_insert (base_info->member_parent, GUINT_TO_POINTER (member_token), GUINT_TO_POINTER (m_class_get_type_token (klass))); +} + +static void +add_method_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t method_token, MonoDebugInformationEnc* pdb_address) +{ + add_member_to_baseline (base_info, delta_info, klass, method_token); if (pdb_address) set_delta_method_debug_info (delta_info, method_token, pdb_address); } -static GArray* -hot_reload_get_added_methods (MonoClass *klass) +static GSList* +hot_reload_get_added_members (MonoClass *klass) { /* FIXME: locking for the GArray? */ MonoImage *image = m_class_get_image (klass); if (!image->has_updates) return NULL; - BaselineInfo *base_info = baseline_info_lookup (image); - if (!base_info || base_info->added_methods == NULL) + MonoClassMetadataUpdateInfo *klass_info = mono_class_get_metadata_update_info (klass); + if (!klass_info) return NULL; - - return g_hash_table_lookup (base_info->added_methods, klass); + return klass_info->added_members; } static uint32_t -hot_reload_method_parent (MonoImage *base_image, uint32_t method_token) +hot_reload_member_parent (MonoImage *base_image, uint32_t member_token) { + /* make sure they passed a token, not just a table row index */ + g_assert (mono_metadata_token_table (member_token) != 0); + if (!base_image->has_updates) return 0; BaselineInfo *base_info = baseline_info_lookup (base_image); - if (!base_info || base_info->method_parent == NULL) + if (!base_info || base_info->member_parent == NULL) return 0; - uint32_t res = GPOINTER_TO_UINT (g_hash_table_lookup (base_info->method_parent, GUINT_TO_POINTER (method_token))); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "method_parent lookup: 0x%08x returned 0x%08x\n", method_token, res); + uint32_t res = GPOINTER_TO_UINT (g_hash_table_lookup (base_info->member_parent, GUINT_TO_POINTER (member_token))); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "member_parent lookup: 0x%08x returned 0x%08x\n", member_token, res); + + return res; +} + +static uint32_t +hot_reload_method_parent (MonoImage *base_image, uint32_t method_token) +{ + /* the callers might pass just an index without a table */ + uint32_t lookup_token = mono_metadata_make_token (MONO_TABLE_METHOD, mono_metadata_token_index (method_token)); + + return hot_reload_member_parent (base_image, lookup_token); +} + +static void +add_field_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t field_token) +{ + add_member_to_baseline (base_info, delta_info, klass, field_token); +} + +static uint32_t +hot_reload_field_parent (MonoImage *base_image, uint32_t field_token) +{ + /* the callers might pass just an index without a table */ + uint32_t lookup_token = mono_metadata_make_token (MONO_TABLE_FIELD, mono_metadata_token_index (field_token)); + + return hot_reload_member_parent (base_image, lookup_token); +} + + +/* HACK - keep in sync with locator_t in metadata/metadata.c */ +typedef struct { + int idx; /* The index that we are trying to locate */ + int col_idx; /* The index in the row where idx may be stored */ + MonoTableInfo *t; /* pointer to the table */ + guint32 result; +} upd_locator_t; + +void* +hot_reload_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer) +{ + BaselineInfo *base_info = baseline_info_lookup (base_image); + g_assert (base_info); + + g_assert (base_image->tables < base_table && base_table < &base_image->tables [MONO_TABLE_LAST]); + + int tbl_index; + { + size_t s = ALIGN_TO (sizeof (MonoTableInfo), sizeof (gpointer)); + tbl_index = ((intptr_t) base_table - (intptr_t) base_image->tables) / s; + } + + DeltaInfo *delta_info = NULL; + const MonoTableInfo *latest_mod_table = base_table; + gboolean success = effective_table_mutant (base_image, base_info, tbl_index, &latest_mod_table, &delta_info); + g_assert (success); + uint32_t rows = table_info_get_rows (latest_mod_table); + + upd_locator_t *loc = (upd_locator_t*)key; + g_assert (loc); + loc->result = 0; + /* HACK: this is so that the locator can compute the row index of the given row. but passing the mutant table to other metadata functions could backfire. */ + loc->t = (MonoTableInfo*)latest_mod_table; + for (uint32_t idx = 0; idx < rows; ++idx) { + const char *row = latest_mod_table->base + idx * latest_mod_table->row_size; + if (!comparer (loc, row)) + return (void*)row; + } + return NULL; +} + +static uint32_t +hot_reload_get_field_idx (MonoClassField *field) +{ + g_assert (m_field_is_from_update (field)); + MonoClassMetadataUpdateField *field_info = (MonoClassMetadataUpdateField*)field; + return mono_metadata_token_index (field_info->token); +} + +static MonoClassField * +hot_reload_get_field (MonoClass *klass, uint32_t fielddef_token) { + MonoClassMetadataUpdateInfo *info = mono_class_get_or_add_metadata_update_info (klass); + g_assert (mono_metadata_token_table (fielddef_token) == MONO_TABLE_FIELD); + /* FIXME: this needs locking in the multi-threaded case. There could be an update happening that resizes the array. */ + GPtrArray *added_fields = info->added_fields; + uint32_t count = added_fields->len; + for (uint32_t i = 0; i < count; ++i) { + MonoClassMetadataUpdateField *field = (MonoClassMetadataUpdateField *)g_ptr_array_index (added_fields, i); + if (field->token == fielddef_token) + return &field->field; + } + return NULL; +} + + +static MonoClassMetadataUpdateField * +metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, MonoError *error) +{ + // TODO: hang a "pending field" struct off the parent_klass if !parent_klass->fields + // In that case we can do things simpler, maybe by just creating the MonoClassField array as usual, and just relying on the normal layout algorithm to make space for the instance. + + MonoClassMetadataUpdateInfo *parent_info = mono_class_get_or_add_metadata_update_info (parent_klass); + + MonoClassMetadataUpdateField *field = mono_class_alloc0 (parent_klass, sizeof (MonoClassMetadataUpdateField)); + + m_field_set_parent (&field->field, parent_klass); + m_field_set_meta_flags (&field->field, MONO_CLASS_FIELD_META_FLAG_FROM_UPDATE); + /* It's a special field */ + field->field.offset = -1; + field->generation = generation; + field->token = fielddef_token; + + uint32_t name_idx = mono_metadata_decode_table_row_col (image_base, MONO_TABLE_FIELD, mono_metadata_token_index (fielddef_token) - 1, MONO_FIELD_NAME); + field->field.name = mono_metadata_string_heap (image_base, name_idx); + + mono_field_resolve_type (&field->field, error); + if (!is_ok (error)) + return NULL; + + if (!parent_info->added_fields) { + parent_info->added_fields = g_ptr_array_new (); + } + + g_ptr_array_add (parent_info->added_fields, field); + + return field; +} + +static void +ensure_class_runtime_info_inited (MonoClass *klass, MonoClassRuntimeMetadataUpdateInfo *runtime_info) +{ + if (runtime_info->inited) + return; + mono_loader_lock (); + if (runtime_info->inited) { + mono_loader_unlock (); + return; + } + + mono_coop_mutex_init (&runtime_info->static_fields_lock); + + /* FIXME: is it ok to re-use MONO_ROOT_SOURCE_STATIC here? */ + runtime_info->static_fields = mono_g_hash_table_new_type_internal (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_STATIC, NULL, "Hot Reload Static Fields"); + + runtime_info->inited = TRUE; + + mono_loader_unlock (); +} + +static void +class_runtime_info_static_fields_lock (MonoClassRuntimeMetadataUpdateInfo *runtime_info) +{ + mono_coop_mutex_lock (&runtime_info->static_fields_lock); +} + +static void +class_runtime_info_static_fields_unlock (MonoClassRuntimeMetadataUpdateInfo *runtime_info) +{ + mono_coop_mutex_unlock (&runtime_info->static_fields_lock); +} + +static GENERATE_GET_CLASS_WITH_CACHE_DECL (hot_reload_field_store); + +static GENERATE_GET_CLASS_WITH_CACHE(hot_reload_field_store, "Mono.HotReload", "FieldStore"); + + +static MonoObject* +create_static_field_storage (MonoType *t, MonoError *error) +{ + MonoClass *klass; + if (!mono_type_is_reference (t)) + klass = mono_class_from_mono_type_internal (t); + else + klass = mono_class_get_hot_reload_field_store_class (); + + return mono_object_new_pinned (klass, error); +} + +static gpointer +hot_reload_get_static_field_addr (MonoClassField *field) +{ + g_assert (m_field_is_from_update (field)); + MonoClassMetadataUpdateField *f = (MonoClassMetadataUpdateField *)field; + g_assert ((f->field.type->attrs & FIELD_ATTRIBUTE_STATIC) != 0); + g_assert (!m_type_is_byref(f->field.type)); // byref fields only in ref structs, which aren't allowed in EnC updates + + MonoClass *parent = m_field_get_parent (&f->field); + MonoClassMetadataUpdateInfo *parent_info = mono_class_get_or_add_metadata_update_info (parent); + MonoClassRuntimeMetadataUpdateInfo *runtime_info = &parent_info->runtime; + + ensure_class_runtime_info_inited (parent, runtime_info); + + MonoObject *obj = NULL; + class_runtime_info_static_fields_lock (runtime_info); + obj = (MonoObject*) mono_g_hash_table_lookup (runtime_info->static_fields, GUINT_TO_POINTER (f->token)); + class_runtime_info_static_fields_unlock (runtime_info); + if (!obj) { + ERROR_DECL (error); + obj = create_static_field_storage (f->field.type, error); + class_runtime_info_static_fields_lock (runtime_info); + mono_error_assert_ok (error); + MonoObject *obj2 = (MonoObject*) mono_g_hash_table_lookup (runtime_info->static_fields, GUINT_TO_POINTER (f->token)); + if (!obj2) { + // Noone else created it, use ours + mono_g_hash_table_insert_internal (runtime_info->static_fields, GUINT_TO_POINTER (f->token), obj); + } else { + /* beaten by another thread, silently drop our storage object and use theirs */ + obj = obj2; + } + class_runtime_info_static_fields_unlock (runtime_info); + } + g_assert (obj); + + gpointer addr = NULL; + if (!mono_type_is_reference (f->field.type)) { + // object is just the boxed value + addr = mono_object_unbox_internal (obj); + } else { + // object is a Mono.HotReload.FieldStore, and the static field value is obj._loc + MonoHotReloadFieldStoreObject *store = (MonoHotReloadFieldStoreObject *)obj; + addr = (gpointer)&store->_loc; + } + g_assert (addr); + + return addr; +} + +static MonoMethod * +hot_reload_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error) +{ + GSList *members = hot_reload_get_added_members (klass); + if (!members) + return NULL; + + MonoImage *image = m_class_get_image (klass); + MonoMethod *res = NULL; + for (GSList *ptr = members; ptr; ptr = ptr->next) { + uint32_t token = GPOINTER_TO_UINT(ptr->data); + if (mono_metadata_token_table (token) != MONO_TABLE_METHOD) + continue; + uint32_t idx = mono_metadata_token_index (token); + uint32_t cols [MONO_METHOD_SIZE]; + mono_metadata_decode_table_row (image, MONO_TABLE_METHOD, idx - 1, cols, MONO_METHOD_SIZE); + + if (!strcmp (mono_metadata_string_heap (image, cols [MONO_METHOD_NAME]), name)) { + ERROR_DECL (local_error); + MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, local_error); + if (!method) { + mono_error_cleanup (local_error); + continue; + } + if (param_count == -1) { + res = method; + break; + } + MonoMethodSignature *sig = mono_method_signature_checked (method, local_error); + if (!sig) { + mono_error_cleanup (error); + continue; + } + if ((method->flags & flags) == flags && sig->param_count == param_count) { + res = method; + break; + } + } + } return res; } diff --git a/src/mono/mono/component/hot_reload.h b/src/mono/mono/component/hot_reload.h index 416ff56e70eab..790234e557718 100644 --- a/src/mono/mono/component/hot_reload.h +++ b/src/mono/mono/component/hot_reload.h @@ -8,7 +8,9 @@ #include #include "mono/metadata/object-forward.h" #include "mono/metadata/metadata-internals.h" +#include "mono/metadata/class-internals.h" #include "mono/metadata/metadata-update.h" +#include "mono/utils/bsearch.h" #include "mono/utils/mono-error.h" #include "mono/utils/mono-compiler.h" #include "mono/component/component.h" @@ -31,8 +33,13 @@ typedef struct _MonoComponentHotReload { gpointer (*get_updated_method_ppdb) (MonoImage *base_image, uint32_t idx); gboolean (*has_modified_rows) (const MonoTableInfo *table); gboolean (*table_num_rows_slow) (MonoImage *base_image, int table_index); - GArray* (*get_added_methods) (MonoClass *klass); uint32_t (*method_parent) (MonoImage *base_image, uint32_t method_index); + void* (*metadata_linear_search) (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer); + uint32_t (*field_parent) (MonoImage *base_image, uint32_t method_index); + uint32_t (*get_field_idx) (MonoClassField *field); + MonoClassField* (*get_field) (MonoClass *klass, uint32_t fielddef_token); + gpointer (*get_static_field_addr) (MonoClassField *field); + MonoMethod* (*find_method_by_name) (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error); } MonoComponentHotReload; MONO_COMPONENT_EXPORT_ENTRYPOINT diff --git a/src/mono/mono/component/mini-wasm-debugger.c b/src/mono/mono/component/mini-wasm-debugger.c index 81a2011e1ef54..33728e8ca0609 100644 --- a/src/mono/mono/component/mini-wasm-debugger.c +++ b/src/mono/mono/component/mini-wasm-debugger.c @@ -174,7 +174,7 @@ mono_wasm_debugger_init (void) mono_profiler_set_domain_loaded_callback (prof, appdomain_load); mono_profiler_set_assembly_loaded_callback (prof, assembly_loaded); -//debugger-agent initialization +//debugger-agent initialization DebuggerTransport trans; trans.name = "buffer-wasm-communication"; trans.send = receive_debugger_agent_message; @@ -202,7 +202,7 @@ assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly) MonoDebugHandle *handle = mono_debug_get_handle (assembly_image); if (handle) { MonoPPDBFile *ppdb = handle->ppdb; - if (ppdb && !mono_ppdb_is_embedded (ppdb)) { //if it's an embedded pdb we don't need to send pdb extrated to DebuggerProxy. + if (ppdb && !mono_ppdb_is_embedded (ppdb)) { //if it's an embedded pdb we don't need to send pdb extrated to DebuggerProxy. pdb_image = mono_ppdb_get_image (ppdb); mono_wasm_asm_loaded (assembly_image->assembly_name, assembly_image->raw_data, assembly_image->raw_data_len, pdb_image->raw_data, pdb_image->raw_data_len); return; @@ -339,7 +339,7 @@ write_value_to_buffer (MdbgProtBuffer *buf, MonoTypeEnum type, const char* varia return TRUE; } -EMSCRIPTEN_KEEPALIVE void +EMSCRIPTEN_KEEPALIVE void mono_wasm_set_is_debugger_attached (gboolean is_attached) { mono_set_is_debugger_attached (is_attached); @@ -357,7 +357,7 @@ mono_wasm_set_is_debugger_attached (gboolean is_attached) extern void mono_wasm_add_dbg_command_received(mono_bool res_ok, int id, void* buffer, int buffer_len); -EMSCRIPTEN_KEEPALIVE gboolean +EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, int command, guint8* data, unsigned int size, int valtype, char* newvalue) { if (!debugger_enabled) { @@ -378,7 +378,7 @@ mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, i return TRUE; } -EMSCRIPTEN_KEEPALIVE gboolean +EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, guint8* data, unsigned int size) { if (!debugger_enabled) { @@ -392,7 +392,7 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, buffer_init (&buf, 128); gboolean no_reply; MdbgProtErrorCode error = 0; - if (command_set == MDBGPROT_CMD_SET_VM && command == MDBGPROT_CMD_VM_INVOKE_METHOD ) + if (command_set == MDBGPROT_CMD_SET_VM && command == MDBGPROT_CMD_VM_INVOKE_METHOD ) { DebuggerTlsData* tls = mono_wasm_get_tls (); InvokeData invoke_data; @@ -409,12 +409,12 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, return TRUE; } -static gboolean +static gboolean receive_debugger_agent_message (void *data, int len) { mono_wasm_add_dbg_command_received(1, -1, data, len); mono_wasm_save_thread_context(); - mono_wasm_fire_debugger_agent_message (); + mono_wasm_fire_debugger_agent_message (); return FALSE; } diff --git a/src/mono/mono/eglib/garray.c b/src/mono/mono/eglib/garray.c index 97df96736a14f..212179043bb03 100644 --- a/src/mono/mono/eglib/garray.c +++ b/src/mono/mono/eglib/garray.c @@ -46,20 +46,20 @@ static void ensure_capacity (GArrayPriv *priv, guint capacity) { guint new_capacity; - + if (capacity <= priv->capacity) return; - + new_capacity = (capacity + (capacity >> 1) + 63) & ~63; - + priv->array.data = g_realloc (priv->array.data, element_length (priv, new_capacity)); - + if (priv->clear_) { memset (element_offset (priv, priv->capacity), 0, element_length (priv, new_capacity - priv->capacity)); } - + priv->capacity = new_capacity; } @@ -122,7 +122,7 @@ g_array_append_vals (GArray *array, g_return_val_if_fail (array != NULL, NULL); ensure_capacity (priv, priv->array.len + len + (priv->zero_terminated ? 1 : 0)); - + memmove (element_offset (priv, priv->array.len), data, element_length (priv, len)); @@ -150,7 +150,7 @@ g_array_insert_vals (GArray *array, g_return_val_if_fail (array != NULL, NULL); ensure_capacity (priv, array->len + len + extra); - + /* first move the existing elements out of the way */ memmove (element_offset (priv, index_ + len), element_offset (priv, index_), diff --git a/src/mono/mono/eglib/gdir-unix.c b/src/mono/mono/eglib/gdir-unix.c index fe27306f6252a..10b15e7bc24e4 100644 --- a/src/mono/mono/eglib/gdir-unix.c +++ b/src/mono/mono/eglib/gdir-unix.c @@ -112,16 +112,16 @@ g_mkdir_with_parents (const gchar *pathname, int mode) { char *path, *d; int rv; - + if (!pathname || *pathname == '\0') { mono_set_errno (EINVAL); return -1; } - + d = path = g_strdup (pathname); if (*d == '/') d++; - + while (TRUE) { if (*d == '/' || *d == '\0') { char orig = *d; @@ -141,8 +141,8 @@ g_mkdir_with_parents (const gchar *pathname, int mode) d++; } } - + g_free (path); - + return 0; } diff --git a/src/mono/mono/eglib/gdir-win32.c b/src/mono/mono/eglib/gdir-win32.c index 5683c499236af..30004642361fd 100644 --- a/src/mono/mono/eglib/gdir-win32.c +++ b/src/mono/mono/eglib/gdir-win32.c @@ -127,7 +127,7 @@ void g_dir_close (GDir *dir) { g_return_if_fail (dir != NULL && dir->handle != 0); - + if (dir->current) g_free (dir->current); dir->current = NULL; diff --git a/src/mono/mono/eglib/gerror.c b/src/mono/mono/eglib/gerror.c index f767f95bc2711..b68d4ccb4121a 100644 --- a/src/mono/mono/eglib/gerror.c +++ b/src/mono/mono/eglib/gerror.c @@ -35,13 +35,13 @@ g_error_new (gpointer domain, gint code, const char *format, ...) { va_list args; GError *err = g_new (GError, 1); - + err->domain = domain; err->code = code; va_start (args, format); if (g_vasprintf (&err->message, format, args) == -1) - err->message = g_strdup_printf ("internal: invalid format string %s", format); + err->message = g_strdup_printf ("internal: invalid format string %s", format); va_end (args); return err; @@ -51,12 +51,12 @@ static GError * g_error_vnew (gpointer domain, gint code, const char *format, va_list ap) { GError *err = g_new (GError, 1); - + err->domain = domain; err->code = code; if (g_vasprintf (&err->message, format, ap) == -1) - err->message = g_strdup_printf ("internal: invalid format string %s", format); + err->message = g_strdup_printf ("internal: invalid format string %s", format); return err; } @@ -75,7 +75,7 @@ g_error_free (GError *gerror) { if (!gerror) return; - + g_free (gerror->message); g_free (gerror); } diff --git a/src/mono/mono/eglib/gfile-posix.c b/src/mono/mono/eglib/gfile-posix.c index f46f8098f6bcf..53414c659d780 100644 --- a/src/mono/mono/eglib/gfile-posix.c +++ b/src/mono/mono/eglib/gfile-posix.c @@ -143,7 +143,12 @@ g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **gerror) t = g_build_filename (g_get_tmp_dir (), tmpl, (const char*)NULL); + #ifdef HOST_WASI + g_critical ("g_file_open_tmp is not implemented for WASI"); + return 0; + #else fd = mkstemp (t); + #endif if (fd == -1) { if (gerror) { diff --git a/src/mono/mono/eglib/gfile-unix.c b/src/mono/mono/eglib/gfile-unix.c index eab90669a25ae..78815dc9c82bd 100644 --- a/src/mono/mono/eglib/gfile-unix.c +++ b/src/mono/mono/eglib/gfile-unix.c @@ -111,6 +111,9 @@ g_mkdtemp (char *temp) */ #if defined(HAVE_MKDTEMP) && !defined(_AIX) return mkdtemp (g_strdup (temp)); +#elif defined(HOST_WASI) + g_critical ("g_mkdtemp is not implemented for WASI\n"); + return NULL; #else temp = mktemp (g_strdup (temp)); /* 0700 is the mode specified in specs */ diff --git a/src/mono/mono/eglib/gfile-win32.c b/src/mono/mono/eglib/gfile-win32.c index f7195444860f5..2d86027d164fc 100644 --- a/src/mono/mono/eglib/gfile-win32.c +++ b/src/mono/mono/eglib/gfile-win32.c @@ -94,14 +94,14 @@ g_file_test (const gchar *filename, GFileTest test) { gunichar2* utf16_filename = NULL; DWORD attr; - + if (filename == NULL || test == 0) return FALSE; utf16_filename = u8to16 (filename); attr = GetFileAttributesW (utf16_filename); g_free (utf16_filename); - + if (attr == INVALID_FILE_ATTRIBUTES) return FALSE; diff --git a/src/mono/mono/eglib/gfile.c b/src/mono/mono/eglib/gfile.c index a0222ccbbd3c6..75f9ccfa47cf4 100644 --- a/src/mono/mono/eglib/gfile.c +++ b/src/mono/mono/eglib/gfile.c @@ -117,41 +117,41 @@ g_file_set_contents (const gchar *filename, const gchar *contents, gssize length const char *name; char *path; FILE *fp; - + if (!(name = strrchr (filename, G_DIR_SEPARATOR))) name = filename; else name++; - + path = g_strdup_printf (TMP_FILE_FORMAT, (int)(name - filename), filename, name); if (!(fp = fopen (path, "wb"))) { g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); g_free (path); return FALSE; } - + if (length < 0) length = strlen (contents); - + if (fwrite (contents, 1, length, fp) < length) { g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (ferror (fp)), "%s", g_strerror (ferror (fp))); g_unlink (path); g_free (path); fclose (fp); - + return FALSE; } - + fclose (fp); - + if (g_rename (path, filename) != 0) { g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); g_unlink (path); g_free (path); return FALSE; } - + g_free (path); - + return TRUE; } diff --git a/src/mono/mono/eglib/glist.c b/src/mono/mono/eglib/glist.c index 9fe1748133857..6a05f96a511e3 100644 --- a/src/mono/mono/eglib/glist.c +++ b/src/mono/mono/eglib/glist.c @@ -12,10 +12,10 @@ * 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 @@ -185,14 +185,14 @@ g_list_find_custom (GList *list, gconstpointer data, GCompareFunc func) { if (!func) return NULL; - + while (list) { if (func (list->data, data) == 0) return list; - + list = list->next; } - + return NULL; } diff --git a/src/mono/mono/eglib/gmarkup.c b/src/mono/mono/eglib/gmarkup.c index 826854a1ed346..6639ec2aa83ea 100644 --- a/src/mono/mono/eglib/gmarkup.c +++ b/src/mono/mono/eglib/gmarkup.c @@ -87,12 +87,12 @@ void g_markup_parse_context_free (GMarkupParseContext *context) { GSList *l; - + g_return_if_fail (context != NULL); if (context->user_data_dnotify != NULL) (context->user_data_dnotify) (context->user_data); - + if (context->text != NULL) g_string_free (context->text, TRUE); for (l = context->level; l; l = l->next) @@ -159,7 +159,7 @@ parse_value (const char *p, const char *end, char **value, GError **gerror) { const char *start; int l; - + if (*p != '"'){ set_error ("%s", "Expected the attribute value to start with a quote"); return end; @@ -184,7 +184,7 @@ parse_name (const char *p, const char *end, char **value) { const char *start = p; int l; - + if (p < end && my_isnamestartchar (*p)) for (; p < end && my_isnamechar (*p); p++) ; @@ -209,22 +209,22 @@ parse_attributes (const char *p, const char *end, char ***names, char ***values, p = skip_space (p, end); if (p == end) return end; - + if (*p == '>'){ *full_stop = 0; - return p; + return p; } if (state == SKIP_XML_DECLARATION && *p == '?' && ((p+1) < end) && *(p+1) == '>'){ *full_stop = 0; return p+1; } - + if (*p == '/' && ((p+1) < end && *(p+1) == '>')){ *full_stop = 1; return p+1; } else { char *name, *value; - + p = parse_name (p, end, &name); if (p == end) return p; @@ -258,9 +258,9 @@ parse_attributes (const char *p, const char *end, char ***names, char ***values, (*names) [nnames-1] = name; (*values) [nnames-1] = value; (*names) [nnames] = NULL; - (*values) [nnames] = NULL; + (*values) [nnames] = NULL; } - } + } } static void @@ -270,7 +270,7 @@ destroy_parse_state (GMarkupParseContext *context) for (p = context->level; p != NULL; p = p->next) g_free (p->data); - + g_slist_free (context->level); if (context->text != NULL) g_string_free (context->text, TRUE); @@ -284,13 +284,13 @@ g_markup_parse_context_parse (GMarkupParseContext *context, GError **gerror) { const char *p, *end; - + g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (text != NULL, FALSE); g_return_val_if_fail (text_len >= 0, FALSE); end = text + text_len; - + for (p = text; p < end; p++){ char c = *p; @@ -328,12 +328,12 @@ g_markup_parse_context_parse (GMarkupParseContext *context, p += 2; break; } - + if (!my_isnamestartchar (*p)){ set_error ("%s", "Expected an element name"); goto fail; } - + for (++p; p < end && my_isnamechar (*p); p++) ; if (p == end){ @@ -341,7 +341,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, goto fail; } element_end = p; - + for (; p < end && my_isspace (*p); p++) ; if (p == end){ @@ -382,7 +382,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, g_free (ename); goto fail; } - + if (full_stop){ if (context->parser.end_element != NULL && context->state == START_ELEMENT){ context->parser.end_element (context, ename, context->user_data, gerror); @@ -395,7 +395,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, } else { context->level = g_slist_prepend (context->level, ename); } - + context->state = TEXT; break; } /* case START_ELEMENT */ @@ -422,7 +422,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, break; } break; - + case FLUSH_TEXT: if (context->parser.text != NULL && context->text != NULL){ context->parser.text (context, context->text->str, context->text->len, @@ -430,7 +430,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, if (gerror != NULL && *gerror != NULL) goto fail; } - + if (c == '/') context->state = CLOSING_ELEMENT; else { @@ -447,7 +447,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error ("%s", "Too many closing tags, not enough open tags"); goto fail; } - + text = (char*)current->data; if (context->parser.end_element != NULL){ context->parser.end_element (context, text, context->user_data, gerror); @@ -460,13 +460,13 @@ g_markup_parse_context_parse (GMarkupParseContext *context, while (p < end && *p != '>') p++; - + context->level = context->level->next; g_slist_free_1 (current); context->state = TEXT; break; } /* case CLOSING_ELEMENT */ - + } /* switch */ } @@ -475,7 +475,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, fail: if (context->parser.error && gerror != NULL && *gerror) context->parser.error (context, *gerror, context->user_data); - + destroy_parse_state (context); return FALSE; } diff --git a/src/mono/mono/eglib/gmem.c b/src/mono/mono/eglib/gmem.c index 11d117bb60944..b50a241571504 100644 --- a/src/mono/mono/eglib/gmem.c +++ b/src/mono/mono/eglib/gmem.c @@ -111,14 +111,14 @@ gpointer g_realloc (gpointer obj, gsize size) g_error ("Could not allocate %i bytes", size); } -gpointer -g_malloc (gsize x) -{ +gpointer +g_malloc (gsize x) +{ gpointer ptr; if (!x) return 0; ptr = G_MALLOC_INTERNAL (x); - if (ptr) + if (ptr) return ptr; g_error ("Could not allocate %i bytes", x); } @@ -133,12 +133,12 @@ gpointer g_calloc (gsize n, gsize x) return ptr; g_error ("Could not allocate %i (%i * %i) bytes", x*n, n, x); } -gpointer g_malloc0 (gsize x) -{ +gpointer g_malloc0 (gsize x) +{ return g_calloc (1,x); } -gpointer g_try_malloc (gsize x) +gpointer g_try_malloc (gsize x) { if (x) return G_MALLOC_INTERNAL (x); @@ -147,10 +147,10 @@ gpointer g_try_malloc (gsize x) gpointer g_try_realloc (gpointer obj, gsize size) -{ +{ if (!size) { G_FREE_INTERNAL (obj); return 0; - } + } return G_REALLOC_INTERNAL (obj, size); } diff --git a/src/mono/mono/eglib/gmisc-unix.c b/src/mono/mono/eglib/gmisc-unix.c index 2630d515fda5f..0c8ec6bec8d47 100644 --- a/src/mono/mono/eglib/gmisc-unix.c +++ b/src/mono/mono/eglib/gmisc-unix.c @@ -43,8 +43,8 @@ static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER; /* MONO Comment - * - * As per the UNIX spec, + * + * As per the UNIX spec, * "The return value from getenv() may point to static data which may be overwritten by subsequent calls to getenv(), setenv(), or unsetenv()." * Source: Unix Manual Pages for getenv, IEEE Std 1003.1 * @@ -56,7 +56,7 @@ static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER; * g_getenv does not mimic the behavior of POSIX getenv anymore. * * The memory address returned will be unique to the invocaton, and must be freed. - * */ + * */ gchar * g_getenv (const gchar *variable) { diff --git a/src/mono/mono/eglib/gmisc-win32.c b/src/mono/mono/eglib/gmisc-win32.c index 82860a575ed12..0c2f6e12f2a4d 100644 --- a/src/mono/mono/eglib/gmisc-win32.c +++ b/src/mono/mono/eglib/gmisc-win32.c @@ -48,7 +48,7 @@ g_getenv(const gchar *variable) gchar* val = NULL; gint32 buffer_size = 1024; gint32 retval; - var = u8to16(variable); + var = u8to16(variable); // FIXME This should loop in case another thread is growing the data. buffer = g_new (gunichar2, buffer_size); retval = GetEnvironmentVariableW (var, buffer, buffer_size); @@ -68,7 +68,7 @@ g_getenv(const gchar *variable) } g_free(var); g_free(buffer); - return val; + return val; } gboolean @@ -76,7 +76,7 @@ g_setenv(const gchar *variable, const gchar *value, gboolean overwrite) { gunichar2 *var, *val; gboolean result; - var = u8to16(variable); + var = u8to16(variable); val = u8to16(value); result = (SetEnvironmentVariableW(var, val) != 0) ? TRUE : FALSE; g_free(var); @@ -88,7 +88,7 @@ void g_unsetenv(const gchar *variable) { gunichar2 *var; - var = u8to16(variable); + var = u8to16(variable); SetEnvironmentVariableW(var, L""); g_free(var); } @@ -141,7 +141,7 @@ g_path_is_absolute (const char *filename) (filename[2] == '\\' || filename[2] == '/')) return TRUE; /* UNC paths */ - else if (filename[0] == '\\' && filename[1] == '\\' && + else if (filename[0] == '\\' && filename[1] == '\\' && filename[2] != '\0') return TRUE; } diff --git a/src/mono/mono/eglib/gmodule-unix.c b/src/mono/mono/eglib/gmodule-unix.c index 24b3a3023b114..bd5cc2648d80e 100644 --- a/src/mono/mono/eglib/gmodule-unix.c +++ b/src/mono/mono/eglib/gmodule-unix.c @@ -50,7 +50,7 @@ g_module_open (const gchar *file, GModuleFlags flags) int f = 0; GModule *module; void *handle; - + flags &= G_MODULE_BIND_MASK; if ((flags & G_MODULE_BIND_LAZY) != 0) f |= RTLD_LAZY; @@ -60,10 +60,10 @@ g_module_open (const gchar *file, GModuleFlags flags) handle = dlopen (file, f); if (handle == NULL) return NULL; - + module = g_new (GModule,1); module->handle = handle; - + return module; } @@ -167,7 +167,7 @@ g_module_open (const gchar *file, GModuleFlags flags) if (file != NULL) { gunichar2 *file16; - file16 = u8to16(file); + file16 = u8to16(file); module->main_module = FALSE; module->handle = LoadLibrary (file16); g_free(file16); @@ -175,7 +175,7 @@ g_module_open (const gchar *file, GModuleFlags flags) g_free (module); return NULL; } - + } else { module->main_module = TRUE; module->handle = GetModuleHandle (NULL); @@ -257,7 +257,7 @@ g_module_error (void) TCHAR* buf = NULL; DWORD code = GetLastError (); - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL); ret = u16to8 (buf); @@ -320,15 +320,15 @@ gchar * g_module_build_path (const gchar *directory, const gchar *module_name) { const char *lib_prefix = ""; - + if (module_name == NULL) return NULL; if (strncmp (module_name, "lib", 3) != 0) lib_prefix = LIBPREFIX; - + if (directory && *directory) return g_strdup_printf ("%s/%s%s" LIBSUFFIX, directory, lib_prefix, module_name); - return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); + return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); } diff --git a/src/mono/mono/eglib/goutput.c b/src/mono/mono/eglib/goutput.c index 82ba7c09d03d0..bee7f9446a6b3 100644 --- a/src/mono/mono/eglib/goutput.c +++ b/src/mono/mono/eglib/goutput.c @@ -124,7 +124,7 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask) GLogLevelFlags old_fatal = fatal; fatal |= fatal_mask; - + return old_fatal; } @@ -147,7 +147,7 @@ g_logstr (const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg) { if (!default_log_func) default_log_func = g_log_default_handler; - + default_log_func (log_domain, log_level, msg, default_log_func_user_data); } diff --git a/src/mono/mono/eglib/gpath.c b/src/mono/mono/eglib/gpath.c index e6ec47b05f1ee..96f67f27388bb 100644 --- a/src/mono/mono/eglib/gpath.c +++ b/src/mono/mono/eglib/gpath.c @@ -32,7 +32,7 @@ #include #ifdef G_OS_WIN32 -#include +#include #endif #ifdef HAVE_UNISTD_H @@ -47,45 +47,45 @@ g_build_path (const gchar *separator, const gchar *first_element, ...) GString *path; va_list args; size_t slen; - + g_return_val_if_fail (separator != NULL, NULL); - + path = g_string_sized_new (48); slen = strlen (separator); - + va_start (args, first_element); for (elem = first_element; elem != NULL; elem = next) { /* trim any trailing separators from @elem */ endptr = elem + strlen (elem); trimmed = FALSE; - + while (endptr >= elem + slen) { if (strncmp (endptr - slen, separator, slen) != 0) break; - + endptr -= slen; trimmed = TRUE; } - + /* append elem, not including any trailing separators */ if (endptr > elem) g_string_append_len (path, elem, endptr - elem); - + /* get the next element */ do { if (!(next = va_arg (args, char *))) break; - + /* remove leading separators */ while (!strncmp (next, separator, slen)) next += slen; } while (*next == '\0'); - + if (next || trimmed) g_string_append_len (path, separator, slen); } va_end (args); - + return g_string_free (path, FALSE); } @@ -149,7 +149,7 @@ g_path_get_basename (const char *filename) r = strrchr_seperator (copy); if (r == NULL){ - g_free (copy); + g_free (copy); return g_strdup ("/"); } r = g_strdup (&r[1]); @@ -170,10 +170,10 @@ strtok_r(char *s, const char *delim, char **last) char *spanp; int c, sc; char *tok; - + if (s == NULL && (s = *last) == NULL) return NULL; - + /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ @@ -247,8 +247,8 @@ g_find_program_in_path (const gchar *program) #endif while ((l = strtok_r (x, G_SEARCHPATH_SEPARATOR_S, &save)) != NULL){ - char *probe_path; - + char *probe_path; + x = NULL; probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program, NULL); #ifdef HAVE_ACCESS @@ -309,7 +309,7 @@ g_ensure_directory_exists (const gchar *filename) gunichar2 *p; gunichar2 *dir_utf16 = NULL; int retval; - + if (!dir_utf8 || !dir_utf8 [0]) return FALSE; @@ -332,7 +332,7 @@ g_ensure_directory_exists (const gchar *filename) p = dir_utf16; /* get past C:\ )*/ - while (*p++ != '\\') + while (*p++ != '\\') { } @@ -349,7 +349,7 @@ g_ensure_directory_exists (const gchar *filename) break; *p++ = '\\'; } - + g_free (dir_utf16); return TRUE; #else @@ -357,17 +357,17 @@ g_ensure_directory_exists (const gchar *filename) gchar *dir = g_path_get_dirname (filename); int retval; struct stat sbuf; - + if (!dir || !dir [0]) { g_free (dir); return FALSE; } - + if (stat (dir, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) { g_free (dir); return TRUE; } - + p = dir; while (*p == '/') p++; @@ -385,7 +385,7 @@ g_ensure_directory_exists (const gchar *filename) break; *p++ = '/'; } - + g_free (dir); return TRUE; #endif diff --git a/src/mono/mono/eglib/gpattern.c b/src/mono/mono/eglib/gpattern.c index 1bece4df7726e..1ddbdb18f6263 100644 --- a/src/mono/mono/eglib/gpattern.c +++ b/src/mono/mono/eglib/gpattern.c @@ -176,7 +176,7 @@ match_string (GSList *list, const gchar *str, size_t idx, size_t max) idx += len; list = list->next; if (list) { - /* + /* * When recursing, we need this to avoid returning FALSE * because 'list' will not be NULL */ diff --git a/src/mono/mono/eglib/gptrarray.c b/src/mono/mono/eglib/gptrarray.c index 18509bc4accf3..a22288b09895e 100644 --- a/src/mono/mono/eglib/gptrarray.c +++ b/src/mono/mono/eglib/gptrarray.c @@ -37,7 +37,7 @@ typedef struct _GPtrArrayPriv { guint size; } GPtrArrayPriv; -static void +static void g_ptr_array_grow(GPtrArrayPriv *array, guint length) { g_assert (array); @@ -93,7 +93,7 @@ g_ptr_array_free(GPtrArray *array, gboolean free_seg) } g_free(array); - + return data; } @@ -104,7 +104,7 @@ g_ptr_array_set_size(GPtrArray *array, gint length) if((size_t)length > array->len) { g_ptr_array_grow((GPtrArrayPriv *)array, length); - memset(array->pdata + array->len, 0, (length - array->len) + memset(array->pdata + array->len, 0, (length - array->len) * sizeof(gpointer)); } @@ -133,7 +133,7 @@ g_ptr_array_remove_index(GPtrArray *array, guint index) g_memmove(array->pdata + index, array->pdata + index + 1, (array->len - index - 1) * sizeof(gpointer)); } - + array->len--; array->pdata[array->len] = NULL; @@ -199,7 +199,7 @@ g_ptr_array_remove_fast(GPtrArray *array, gpointer data) return FALSE; } -void +void g_ptr_array_foreach(GPtrArray *array, GFunc func, gpointer user_data) { guint i; @@ -220,7 +220,7 @@ void g_ptr_array_sort_with_data (GPtrArray *array, GCompareDataFunc compare, gpointer user_data) { g_assert (array); - + g_qsort_with_data (array->pdata, array->len, sizeof (gpointer), compare, user_data); } diff --git a/src/mono/mono/eglib/gqsort.c b/src/mono/mono/eglib/gqsort.c index cbc9089d33175..f06a3e2efe043 100644 --- a/src/mono/mono/eglib/gqsort.c +++ b/src/mono/mono/eglib/gqsort.c @@ -73,85 +73,85 @@ g_qsort_with_data (gpointer base, size_t nmemb, size_t size, GCompareDataFunc co size_t n, n1, n2; char *lo, *hi; int swaplong; - + if (nmemb <= 1) return; - + SWAP_INIT (); - + /* initialize our stack */ sp = stack; QSORT_PUSH (sp, base, nmemb); - + do { QSORT_POP (sp, lo, n); - + hi = lo + (n - 1) * size; - + if (n < MAX_THRESHOLD) { /* switch to insertion sort */ for (i = lo + size; i <= hi; i += size) for (k = i; k > lo && compare (k - size, k, user_data) > 0; k -= size) SWAP (k - size, k); - + continue; } - + /* calculate the middle element */ mid = lo + (n / 2) * size; - + /* once we re-order the lo, mid, and hi elements to be in * ascending order, we'll use mid as our pivot. */ if (compare (mid, lo, user_data) < 0) { SWAP (mid, lo); } - + if (compare (hi, mid, user_data) < 0) { SWAP (mid, hi); if (compare (mid, lo, user_data) < 0) { SWAP (mid, lo); } } - + /* since we've already guaranteed that lo <= mid and mid <= hi, * we can skip comparing them again */ i = lo + size; k = hi - size; - + do { /* find the first element with a value > pivot value */ while (i < k && compare (i, mid, user_data) <= 0) i += size; - + /* find the last element with a value <= pivot value */ while (k >= i && compare (mid, k, user_data) < 0) k -= size; - + if (k <= i) break; - + SWAP (i, k); - + /* make sure we keep track of our pivot element */ if (mid == i) { mid = k; } else if (mid == k) { mid = i; } - + i += size; k -= size; } while (1); - + if (k != mid) { /* swap the pivot with the last element in the first partition */ SWAP (mid, k); } - + /* calculate segment sizes */ n2 = (hi - k) / size; n1 = (k - lo) / size; - + /* push our partitions onto the stack, largest first * (to make sure we don't run out of stack space) */ if (n2 > n1) { diff --git a/src/mono/mono/eglib/gqueue.c b/src/mono/mono/eglib/gqueue.c index f9bba47aee4ba..adf5700b7c5df 100644 --- a/src/mono/mono/eglib/gqueue.c +++ b/src/mono/mono/eglib/gqueue.c @@ -12,10 +12,10 @@ * 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 @@ -58,7 +58,7 @@ g_queue_is_empty (GQueue *queue) { if (!queue) return TRUE; - + return queue->length == 0; } @@ -67,9 +67,9 @@ g_queue_push_head (GQueue *queue, gpointer head) { if (!queue) return; - + queue->head = g_list_prepend (queue->head, head); - + if (!queue->tail) queue->tail = queue->head; @@ -101,12 +101,12 @@ g_queue_free (GQueue *queue) { if (!queue) return; - + g_list_free (queue->head); g_free (queue); } -void +void g_queue_foreach (GQueue *queue, GFunc func, gpointer user_data) { g_list_foreach (queue->head, func, user_data); diff --git a/src/mono/mono/eglib/gshell.c b/src/mono/mono/eglib/gshell.c index 820ac46c2fff8..5fdf99d35c094 100644 --- a/src/mono/mono/eglib/gshell.c +++ b/src/mono/mono/eglib/gshell.c @@ -64,7 +64,7 @@ split_cmdline (const gchar *cmdline, GPtrArray *array, GError **gerror) } } else if (c == '\\' && quote_char == '\"'){ escaped = TRUE; - } else + } else g_string_append_c (str, c); } else if (g_ascii_isspace (c)) { if (str->len > 0) { @@ -150,7 +150,7 @@ g_shell_quote (const gchar *unquoted_string) { GString *result = g_string_new ("'"); const gchar *p; - + for (p = unquoted_string; *p; p++){ if (*p == '\'') g_string_append (result, "'\\'"); @@ -169,7 +169,7 @@ g_shell_unquote (const gchar *quoted_string, GError **gerror) if (quoted_string == NULL) return NULL; - + /* Quickly try to determine if we need to unquote or not */ for (p = quoted_string; *p; p++){ if (*p == '\'' || *p == '"' || *p == '\\'){ @@ -177,7 +177,7 @@ g_shell_unquote (const gchar *quoted_string, GError **gerror) break; } } - + if (!do_unquote) return g_strdup (quoted_string); @@ -217,7 +217,7 @@ g_shell_unquote (const gchar *quoted_string, GError **gerror) g_string_append_c (result, '\\'); break; } - } + } g_string_append_c (result, *p); } if (!*p){ @@ -257,8 +257,8 @@ char *args [] = { "\\\\", "'\\\\'", "\"f\\$\"\\\"\\\\", // /\\\"\\\\" - "'f\\$'\\\"\\\\", - "'f\\$\\\\'", + "'f\\$'\\\"\\\\", + "'f\\$\\\\'", NULL }; @@ -268,12 +268,12 @@ main () { char **s = args; int i; - + while (*s){ char *r1 = g_shell_unquote (*s, NULL); char *r2 = g2_shell_unquote (*s, NULL); char *ok = r1 == r2 ? "ok" : (r1 != NULL && r2 != NULL && strcmp (r1, r2) == 0) ? "ok" : "fail"; - + printf ("%s [%s] -> [%s] - [%s]\n", ok, *s, r1, r2); s++; } @@ -283,7 +283,7 @@ main () buffer [1] = '\\'; buffer [3] = '\"'; buffer [4] = 0; - + for (i = 32; i < 255; i++){ buffer [2] = i; printf ("%d [%s] -> [%s]\n", i, buffer, g_shell_unquote (buffer, NULL)); diff --git a/src/mono/mono/eglib/gslist.c b/src/mono/mono/eglib/gslist.c index 65744eaa73b72..71cd6dfd972e9 100644 --- a/src/mono/mono/eglib/gslist.c +++ b/src/mono/mono/eglib/gslist.c @@ -12,10 +12,10 @@ * 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 @@ -60,7 +60,7 @@ g_slist_prepend (GSList *list, gpointer data) } /* - * Insert the given data in a new node after the current node. + * Insert the given data in a new node after the current node. * Return new node. */ static GSList * @@ -186,14 +186,14 @@ g_slist_find_custom (GSList *list, gconstpointer data, GCompareFunc func) { if (!func) return NULL; - + while (list) { if (func (list->data, data) == 0) return list; - + list = list->next; } - + return NULL; } @@ -299,7 +299,7 @@ GSList* g_slist_insert_sorted (GSList *list, gpointer data, GCompareFunc func) { GSList *prev = NULL; - + if (!func) return list; @@ -320,15 +320,15 @@ gint g_slist_index (GSList *list, gconstpointer data) { gint index = 0; - + while (list) { if (list->data == data) return index; - + index++; list = list->next; } - + return -1; } diff --git a/src/mono/mono/eglib/gspawn.c b/src/mono/mono/eglib/gspawn.c index 03711f9affd06..7dc6fbcd8c7ff 100644 --- a/src/mono/mono/eglib/gspawn.c +++ b/src/mono/mono/eglib/gspawn.c @@ -84,9 +84,9 @@ mono_close_pipe (int p [2]) #if defined(__APPLE__) #if defined (TARGET_OSX) -/* Apple defines this in crt_externs.h but doesn't provide that header for +/* Apple defines this in crt_externs.h but doesn't provide that header for * arm-apple-darwin9. We'll manually define the symbol on Apple as it does - * in fact exist on all implementations (so far) + * in fact exist on all implementations (so far) */ G_BEGIN_DECLS gchar ***_NSGetEnviron(void); @@ -131,12 +131,12 @@ read_pipes (int outfd, gchar **out_str, int errfd, gchar **err_str, GError **ger if (out_str) { *out_str = NULL; out = g_string_new (""); - } + } if (err_str) { *err_str = NULL; err = g_string_new (""); - } + } do { if (out_closed && err_closed) @@ -208,18 +208,18 @@ write_all (int fd, const void *vbuf, size_t n) const char *buf = (const char *) vbuf; size_t nwritten = 0; int w; - + do { do { w = write (fd, buf + nwritten, n - nwritten); } while (w == -1 && errno == EINTR); - + if (w == -1) return -1; - + nwritten += w; } while (nwritten < n); - + return nwritten; } @@ -264,7 +264,7 @@ g_spawn_command_line_sync (const gchar *command_line, int stderr_pipe [2] = { -1, -1 }; int status; int res; - + if (!g_shell_parse_argv (command_line, &argc, &argv, gerror)) return FALSE; diff --git a/src/mono/mono/eglib/gstr.c b/src/mono/mono/eglib/gstr.c index cbf63d8f02b97..8e03bf7e2e465 100644 --- a/src/mono/mono/eglib/gstr.c +++ b/src/mono/mono/eglib/gstr.c @@ -38,9 +38,9 @@ #include -/* - * g_strndup and g_vasprintf need to allocate memory with g_malloc if - * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free +/* + * g_strndup and g_vasprintf need to allocate memory with g_malloc if + * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free * rather than free. */ @@ -71,7 +71,7 @@ gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap) int len; size_t buflen; va_list ap2; - + #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) ap2 = ap; len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) @@ -139,7 +139,7 @@ g_str_has_suffix(const gchar *str, const gchar *suffix) { size_t str_length; size_t suffix_length; - + g_return_val_if_fail(str != NULL, FALSE); g_return_val_if_fail(suffix != NULL, FALSE); @@ -156,7 +156,7 @@ g_str_has_prefix(const gchar *str, const gchar *prefix) { size_t str_length; size_t prefix_length; - + g_return_val_if_fail(str != NULL, FALSE); g_return_val_if_fail(prefix != NULL, FALSE); @@ -173,7 +173,7 @@ g_strdup_vprintf (const gchar *format, va_list args) { int n; char *ret; - + n = g_vasprintf (&ret, format, args); if (n == -1) return NULL; @@ -301,7 +301,7 @@ g_strconcat (const gchar *first, ...) len += strlen (s); } va_end (args); - + ret = (char*)g_malloc (len + 1); if (ret == NULL) return NULL; @@ -323,24 +323,24 @@ g_strconcat (const gchar *first, ...) static void add_to_vector (gchar ***vector, int size, gchar *token) { - *vector = *vector == NULL ? + *vector = *vector == NULL ? (gchar **)g_malloc(2 * sizeof(*vector)) : (gchar **)g_realloc(*vector, (size + 1) * sizeof(*vector)); - + (*vector)[size - 1] = token; } -gchar ** +gchar ** g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) { const gchar *c; gchar *token, **vector; gint size = 1; - + g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (delimiter != NULL, NULL); g_return_val_if_fail (delimiter[0] != 0, NULL); - + if (strncmp (string, delimiter, strlen (delimiter)) == 0) { vector = (gchar **)g_malloc (2 * sizeof(vector)); vector[0] = g_strdup (""); @@ -375,7 +375,7 @@ g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) token = g_strdup (c); } } - + add_to_vector (&vector, size, token); size++; } @@ -389,14 +389,14 @@ g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) } size++; } - + if (vector == NULL) { vector = (gchar **) g_malloc (2 * sizeof (vector)); vector [0] = NULL; } else if (size > 0) { vector[size - 1] = NULL; } - + return vector; } @@ -409,21 +409,21 @@ charcmp (gchar testchar, const gchar *compare) } compare++; } - + return FALSE; } -gchar ** +gchar ** g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens) { const gchar *c; gchar *token, **vector; gint size = 1; - + g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (delimiter != NULL, NULL); g_return_val_if_fail (delimiter[0] != 0, NULL); - + if (charcmp (*string, delimiter)) { vector = (gchar **)g_malloc (2 * sizeof(vector)); vector[0] = g_strdup (""); @@ -442,16 +442,16 @@ g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens) } else { token = g_strndup (c, toklen); } - + c = string + 1; - + add_to_vector (&vector, size, token); size++; } string++; } - + if (max_tokens > 0 && size >= max_tokens) { if (*string) { /* Add the rest of the string as the last element */ @@ -471,14 +471,14 @@ g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens) size++; } } - + if (vector == NULL) { vector = (gchar **) g_malloc (2 * sizeof (vector)); vector [0] = NULL; } else if (size > 0) { vector[size - 1] = NULL; } - + return vector; } @@ -514,7 +514,7 @@ g_strjoin (const gchar *separator, ...) slen = strlen (separator); else slen = 0; - + len = 0; va_start (args, separator); for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){ @@ -525,7 +525,7 @@ g_strjoin (const gchar *separator, ...) if (len == 0) return g_strdup (""); - + /* Remove the last separator */ if (slen > 0 && len > 0) len -= slen; @@ -549,12 +549,12 @@ g_strjoinv (const gchar *separator, gchar **str_array) { char *res, *r; size_t slen, len, i; - + if (separator != NULL) slen = strlen (separator); else slen = 0; - + len = 0; for (i = 0; str_array [i] != NULL; i++){ len += strlen (str_array [i]); @@ -641,7 +641,7 @@ g_snprintf(gchar *string, gulong n, gchar const *format, ...) { va_list args; gint ret; - + va_start(args, format); ret = vsnprintf(string, n, format, args); va_end(args); @@ -657,7 +657,7 @@ char_needs_encoding (char c) { if (((unsigned char)c) >= 0x80) return TRUE; - + if ((c >= '@' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '&' && c < 0x3b) || @@ -677,7 +677,7 @@ g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **gerror #else const char *uriPrefix = "file://"; #endif - + g_return_val_if_fail (filename != NULL, NULL); if (hostname != NULL) @@ -686,10 +686,10 @@ g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **gerror if (!g_path_is_absolute (filename)){ if (gerror != NULL) *gerror = g_error_new (NULL, 2, "Not an absolute filename"); - + return NULL; } - + n = strlen (uriPrefix) + 1; for (p = filename; *p; p++){ #ifdef G_OS_WIN32 @@ -742,7 +742,7 @@ g_filename_from_uri (const gchar *uri, gchar **hostname, GError **gerror) const char *p; char *r, *result; int flen = 0; - + g_return_val_if_fail (uri != NULL, NULL); if (hostname != NULL) @@ -763,7 +763,7 @@ g_filename_from_uri (const gchar *uri, gchar **hostname, GError **gerror) *gerror = g_error_new (NULL, 2, "URI contains an invalid escape sequence"); return NULL; } - } + } flen++; } #ifndef G_OS_WIN32 @@ -822,16 +822,16 @@ gchar * g_ascii_strdown (const gchar *str, gssize len) { char *ret; - + g_return_val_if_fail (str != NULL, NULL); if (len == -1) len = strlen (str); - + ret = g_malloc (len + 1); g_ascii_strdown_no_alloc (ret, str, len); ret [len] = 0; - + return ret; } @@ -846,17 +846,17 @@ g_ascii_strup (const gchar *str, gssize len) { char *ret; int i; - + g_return_val_if_fail (str != NULL, NULL); if (len == -1) len = strlen (str); - + ret = g_malloc (len + 1); for (i = 0; i < len; i++) ret [i] = g_ascii_toupper (str [i]); ret [i] = 0; - + return ret; } @@ -899,7 +899,7 @@ g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n) if (j) return j; } - + return 0; } @@ -965,7 +965,7 @@ g_strdelimit (gchar *string, gchar delimiter, gchar new_delimiter) } } -gsize +gsize g_strlcpy (gchar *dest, const gchar *src, gsize dest_size) { g_assert (src); @@ -1011,9 +1011,9 @@ g_stpcpy (gchar *dest, const char *src) #else while (*src) *dest++ = *src++; - + *dest = '\0'; - + return dest; #endif } @@ -1128,7 +1128,7 @@ g_str_from_file_region (int fd, guint64 offset, gsize size) char *buffer; off_t loc; int status; - + do { loc = lseek (fd, offset, SEEK_SET); } while (loc == -1 && errno == EINTR); diff --git a/src/mono/mono/eglib/gstring.c b/src/mono/mono/eglib/gstring.c index 403b3ec416736..de3f0658de4c6 100644 --- a/src/mono/mono/eglib/gstring.c +++ b/src/mono/mono/eglib/gstring.c @@ -78,12 +78,12 @@ gchar * g_string_free (GString *string, gboolean free_segment) { gchar *data; - + g_return_val_if_fail (string != NULL, NULL); data = string->str; g_free(string); - + if(!free_segment) { return data; } @@ -125,7 +125,7 @@ g_string_append_c (GString *string, gchar c) g_return_val_if_fail(string != NULL, NULL); GROW_IF_NECESSARY(string, 1); - + string->str[string->len] = c; string->str[string->len + 1] = 0; string->len++; @@ -138,12 +138,12 @@ g_string_append_unichar (GString *string, gunichar c) { gchar utf8[6]; gint len; - + g_return_val_if_fail (string != NULL, NULL); - + if ((len = g_unichar_to_utf8 (c, utf8)) <= 0) return string; - + return g_string_append_len (string, utf8, len); } @@ -152,7 +152,7 @@ g_string_append_printf (GString *string, const gchar *format, ...) { char *ret; va_list args; - + g_return_if_fail (string != NULL); g_return_if_fail (format != NULL); @@ -181,12 +181,12 @@ void g_string_printf (GString *string, const gchar *format, ...) { va_list args; - + g_return_if_fail (string != NULL); g_return_if_fail (format != NULL); g_free (string->str); - + va_start (args, format); string->str = g_strdup_vprintf (format, args); va_end (args); @@ -203,7 +203,7 @@ g_string_truncate (GString *string, gsize len) /* Silent return */ if (len >= string->len) return string; - + string->len = len; string->str[len] = 0; return string; @@ -215,7 +215,7 @@ g_string_set_size (GString *string, gsize len) g_return_val_if_fail (string != NULL, string); GROW_IF_NECESSARY(string, len); - + string->len = len; string->str[len] = 0; return string; diff --git a/src/mono/mono/eglib/gunicode-win32.c b/src/mono/mono/eglib/gunicode-win32.c index bbae5972f318d..c402b6301c4e5 100644 --- a/src/mono/mono/eglib/gunicode-win32.c +++ b/src/mono/mono/eglib/gunicode-win32.c @@ -30,7 +30,7 @@ g_get_charset (G_CONST_RETURN char **charset) eg_my_charset = buf; is_utf8 = FALSE; } - + if (charset != NULL) *charset = eg_my_charset; diff --git a/src/mono/mono/eglib/gutf8.c b/src/mono/mono/eglib/gutf8.c index ab6e190b91dfe..8be331aaae774 100644 --- a/src/mono/mono/eglib/gutf8.c +++ b/src/mono/mono/eglib/gutf8.c @@ -36,13 +36,13 @@ utf8_case_conv (const gchar *str, gssize len, gboolean upper) gunichar *ustr; glong i, ulen; gchar *utf8; - + ustr = g_utf8_to_ucs4_fast (str, (glong) len, &ulen); for (i = 0; i < ulen; i++) ustr[i] = upper ? g_unichar_toupper (ustr[i]) : g_unichar_tolower (ustr[i]); utf8 = g_ucs4_to_utf8 (ustr, ulen, NULL, NULL, NULL); g_free (ustr); - + return utf8; } @@ -63,7 +63,7 @@ utf8_validate (const unsigned char *inptr, size_t len) { const unsigned char *ptr = inptr + len; unsigned char c; - + /* Everything falls through when TRUE... */ switch (len) { default: @@ -71,7 +71,7 @@ utf8_validate (const unsigned char *inptr, size_t len) case 4: if ((c = (*--ptr)) < 0x80 || c > 0xBF) return FALSE; - + if ((c == 0xBF || c == 0xBE) && ptr[-1] == 0xBF) { if (ptr[-2] == 0x8F || ptr[-2] == 0x9F || ptr[-2] == 0xAF || ptr[-2] == 0xBF) @@ -83,7 +83,7 @@ utf8_validate (const unsigned char *inptr, size_t len) case 2: if ((c = (*--ptr)) < 0x80 || c > 0xBF) return FALSE; - + /* no fall-through in this inner switch */ switch (*inptr) { case 0xE0: if (c < 0xA0) return FALSE; break; @@ -97,10 +97,10 @@ utf8_validate (const unsigned char *inptr, size_t len) } case 1: if (*inptr >= 0x80 && *inptr < 0xC2) return FALSE; } - + if (*inptr > 0xF4) return FALSE; - + return TRUE; } @@ -126,10 +126,10 @@ g_utf8_validate (const gchar *str, gssize max_len, const gchar **end) gboolean valid = TRUE; guint length, min; gssize n = 0; - + if (max_len == 0) return FALSE; - + if (max_len < 0) { while (*inptr != 0) { length = g_utf8_jump_table[*inptr]; @@ -137,7 +137,7 @@ g_utf8_validate (const gchar *str, gssize max_len, const gchar **end) valid = FALSE; break; } - + inptr += length; } } else { @@ -148,28 +148,28 @@ g_utf8_validate (const gchar *str, gssize max_len, const gchar **end) valid = FALSE; break; } - + length = g_utf8_jump_table[*inptr]; min = MIN (length, max_len - n); - + if (!utf8_validate (inptr, min)) { valid = FALSE; break; } - + if (min < length) { valid = FALSE; break; } - + inptr += length; n += length; } } - + if (end != NULL) *end = (gchar *) inptr; - + return valid; } @@ -179,10 +179,10 @@ g_utf8_get_char_validated (const gchar *str, gssize max_len) unsigned char *inptr = (unsigned char *) str; gunichar u = *inptr; int n, i; - + if (max_len == 0) return -2; - + if (u < 0x80) { /* simple ascii case */ return u; @@ -206,21 +206,21 @@ g_utf8_get_char_validated (const gchar *str, gssize max_len) } else { return -1; } - + if (max_len > 0) { if (!utf8_validate (inptr, MIN (max_len, n))) return -1; - + if (max_len < n) return -2; } else { if (!utf8_validate (inptr, n)) return -1; } - + for (i = 1; i < n; i++) u = (u << 6) | (*++inptr ^ 0x80); - + return u; } @@ -229,10 +229,10 @@ g_utf8_strlen (const gchar *str, gssize max_len) { const guchar *inptr = (const guchar *) str; glong clen = 0, len = 0, n; - + if (max_len == 0) return 0; - + if (max_len < 0) { while (*inptr) { inptr += g_utf8_jump_table[*inptr]; @@ -243,13 +243,13 @@ g_utf8_strlen (const gchar *str, gssize max_len) n = g_utf8_jump_table[*inptr]; if ((clen + n) > max_len) break; - + inptr += n; clen += n; len++; } } - + return len; } @@ -259,7 +259,7 @@ g_utf8_get_char (const gchar *src) unsigned char *inptr = (unsigned char *) src; gunichar u = *inptr; int n, i; - + if (u < 0x80) { /* simple ascii case */ return u; @@ -279,10 +279,10 @@ g_utf8_get_char (const gchar *src) u &= 0x01; n = 6; } - + for (i = 1; i < n; i++) u = (u << 6) | (*++inptr ^ 0x80); - + return u; } @@ -303,12 +303,12 @@ g_utf8_offset_to_pointer (const gchar *str, glong offset) // since the minimum size of a character is 1 // we know we can step back at least offset bytes jump = jump + offset; - + // if we land in the middle of a character // walk to the beginning while ((*jump & 0xc0) == 0x80) jump --; - + // count how many characters we've actually walked // by going forward p = jump; @@ -316,10 +316,10 @@ g_utf8_offset_to_pointer (const gchar *str, glong offset) p = g_utf8_next_char (p); offset ++; } while (p < jump); - + } while (offset < 0); } - + return (gchar *)p; } @@ -329,10 +329,10 @@ g_utf8_pointer_to_offset (const gchar *str, const gchar *pos) const gchar *inptr, *inend; glong offset = 0; glong sign = 1; - + if (pos == str) return 0; - + if (str < pos) { inptr = str; inend = pos; @@ -341,11 +341,11 @@ g_utf8_pointer_to_offset (const gchar *str, const gchar *pos) inend = str; sign = -1; } - + do { inptr = g_utf8_next_char (inptr); offset++; } while (inptr < inend); - + return offset * sign; } diff --git a/src/mono/mono/eglib/sort.frag.h b/src/mono/mono/eglib/sort.frag.h index 6dc1950ae4e9a..10ff451d4e6e8 100644 --- a/src/mono/mono/eglib/sort.frag.h +++ b/src/mono/mono/eglib/sort.frag.h @@ -11,10 +11,10 @@ * 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 diff --git a/src/mono/mono/eglib/test/array.c b/src/mono/mono/eglib/test/array.c index 20865dadbe8cb..305c2f317396b 100644 --- a/src/mono/mono/eglib/test/array.c +++ b/src/mono/mono/eglib/test/array.c @@ -19,7 +19,7 @@ test_array_big (void) for (i = 0; i < 10000; i++) if (g_array_index (garray, gint, i) != i) return FAILED ("array value didn't match"); - + g_array_free (garray, TRUE); return NULL; @@ -101,7 +101,7 @@ test_array_insert_val (void) g_array_insert_val (array, 2, array); if (array != g_array_index (array, gpointer, 2)) return FAILED ("3 The value in the array is incorrect"); - + g_array_free (array, TRUE); array = g_array_new (FALSE, FALSE, sizeof (gpointer)); ptr0 = array; diff --git a/src/mono/mono/eglib/test/assertf.c b/src/mono/mono/eglib/test/assertf.c index 05484adb91d8b..3a844d75e1776 100644 --- a/src/mono/mono/eglib/test/assertf.c +++ b/src/mono/mono/eglib/test/assertf.c @@ -5,7 +5,7 @@ f is for format, like printf Previously one would say like: if (!expr) g_error(...) - + now: g_assertf(expr, ...); */ diff --git a/src/mono/mono/eglib/test/endian.c b/src/mono/mono/eglib/test/endian.c index d70c7c68c906f..ff40b7d2fce52 100644 --- a/src/mono/mono/eglib/test/endian.c +++ b/src/mono/mono/eglib/test/endian.c @@ -7,7 +7,7 @@ test_swap (void) guint64 b = (((guint64)a) << 32) | a, res64; guint64 b_expect = (((guint64)0x1efcdab) << 32) | 0x01efcdab; guint16 c = 0xabcd, res16; - + res32 = GUINT32_SWAP_LE_BE (a); if (res32 != 0x01efcdab) return FAILED ("GUINT32_SWAP_LE_BE returned 0x%x", res32); @@ -20,8 +20,8 @@ test_swap (void) return FAILED ("GUINT64_SWAP_LE_BE returned 0x%" PRIx64 " (had=0x%" PRIx64 ")", (guint64)res64, (guint64)b); res16 = GUINT16_SWAP_LE_BE(c); if (res16 != 0xcdab) - return FAILED ("GUINT16_SWAP_LE_BE returned 0x%x", (guint32) res16); - + return FAILED ("GUINT16_SWAP_LE_BE returned 0x%x", (guint32) res16); + return OK; } diff --git a/src/mono/mono/eglib/test/fake.c b/src/mono/mono/eglib/test/fake.c index 96e85541182ab..07f511f966216 100644 --- a/src/mono/mono/eglib/test/fake.c +++ b/src/mono/mono/eglib/test/fake.c @@ -1,7 +1,7 @@ /* * Fake test allows debugging of the driver itself */ - + #include "test.h" static RESULT diff --git a/src/mono/mono/eglib/test/hashtable.c b/src/mono/mono/eglib/test/hashtable.c index 94878f3fa8e1c..7ec13baefb995 100644 --- a/src/mono/mono/eglib/test/hashtable.c +++ b/src/mono/mono/eglib/test/hashtable.c @@ -29,7 +29,7 @@ hash_t1 (void) return FAILED ("did not find all keys, got %d expected 2", foreach_count); if (foreach_fail) return FAILED("failed to pass the user-data to foreach"); - + if (!g_hash_table_remove (t, (char*)"my")) return FAILED ("did not find known key"); if (g_hash_table_size (t) != 1) @@ -37,7 +37,7 @@ hash_t1 (void) g_hash_table_insert(t, (char*)"hello", (char*)"moon"); if (strcmp (g_hash_table_lookup (t, (char*)"hello"), (char*)"moon") != 0) return FAILED ("did not replace world with moon"); - + if (!g_hash_table_remove (t, (char*)"hello")) return FAILED ("did not find known key"); if (g_hash_table_size (t) != 0) @@ -70,7 +70,7 @@ hash_null_lookup (void) { GHashTable *hash = g_hash_table_new (NULL, NULL); gpointer ok, ov; - + g_hash_table_insert (hash, NULL, GINT_TO_POINTER (1)); g_hash_table_insert (hash, GINT_TO_POINTER(1), GINT_TO_POINTER(2)); @@ -87,7 +87,7 @@ hash_null_lookup (void) return FAILED ("Incorrect key found"); if (ov != GINT_TO_POINTER (2)) return FAILED ("Got wrong value %p\n", ov); - + g_hash_table_destroy (hash); return NULL; @@ -106,14 +106,14 @@ hash_grow (void) { GHashTable *hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); int i, count = 0; - + for (i = 0; i < 1000; i++) g_hash_table_insert (hash, g_strdup_printf ("%d", i), g_strdup_printf ("x-%d", i)); for (i = 0; i < 1000; i++){ char buffer [30]; gpointer value; - + sprintf (buffer, "%d", i); value = g_hash_table_lookup (hash, buffer); diff --git a/src/mono/mono/eglib/test/list.c b/src/mono/mono/eglib/test/list.c index b428e2d8dd422..98b2182924cd0 100644 --- a/src/mono/mono/eglib/test/list.c +++ b/src/mono/mono/eglib/test/list.c @@ -41,7 +41,7 @@ test_list_nth (void) nth = g_list_nth (list, 1); if (nth->data != bar) return FAILED ("nth failed. #1"); - + nth = g_list_nth (list, 2); if (nth->data != baz) return FAILED ("nth failed. #2"); @@ -73,7 +73,7 @@ test_list_index (void) i = g_list_index (list, bar); if (i != 1) return FAILED ("index failed. #1: %d", i); - + i = g_list_index (list, baz); if (i != 2) return FAILED ("index failed. #2: %d", i); @@ -104,7 +104,7 @@ test_list_last (void) GList *foo = g_list_prepend (NULL, (char*)"foo"); GList *bar = g_list_prepend (NULL, (char*)"bar"); GList *last; - + foo = g_list_concat (foo, bar); last = g_list_last (foo); @@ -114,7 +114,7 @@ test_list_last (void) foo = g_list_concat (foo, g_list_prepend (NULL, (char*)"baz")); foo = g_list_concat (foo, g_list_prepend (NULL, (char*)"quux")); - last = g_list_last (foo); + last = g_list_last (foo); if (strcmp ("quux", last->data)) return FAILED ("last failed. #2"); @@ -141,7 +141,7 @@ test_list_concat (void) if (g_list_first (list) != foo) return FAILED ("Concat failed. #4"); - + if (g_list_last (list) != bar) return FAILED ("Concat failed. #5"); @@ -176,7 +176,7 @@ test_list_insert_sorted (void) /* insert at the beginning */ list = g_list_insert_sorted (list, (char*)"", compare); if (strcmp ("", list->data)) - return FAILED ("insert_sorted failed. #2"); + return FAILED ("insert_sorted failed. #2"); /* insert at the end */ list = g_list_insert_sorted (list, (char*)"aaaa", compare); @@ -206,7 +206,7 @@ test_list_copy (void) return FAILED ("copy failed."); g_list_free (list); - g_list_free (copy); + g_list_free (copy); return OK; } @@ -234,7 +234,7 @@ test_list_reverse (void) } g_list_free (list); - g_list_free (reverse); + g_list_free (reverse); return OK; } @@ -267,7 +267,7 @@ test_list_remove_link (void) GList *list = foo; foo = g_list_concat (foo, bar); - foo = g_list_concat (foo, baz); + foo = g_list_concat (foo, baz); list = g_list_remove_link (list, bar); @@ -277,7 +277,7 @@ test_list_remove_link (void) if (bar->next != NULL) return FAILED ("remove_link failed #2"); - g_list_free (list); + g_list_free (list); g_list_free (bar); return OK; } @@ -299,7 +299,7 @@ test_list_insert_before (void) return FAILED ("2"); if (strcmp (g_list_nth_data (foo, 1), (char*)"baz")) - return FAILED ("3: %s", g_list_nth_data (foo, 1)); + return FAILED ("3: %s", g_list_nth_data (foo, 1)); g_list_free (foo); return OK; @@ -400,26 +400,26 @@ test_list_find_custom (void) char *foo = (char*)"foo"; char *bar = (char*)"bar"; char *baz = (char*)"baz"; - + list = g_list_prepend (list, baz); list = g_list_prepend (list, bar); list = g_list_prepend (list, foo); - + found = g_list_find_custom (list, baz, find_custom); - + if (found == NULL) return FAILED ("Find failed"); - + g_list_free (list); - + return OK; } static Test list_tests [] = { { "length", test_list_length}, { "nth", test_list_nth}, - { "index", test_list_index}, - { "last", test_list_last}, + { "index", test_list_index}, + { "last", test_list_last}, { "append", test_list_append}, { "concat", test_list_concat}, {"insert_sorted", test_list_insert_sorted}, diff --git a/src/mono/mono/eglib/test/markup.c b/src/mono/mono/eglib/test/markup.c index b7700615a710c..7dd3ca3ea1546 100644 --- a/src/mono/mono/eglib/test/markup.c +++ b/src/mono/mono/eglib/test/markup.c @@ -12,7 +12,7 @@ markup_test (const char *s) GMarkupParser *parser = g_new0 (GMarkupParser, 1); GMarkupParseContext *context; GError *gerror = NULL; - + context = g_markup_parse_context_new (parser, 0, 0, 0); g_markup_parse_context_parse (context, s, strlen (s), &gerror); @@ -39,7 +39,7 @@ invalid_documents (void) do_bad_test (""); do_bad_test (""); do_bad_test (""); - + return OK; } @@ -49,7 +49,7 @@ valid_documents (void) /* These should fail */ do_ok_test (""); do_ok_test (""); - + return OK; } @@ -114,7 +114,7 @@ end_element (GMarkupParseContext *context, GError **gerror) { AppConfigInfo* app_config = (AppConfigInfo*) user_data; - + if (strcmp (element_name, "configuration") == 0) { app_config->configuration_count--; } else if (strcmp (element_name, "startup") == 0) { @@ -136,7 +136,7 @@ domain_test (const char *text) { AppConfigInfo *app_config = g_new0 (AppConfigInfo, 1); GMarkupParseContext *context; - + context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL); if (g_markup_parse_context_parse (context, text, strlen (text), NULL)) { g_markup_parse_context_end_parse (context, NULL); @@ -164,7 +164,7 @@ mono_domain (void) { AppConfigInfo *info; - info = domain_test (""); + info = domain_test (""); if (info->required_runtime == NULL) return FAILED ("No required runtime section"); if (strcmp (info->required_runtime, "v1") != 0) @@ -182,7 +182,7 @@ mono_domain (void) if ((strcmp ((char*)info->supported_runtimes->data, "v1") == 0)){ if (info->supported_runtimes->next == NULL) return FAILED ("Expected 2 supported runtimes"); - + if ((strcmp ((char*)info->supported_runtimes->next->data, "v2") != 0)) return FAILED ("Expected v1, v2, got %s", info->supported_runtimes->next->data); if (info->supported_runtimes->next->next != NULL) @@ -212,7 +212,7 @@ machine_config (void) { char *data; gsize size; - + if (g_file_get_contents ("../../data/net_1_1/machine.config", &data, &size, NULL)){ return markup_test (data); } diff --git a/src/mono/mono/eglib/test/path.c b/src/mono/mono/eglib/test/path.c index 3af25b13b9f6c..a0c2f272289dd 100644 --- a/src/mono/mono/eglib/test/path.c +++ b/src/mono/mono/eglib/test/path.c @@ -22,7 +22,7 @@ test_buildpath (void) char *s; const char *buffer = "var/private"; const char *dir = "/"; - + s = g_build_path ("/", "hola///", "//mundo", (const char*)NULL); if (strcmp (s, "hola/mundo") != 0) return FAILED ("1 Got wrong result, got: %s", s); @@ -47,7 +47,7 @@ test_buildpath (void) if (strcmp (s, "/hello/world/") != 0) return FAILED ("5 Got wrong result, got: %s", s); g_free (s); - + /* Now test multi-char-separators */ s = g_build_path ("**", "hello", "world", (const char*)NULL); if (strcmp (s, "hello**world") != 0) @@ -63,7 +63,7 @@ test_buildpath (void) if (strcmp (s, "hello**world") != 0) return FAILED ("8 Got wrong result, got: %s", s); g_free (s); - + s = g_build_path ("**", "hello**", "**world", (const char*)NULL); if (strcmp (s, "hello**world") != 0) return FAILED ("9 Got wrong result, got: %s", s); @@ -119,7 +119,7 @@ static RESULT test_buildfname (void) { char *s; - + s = g_build_filename ("a", "b", "c", "d", (const char*)NULL); #ifdef G_OS_WIN32 if (strcmp (s, "a\\b\\c\\d") != 0) @@ -143,7 +143,7 @@ test_buildfname (void) if (strcmp (s, "/foo/bar/tolo/meo/") != 0) return FAILED ("1 Got wrong result, got: %s", s); #endif - + return OK; } @@ -195,7 +195,7 @@ test_dirname (void) s = g_path_get_dirname ("/index.html"); if (strcmp (s, "/") != 0) return FAILED ("Expected [/], got [%s]", s); -#endif +#endif return OK; } @@ -274,7 +274,7 @@ test_ppath2 (void) #else const gchar *searchfor = "test-eglib"; #endif - + g_setenv ("PATH", "", TRUE); s = g_find_program_in_path ("ls"); if (s != NULL) { @@ -310,15 +310,15 @@ test_cwd (void) if (dir == NULL) return FAILED ("No current directory?"); g_free (dir); - + if (chdir (newdir) == -1) return FAILED ("No %s?", newdir); - + dir = g_get_current_dir (); if (strcmp (dir, newdir) != 0) return FAILED("Did not go to %s? Instead in %s", newdir, dir); g_free (dir); - + return OK; } #else @@ -334,7 +334,7 @@ test_misc (void) { const char *home = g_get_home_dir (); const char *tmp = g_get_tmp_dir (); - + if (home == NULL) return FAILED ("Where did my home go?"); diff --git a/src/mono/mono/eglib/test/ptrarray.c b/src/mono/mono/eglib/test/ptrarray.c index 51a1396f4c861..f90899814a596 100644 --- a/src/mono/mono/eglib/test/ptrarray.c +++ b/src/mono/mono/eglib/test/ptrarray.c @@ -11,7 +11,7 @@ typedef struct _GPtrArrayPriv { /* Don't add more than 32 items to this please */ static const char *items [] = { - "Apples", "Oranges", "Plumbs", "Goats", "Snorps", "Grapes", + "Apples", "Oranges", "Plumbs", "Goats", "Snorps", "Grapes", "Tickle", "Place", "Coffee", "Cookies", "Cake", "Cheese", "Tseng", "Holiday", "Avenue", "Smashing", "Water", "Toilet", NULL @@ -21,7 +21,7 @@ static GPtrArray *ptrarray_alloc_and_fill(guint *item_count) { GPtrArray *array = g_ptr_array_new(); gint i; - + for(i = 0; items[i] != NULL; i++) { g_ptr_array_add(array, (gpointer)items[i]); } @@ -29,7 +29,7 @@ static GPtrArray *ptrarray_alloc_and_fill(guint *item_count) if (item_count != NULL) { *item_count = i; } - + return array; } @@ -49,18 +49,18 @@ ptrarray_alloc (void) { GPtrArrayPriv *array; guint i; - + array = (GPtrArrayPriv *)ptrarray_alloc_and_fill(&i); - + if (array->size != guess_size(array->len)) { - return FAILED("Size should be %d, but it is %d", + return FAILED("Size should be %d, but it is %d", guess_size(array->len), array->size); } - + if (array->len != i) { return FAILED("Expected %d node(s) in the array", i); } - + g_ptr_array_free((GPtrArray *)array, TRUE); return OK; @@ -76,7 +76,7 @@ RESULT ptrarray_for_iterate (void) char *item = (char *)g_ptr_array_index(array, i); if (item != items[i]) { return FAILED( - "Expected item at %d to be %s, but it was %s", + "Expected item at %d to be %s, but it was %s", i, items[i], item); } } @@ -101,7 +101,7 @@ foreach_callback (gpointer data, gpointer user_data) if (item != item_cmp) { foreach_iterate_error = FAILED( - "Expected item at %d to be %s, but it was %s", + "Expected item at %d to be %s, but it was %s", foreach_iterate_index - 1, item_cmp, item); } } @@ -110,12 +110,12 @@ static RESULT ptrarray_foreach_iterate (void) { GPtrArray *array = ptrarray_alloc_and_fill(NULL); - + foreach_iterate_index = 0; foreach_iterate_error = NULL; - + g_ptr_array_foreach(array, foreach_callback, array); - + g_ptr_array_free(array, TRUE); return foreach_iterate_error; @@ -126,7 +126,7 @@ ptrarray_set_size (void) { GPtrArray *array = g_ptr_array_new(); guint i, grow_length = 50; - + g_ptr_array_add(array, (gpointer)items[0]); g_ptr_array_add(array, (gpointer)items[1]); g_ptr_array_set_size(array, grow_length); @@ -155,9 +155,9 @@ ptrarray_remove_index (void) { GPtrArray *array; guint i; - + array = ptrarray_alloc_and_fill(&i); - + g_ptr_array_remove_index(array, 0); if (array->pdata[0] != items[1]) { return FAILED("First item is not %s, it is %s", items[1], @@ -165,9 +165,9 @@ ptrarray_remove_index (void) } g_ptr_array_remove_index(array, array->len - 1); - + if (array->pdata[array->len - 1] != items[array->len]) { - return FAILED("Last item is not %s, it is %s", + return FAILED("Last item is not %s, it is %s", items[array->len - 2], array->pdata[array->len - 1]); } @@ -206,7 +206,7 @@ ptrarray_remove (void) { GPtrArray *array; guint i; - + array = ptrarray_alloc_and_fill(&i); g_ptr_array_remove(array, (gpointer)items[7]); @@ -242,13 +242,13 @@ ptrarray_sort (void) GPtrArray *array = g_ptr_array_new(); guint i; static gchar * const letters [] = { (char*)"A", (char*)"B", (char*)"C", (char*)"D", (char*)"E" }; - + g_ptr_array_add(array, letters[0]); g_ptr_array_add(array, letters[1]); g_ptr_array_add(array, letters[2]); g_ptr_array_add(array, letters[3]); g_ptr_array_add(array, letters[4]); - + g_ptr_array_sort(array, ptrarray_sort_compare); for (i = 0; i < array->len; i++) { @@ -259,7 +259,7 @@ ptrarray_sort (void) } g_ptr_array_free(array, TRUE); - + return OK; } @@ -307,7 +307,7 @@ ptrarray_remove_fast (void) { GPtrArray *array = g_ptr_array_new(); static gchar * const letters [] = { (char*)"A", (char*)"B", (char*)"C", (char*)"D", (char*)"E" }; - + if (g_ptr_array_remove_fast (array, NULL)) return FAILED ("Removing NULL succeeded"); @@ -339,7 +339,7 @@ ptrarray_remove_fast (void) if (array->pdata [0] != letters [4] || array->pdata [1] != letters [2]) return FAILED ("Last two elements are wrong"); g_ptr_array_free(array, TRUE); - + return OK; } diff --git a/src/mono/mono/eglib/test/queue.c b/src/mono/mono/eglib/test/queue.c index 200952199a8de..f267cb86c8236 100644 --- a/src/mono/mono/eglib/test/queue.c +++ b/src/mono/mono/eglib/test/queue.c @@ -95,12 +95,12 @@ test_queue_pop (void) data = g_queue_pop_head (queue); if (strcmp ("bar", data)) - return FAILED ("expect bar."); + return FAILED ("expect bar."); data = g_queue_pop_head (queue); if (strcmp ("foo", data)) return FAILED ("expect foo."); - + if (g_queue_is_empty (queue) == FALSE) return FAILED ("expect is_empty."); diff --git a/src/mono/mono/eglib/test/shell.c b/src/mono/mono/eglib/test/shell.c index d464f98aed067..4b32f08672571 100644 --- a/src/mono/mono/eglib/test/shell.c +++ b/src/mono/mono/eglib/test/shell.c @@ -11,7 +11,7 @@ test_shell_argv1 (void) gchar **argv; gboolean ret; - /* The next line prints a critical error and returns FALSE + /* The next line prints a critical error and returns FALSE ret = g_shell_parse_argv (NULL, NULL, NULL, NULL); */ ret = g_shell_parse_argv ("", NULL, NULL, NULL); @@ -97,7 +97,7 @@ test_shell_argv1 (void) return FAILED ("24. argv[2] was %s", argv [1]); if (gerror != NULL) return FAILED ("25. error is not null"); - + return OK; } @@ -268,7 +268,7 @@ test_shell_argv4 (void) return FAILED ("6. Expected -e, got: %s", argv [1]); if (strcmp (argv [2], "bash -c 'read -p \"Press any key to continue...\" -n1;'")) return FAILED ("7. Got unexpected result: %s\n", argv [2]); - + return OK; } @@ -299,7 +299,7 @@ test_shell_argv5 (void) return FAILED ("5. Expected echo got %s", argv [0]); if (strcmp (argv [1], "foo,bar")) return FAILED ("6. Expected foo,bar, got: %s", argv [1]); - + return OK; } diff --git a/src/mono/mono/eglib/test/sizes.c b/src/mono/mono/eglib/test/sizes.c index 1f3861fc99a40..cdfab0e95190a 100644 --- a/src/mono/mono/eglib/test/sizes.c +++ b/src/mono/mono/eglib/test/sizes.c @@ -16,7 +16,7 @@ test_formats (void) { char buffer [1024]; gsize a = 1; - + sprintf (buffer, "%" G_GSIZE_FORMAT, a); return NULL; @@ -64,7 +64,7 @@ test_ptrconv (void) uv2 = GPOINTER_TO_UINT (ptr); if (uv != uv2) return FAILED ("uint to pointer and back conversions fail %u != %d", uv, uv2); - + uv = 1; ptr = GUINT_TO_POINTER (uv); uv2 = GPOINTER_TO_UINT (ptr); @@ -78,7 +78,7 @@ test_ptrconv (void) return FAILED ("uint to pointer and back conversions fail %u != %d", uv, uv2); return NULL; - + } typedef struct { @@ -91,7 +91,7 @@ test_offset (void) { if (G_STRUCT_OFFSET (my_struct, a) != 0) return FAILED ("offset of a is not zero"); - + if (G_STRUCT_OFFSET (my_struct, b) != 4 && G_STRUCT_OFFSET (my_struct, b) != 8) return FAILED ("offset of b is 4 or 8, macro might be busted"); diff --git a/src/mono/mono/eglib/test/slist.c b/src/mono/mono/eglib/test/slist.c index b36a9a9c7b525..b678b5427d365 100644 --- a/src/mono/mono/eglib/test/slist.c +++ b/src/mono/mono/eglib/test/slist.c @@ -21,7 +21,7 @@ test_slist_nth (void) nth = g_slist_nth (list, 1); if (nth->data != bar) return FAILED ("nth failed. #1"); - + nth = g_slist_nth (list, 2); if (nth->data != baz) return FAILED ("nth failed. #2"); @@ -53,7 +53,7 @@ test_slist_index (void) i = g_slist_index (list, bar); if (i != 1) return FAILED ("index failed. #1: %d", i); - + i = g_slist_index (list, baz); if (i != 2) return FAILED ("index failed. #2: %d", i); @@ -102,7 +102,7 @@ test_slist_find (void) GSList *list = g_slist_prepend (NULL, (char*)"three"); GSList *found; char *data; - + list = g_slist_prepend (list, (char*)"two"); list = g_slist_prepend (list, (char*)"one"); @@ -131,18 +131,18 @@ test_slist_find_custom (void) char *foo = (char*)"foo"; char *bar = (char*)"bar"; char *baz = (char*)"baz"; - + list = g_slist_prepend (list, baz); list = g_slist_prepend (list, bar); list = g_slist_prepend (list, foo); - + found = g_slist_find_custom (list, baz, find_custom); - + if (found == NULL) return FAILED ("Find failed"); - + g_slist_free (list); - + return OK; } @@ -175,7 +175,7 @@ test_slist_remove_link (void) GSList *list = foo; foo = g_slist_concat (foo, bar); - foo = g_slist_concat (foo, baz); + foo = g_slist_concat (foo, baz); list = g_slist_remove_link (list, bar); @@ -185,7 +185,7 @@ test_slist_remove_link (void) if (bar->next != NULL) return FAILED ("remove_link failed #2"); - g_slist_free (list); + g_slist_free (list); g_slist_free (bar); return OK; @@ -224,7 +224,7 @@ test_slist_insert_sorted (void) if (strcmp ("aaaa", g_slist_last (list)->data)) return FAILED ("insert_sorted failed #3"); - g_slist_free (list); + g_slist_free (list); return OK; } diff --git a/src/mono/mono/eglib/test/string-util.c b/src/mono/mono/eglib/test/string-util.c index fb447229ef404..5c5c445b16c50 100644 --- a/src/mono/mono/eglib/test/string-util.c +++ b/src/mono/mono/eglib/test/string-util.c @@ -12,7 +12,7 @@ test_strfreev (void) array [1] = g_strdup ("two"); array [2] = g_strdup ("three"); array [3] = NULL; - + g_strfreev (array); g_strfreev (NULL); @@ -35,18 +35,18 @@ test_split (void) const gchar *to_split = "Hello world, how are we doing today?"; gint i; gchar **v; - + v= g_strsplit(to_split, " ", 0); - + if(v == NULL) { return FAILED("split failed, got NULL vector (1)"); } - + for(i = 0; v[i] != NULL; i++); if(i != 7) { return FAILED("split failed, expected 7 tokens, got %d", i); } - + g_strfreev(v); v = g_strsplit(to_split, ":", -1); @@ -78,22 +78,22 @@ test_split (void) v = g_strsplit ("appdomain1, Version=0.0.0.0, Culture=neutral", ",", 4); if (strcmp (v [0], "appdomain1") != 0) return FAILED ("Invalid value"); - + if (strcmp (v [1], " Version=0.0.0.0") != 0) return FAILED ("Invalid value"); - + if (strcmp (v [2], " Culture=neutral") != 0) return FAILED ("Invalid value"); if (v [3] != NULL) return FAILED ("Expected only 3 elements"); - + g_strfreev (v); v = g_strsplit ("abcXYdefXghiXYjklYmno", "XY", 4); if (strcmp (v [0], "abc") != 0) return FAILED ("Invalid value 0"); - + if (strcmp (v [1], "defXghi") != 0) return FAILED ("Invalid value 1"); @@ -102,25 +102,25 @@ test_split (void) if (v [3] != NULL) return FAILED ("Expected only 3 elements (1)"); - + g_strfreev (v); v = g_strsplit ("abcXYdefXghiXYjklYmno", "XY", 2); if (strcmp (v [0], "abc") != 0) return FAILED ("Invalid value 3"); - + if (strcmp (v [1], "defXghiXYjklYmno") != 0) return FAILED ("Invalid value 4"); if (v [2] != NULL) return FAILED ("Expected only 2 elements (2)"); - + g_strfreev (v); v = g_strsplit ("abcXYdefXghiXYjklYmnoXY", "XY", 3); if (strcmp (v [0], "abc") != 0) return FAILED ("Invalid value 5"); - + if (strcmp (v [1], "defXghi") != 0) return FAILED ("Invalid value 6"); @@ -129,7 +129,7 @@ test_split (void) if (v [3] != NULL) return FAILED ("Expected only 3 elements (3)"); - + g_strfreev (v); v = g_strsplit ("abcXYXYXYdefXY", "XY", -1); @@ -141,7 +141,7 @@ test_split (void) if (strcmp (v [2], "") != 0) return FAILED ("Invalid value 10"); - + if (strcmp (v [3], "def") != 0) return FAILED ("Invalid value 11"); @@ -150,28 +150,28 @@ test_split (void) if (v [5] != NULL) return FAILED ("Expected only 5 elements (4)"); - + g_strfreev (v); v = g_strsplit ("XYXYXYabcXYdef", "XY", -1); if (strcmp (v [0], "") != 0) return FAILED ("Invalid value 13"); - + if (strcmp (v [1], "") != 0) return FAILED ("Invalid value 14"); - + if (strcmp (v [2], "") != 0) return FAILED ("Invalid value 15"); - + if (strcmp (v [3], "abc") != 0) return FAILED ("Invalid value 16"); - + if (strcmp (v [4], "def") != 0) return FAILED ("Invalid value 17"); if (v [5] != NULL) return FAILED ("Expected only 5 elements (5)"); - + g_strfreev (v); v = g_strsplit ("value=", "=", 2); @@ -191,14 +191,14 @@ static RESULT test_split_set (void) { gchar **v; - + v = g_strsplit_set ("abcXYdefXghiXYjklYmno", "XY", 6); if (strcmp (v [0], "abc") != 0) return FAILED ("Invalid value 0"); if (strcmp (v [1], "") != 0) return FAILED ("Invalid value 1"); - + if (strcmp (v [2], "def") != 0) return FAILED ("Invalid value 2"); @@ -222,19 +222,19 @@ test_split_set (void) if (strcmp (v [1], "") != 0) return FAILED ("Invalid value 7"); - + if (strcmp (v [2], "defXghiXYjklYmno") != 0) return FAILED ("Invalid value 8"); if (v [3] != NULL) return FAILED ("Expected only 3 elements (2)"); - + g_strfreev (v); v = g_strsplit_set ("abcXdefYghiXjklYmnoX", "XY", 5); if (strcmp (v [0], "abc") != 0) return FAILED ("Invalid value 9"); - + if (strcmp (v [1], "def") != 0) return FAILED ("Invalid value 10"); @@ -249,7 +249,7 @@ test_split_set (void) if (v [5] != NULL) return FAILED ("Expected only 5 elements (5)"); - + g_strfreev (v); v = g_strsplit_set ("abcXYXdefXY", "XY", -1); @@ -261,7 +261,7 @@ test_split_set (void) if (strcmp (v [2], "") != 0) return FAILED ("Invalid value 16"); - + if (strcmp (v [3], "def") != 0) return FAILED ("Invalid value 17"); @@ -273,31 +273,31 @@ test_split_set (void) if (v [6] != NULL) return FAILED ("Expected only 6 elements (4)"); - + g_strfreev (v); v = g_strsplit_set ("XYXabcXYdef", "XY", -1); if (strcmp (v [0], "") != 0) return FAILED ("Invalid value 20"); - + if (strcmp (v [1], "") != 0) return FAILED ("Invalid value 21"); - + if (strcmp (v [2], "") != 0) return FAILED ("Invalid value 22"); - + if (strcmp (v [3], "abc") != 0) return FAILED ("Invalid value 23"); if (strcmp (v [4], "") != 0) return FAILED ("Invalid value 24"); - + if (strcmp (v [5], "def") != 0) return FAILED ("Invalid value 25"); if (v [6] != NULL) return FAILED ("Expected only 6 elements (5)"); - + g_strfreev (v); return OK; @@ -343,7 +343,7 @@ static RESULT test_strjoin (void) { char *s; - + s = g_strjoin (NULL, "a", "b", (const char*)NULL); if (strcmp (s, "ab") != 0) return FAILED ("Join of two strings with no separator fails"); @@ -445,7 +445,7 @@ test_filename_to_uri (void) errit ("a"); errit ("./hola"); #endif - + return OK; } @@ -473,7 +473,7 @@ test_filename_from_uri (void) ferrit ("file:///%0"); ferrit ("file:///%jj"); #endif - + return OK; } @@ -590,7 +590,7 @@ test_strlcpy (void) if (0 != strcmp (dest, NUMBERS)) return FAILED ("problem [%s] and [%s]", dest, NUMBERS); g_free (dest); - + return OK; } @@ -622,7 +622,7 @@ test_ascii_strncasecmp (void) n = g_ascii_strncasecmp ("123", "123", 1); if (n != 0) return FAILED ("Should have been 0"); - + n = g_ascii_strncasecmp ("423", "123", 1); if (n <= 0) return FAILED ("Should have been > 0, got %d", n); diff --git a/src/mono/mono/eglib/test/string.c b/src/mono/mono/eglib/test/string.c index c2cc5f37317e2..8b2281b538530 100644 --- a/src/mono/mono/eglib/test/string.c +++ b/src/mono/mono/eglib/test/string.c @@ -10,16 +10,16 @@ test_append_speed (void) { GString *s = g_string_new(""); gint i; - + for(i = 0; i < 1024; i++) { g_string_append(s, "x"); } - + if(strlen (s->str) != 1024) { - return FAILED("Incorrect string size, got: %s %d", + return FAILED("Incorrect string size, got: %s %d", s->str, strlen(s->str)); } - + g_string_free (s, TRUE); return OK; @@ -30,16 +30,16 @@ test_append_c_speed (void) { GString *s = g_string_new(""); gint i; - + for(i = 0; i < 1024; i++) { g_string_append_c(s, 'x'); } - + if(strlen(s->str) != 1024) { - return FAILED("Incorrect string size, got: %s %d", s->str, + return FAILED("Incorrect string size, got: %s %d", s->str, strlen(s->str)); } - + g_string_free(s, TRUE); return OK; @@ -90,7 +90,7 @@ test_gstring (void) s = g_string_new ("Hola"); g_string_printf (s, "Dingus"); - + /* Test that it does not release it */ ret = g_string_free (s, FALSE); g_free (ret); @@ -104,7 +104,7 @@ test_gstring (void) sfail ( 0, 4); sfail ('2', 5); g_string_free (s, TRUE); - + return OK; } @@ -119,7 +119,7 @@ test_sized (void) return FAILED ("Expected an empty len"); g_string_free (s, TRUE); - + return NULL; } @@ -132,7 +132,7 @@ test_truncate (void) if (strlen (s->str) != 3) return FAILED ("size of string should have been 3, instead it is [%s]\n", s->str); g_string_free (s, TRUE); - + s = g_string_new ("a"); s = g_string_truncate (s, 10); if (strlen (s->str) != 1) @@ -143,7 +143,7 @@ test_truncate (void) g_string_truncate (s, 0); if (strlen (s->str) != 0) return FAILED ("The size is not 0"); - + g_string_free (s, TRUE); return NULL; @@ -163,7 +163,7 @@ test_appendlen (void) g_string_append_len (s, "ha", -1); if (s->len != 7) return FAILED ("The length is not seven %d", s->len); - + g_string_free (s, TRUE); return NULL; @@ -175,7 +175,7 @@ test_macros (void) char *s = g_strdup (G_STRLOC); char *p = strchr (s + 2, ':'); int n; - + if (p == NULL) return FAILED ("Did not find a separator"); n = atoi (p+1); @@ -185,7 +185,7 @@ test_macros (void) *p = 0; if (strcmp (s + strlen(s) - 8 , "string.c") != 0) return FAILED ("This did not store the filename on G_STRLOC"); - + g_free (s); return NULL; } diff --git a/src/mono/mono/eglib/test/test.c b/src/mono/mono/eglib/test/test.c index 426812df62c8c..d614e4e3e965b 100644 --- a/src/mono/mono/eglib/test/test.c +++ b/src/mono/mono/eglib/test/test.c @@ -48,16 +48,16 @@ extern gint global_passed, global_tests; static gchar *last_result = NULL; -static gboolean +static gboolean run_test(const Test *test, char **result_out) { - gchar *result; + gchar *result; if((result = test->handler()) == NULL) { *result_out = NULL; return TRUE; } else { - *result_out = result; + *result_out = result; return FALSE; } } @@ -88,7 +88,7 @@ run_group(const Group *group, gint iterations, gboolean quiet, for(i = 0; tests[i].name != NULL; i++) { gchar *result = (char*)""; gboolean iter_pass, run; - + iter_pass = FALSE; if(tests_to_run != NULL) { gint j; @@ -106,15 +106,15 @@ run_group(const Group *group, gint iterations, gboolean quiet, if(!run) { continue; } - + total++; - + if(!quiet) { printf(" %s: ", tests[i].name); } start_time_test = get_timestamp(); - + for(j = 0; j < iterations; j++) { iter_pass = run_test(&(tests[i]), &result); if(!iter_pass) { @@ -131,11 +131,11 @@ run_group(const Group *group, gint iterations, gboolean quiet, printf("OK\n"); } } - } else { + } else { if(!quiet) { printf("FAILED (%s)\n", result); } - + if(last_result == result) { last_result = NULL; g_free(result); @@ -198,12 +198,12 @@ get_timestamp (void) return res.tv_sec + (1.e-6) * res.tv_usec; } -/* +/* * Duplicating code here from EGlib to avoid g_strsplit skew between * EGLib and GLib */ - -gchar ** + +gchar ** eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) { gchar *string_c; @@ -215,12 +215,12 @@ eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) g_return_val_if_fail(string != NULL, NULL); g_return_val_if_fail(delimiter != NULL, NULL); g_return_val_if_fail(delimiter[0] != 0, NULL); - + token_length = strlen(string); string_c = (gchar *)g_malloc(token_length + 1); memcpy(string_c, string, token_length); string_c[token_length] = 0; - + vector = NULL; token = (gchar *)strtok_r(string_c, delimiter, &strtok_save); @@ -230,11 +230,11 @@ eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) memcpy(token_c, token, token_length); token_c[token_length] = 0; - vector = vector == NULL ? + vector = vector == NULL ? (gchar **)g_malloc(2 * sizeof(vector)) : (gchar **)g_realloc(vector, (size + 1) * sizeof(vector)); - - vector[size - 1] = token_c; + + vector[size - 1] = token_c; size++; if(max_tokens > 0 && size >= max_tokens) { @@ -251,7 +251,7 @@ eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) if(vector != NULL && size > 0) { vector[size - 1] = NULL; } - + g_free(string_c); string_c = NULL; diff --git a/src/mono/mono/eglib/test/test.h b/src/mono/mono/eglib/test/test.h index a2003211ee574..d807e6c0839ce 100644 --- a/src/mono/mono/eglib/test/test.h +++ b/src/mono/mono/eglib/test/test.h @@ -25,7 +25,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - + #ifndef _TEST_H #define _TEST_H @@ -36,8 +36,8 @@ #include #ifdef _MSC_VER -/* disable the following warnings - * C4100: The formal parameter is not referenced in the body of the function. The unreferenced parameter is ignored. +/* disable the following warnings + * C4100: The formal parameter is not referenced in the body of the function. The unreferenced parameter is ignored. * C4127: conditional expression is constant (test macros produce a lot of these) */ #pragma warning(disable:4100 4127) diff --git a/src/mono/mono/eglib/test/tests.h b/src/mono/mono/eglib/test/tests.h index 885d87a7caf4f..445552c9dc43b 100644 --- a/src/mono/mono/eglib/test/tests.h +++ b/src/mono/mono/eglib/test/tests.h @@ -26,8 +26,8 @@ DEFINE_TEST_GROUP_INIT_H(memory_tests_init); DEFINE_TEST_GROUP_INIT_H(enum_tests_init); const -static Group test_groups [] = { - {"string", string_tests_init}, +static Group test_groups [] = { + {"string", string_tests_init}, {"strutil", strutil_tests_init}, {"ptrarray", ptrarray_tests_init}, {"slist", slist_tests_init}, @@ -40,7 +40,7 @@ static Group test_groups [] = { {"path", path_tests_init}, {"shell", shell_tests_init}, {"markup", markup_tests_init}, -#if !DISABLE_PROCESS_TESTS +#if !DISABLE_PROCESS_TESTS {"spawn", spawn_tests_init}, {"module", module_tests_init}, #endif diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index c78ab44b56dfd..b50c78617ea8b 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -5245,7 +5245,7 @@ mono_profiler_class_loading ( uint64_t class_id; uint64_t module_id; - + mono_profiler_get_class_data (klass, &class_id, &module_id, NULL, NULL, NULL); mono_profiler_fire_event_enter (); @@ -5428,7 +5428,7 @@ mono_profiler_module_loading ( { if (!EventEnabledMonoProfilerModuleLoading ()) return; - + mono_profiler_fire_event_enter (); FireEtwMonoProfilerModuleLoading ( @@ -5466,7 +5466,7 @@ mono_profiler_module_loaded ( { if (!EventEnabledMonoProfilerModuleLoaded ()) return; - + uint64_t module_id = (uint64_t)image; const ep_char8_t *module_path = NULL; const ep_char8_t *module_guid = NULL; @@ -5517,7 +5517,7 @@ mono_profiler_module_unloaded ( { if (!EventEnabledMonoProfilerModuleUnloaded ()) return; - + uint64_t module_id = (uint64_t)image; const ep_char8_t *module_path = NULL; const ep_char8_t *module_guid = NULL; @@ -5570,7 +5570,7 @@ mono_profiler_assembly_loading ( { if (!EventEnabledMonoProfilerAssemblyLoading ()) return; - + uint64_t assembly_id; uint64_t module_id; @@ -5624,7 +5624,7 @@ mono_profiler_assembly_unloading ( { if (!EventEnabledMonoProfilerAssemblyUnloading ()) return; - + uint64_t assembly_id; uint64_t module_id; @@ -6039,7 +6039,7 @@ mono_profiler_gc_allocation ( if (object) { vtable_id = (uint64_t)mono_object_get_vtable_internal (object); object_size = (uint64_t)mono_object_get_size_internal (object); - + /* account for object alignment */ object_size += 7; object_size &= ~7; diff --git a/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c b/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c index 6df68f607785d..9a00736612a56 100644 --- a/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c +++ b/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c @@ -80,7 +80,7 @@ test_fast_serializer_object_fast_serialize (void) ep_raise_error_if_nok (provider != NULL); test_location = 3; - + ep_event = ep_event_alloc (provider, 1, 1, 1, EP_EVENT_LEVEL_VERBOSE, false, NULL, 0); ep_raise_error_if_nok (ep_event != NULL); diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index eed7c2012e126..a717c205f7910 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -195,7 +195,7 @@ create_domain_objects (MonoDomain *domain) domain->out_of_memory_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL_HANDLE_STRING, error)); mono_error_assert_ok (error); - /* + /* * These two are needed because the signal handlers might be executing on * an alternate stack, and Boehm GC can't handle that. */ @@ -212,7 +212,7 @@ create_domain_objects (MonoDomain *domain) domain->ephemeron_tombstone = MONO_HANDLE_RAW (mono_object_new_handle (mono_defaults.object_class, error)); mono_error_assert_ok (error); - /* + /* * This class is used during exception handling, so initialize it here, to prevent * stack overflows while handling stack overflows. */ @@ -225,7 +225,7 @@ create_domain_objects (MonoDomain *domain) * \param domain domain returned by \c mono_init * * Initialize the core AppDomain: this function will run also some - * IL initialization code, so it needs the execution engine to be fully + * IL initialization code, so it needs the execution engine to be fully * operational. * * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where @@ -377,7 +377,7 @@ mono_runtime_quit (void) (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy); // after quit_function (in particular, mini_cleanup) everything is // cleaned up so MONO_EXIT_GC_UNSAFE can't work and doesn't make sense. - + mono_runtime_quit_internal (); } @@ -390,7 +390,7 @@ mono_runtime_quit_internal (void) MONO_REQ_GC_UNSAFE_MODE; // but note that when we return, we're not in GC Unsafe mode anymore. // After clean up threads don't _have_ a thread state anymore. - + if (quit_function != NULL) quit_function (mono_get_root_domain (), NULL); } @@ -613,12 +613,12 @@ try_load_from (MonoAssembly **assembly, { gchar *fullpath; gboolean found = FALSE; - + *assembly = NULL; fullpath = g_build_filename (path1, path2, path3, path4, (const char*)NULL); found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR); - + if (found) { *assembly = mono_assembly_request_open (fullpath, req, NULL); } @@ -698,7 +698,7 @@ get_app_context_base_directory (MonoError *error) } /* - * Try loading the assembly from ApplicationBase and PrivateBinPath + * Try loading the assembly from ApplicationBase and PrivateBinPath * and then from assemblies_path if any. * LOCKING: This is called from the assembly loading code, which means the caller * might hold the loader lock. Thus, this function must not acquire the domain lock. @@ -778,7 +778,7 @@ ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle, alc = mono_assembly_get_alc (requesting_assembly); if (!alc) g_assert_not_reached (); - + g_assert (alc); mono_assembly_request_prepare_byname (&req, alc); req.basedir = NULL; @@ -948,7 +948,7 @@ runtimeconfig_json_get_buffer (MonovmRuntimeConfigArguments *arg, MonoFileMap ** *file_map = NULL; *buf_handle = NULL; - return NULL; + return NULL; } static void diff --git a/src/mono/mono/metadata/assembly-load-context.c b/src/mono/mono/metadata/assembly-load-context.c index 627086e3f5dfd..f3ce63deb4314 100644 --- a/src/mono/mono/metadata/assembly-load-context.c +++ b/src/mono/mono/metadata/assembly-load-context.c @@ -95,7 +95,7 @@ mono_alc_create_individual (MonoGCHandle this_gchandle, gboolean collectible, Mo static void mono_alc_cleanup_assemblies (MonoAssemblyLoadContext *alc) { - // The minimum refcount on assemblies is 2: one for the domain and one for the ALC. + // The minimum refcount on assemblies is 2: one for the domain and one for the ALC. // The domain refcount might be less than optimal on netcore, but its removal is too likely to cause issues for now. GSList *tmp; @@ -425,7 +425,7 @@ mono_alc_from_gchandle (MonoGCHandle alc_gchandle) return default_alc; MONO_STATIC_POINTER_INIT (MonoClassField, resolve) - + MonoClass *alc_class = mono_class_get_assembly_load_context_class (); g_assert (alc_class); resolve = mono_class_get_field_from_name_full (alc_class, "_nativeAssemblyLoadContext", NULL); @@ -436,7 +436,7 @@ mono_alc_from_gchandle (MonoGCHandle alc_gchandle) MonoAssemblyLoadContext *alc = NULL; mono_field_get_value_internal (mono_gchandle_get_target_internal (alc_gchandle), resolve, &alc); - return alc; + return alc; } MonoGCHandle diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index e8c4bbee3c0a4..493c3ff47d3c5 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -2544,7 +2544,7 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole gchar *key_uq; gchar *retargetable = NULL; gchar *retargetable_uq; - gchar *procarch; + gchar *procarch = NULL; gchar *procarch_uq; gboolean res; gchar *value, *part_name; @@ -2590,43 +2590,47 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Version", part_name_len)) { *is_version_defined = TRUE; - version = value; - if (strlen (version) == 0) { + if (version != NULL || strlen (value) == 0) { goto cleanup_and_fail; } + version = value; tmp++; continue; } if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Culture", part_name_len)) { - culture = value; - if (strlen (culture) == 0) { + if (culture != NULL || strlen (value) == 0) { goto cleanup_and_fail; } + culture = value; tmp++; continue; } if (part_name_len == 14 && !g_ascii_strncasecmp (part_name, "PublicKeyToken", part_name_len)) { *is_token_defined = TRUE; - token = value; - if (strlen (token) == 0) { + if (token != NULL || key != NULL || strlen (value) == 0) { goto cleanup_and_fail; } + token = value; tmp++; continue; } if (part_name_len == 9 && !g_ascii_strncasecmp (part_name, "PublicKey", part_name_len)) { - key = value; - if (strlen (key) == 0) { + if (token != NULL || key != NULL || strlen (value) == 0) { goto cleanup_and_fail; } + key = value; tmp++; continue; } if (part_name_len == 12 && !g_ascii_strncasecmp (part_name, "Retargetable", part_name_len)) { + if (retargetable != NULL) { + goto cleanup_and_fail; + } + retargetable = value; retargetable_uq = unquote (retargetable); if (retargetable_uq != NULL) @@ -2645,6 +2649,10 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole } if (part_name_len == 21 && !g_ascii_strncasecmp (part_name, "ProcessorArchitecture", part_name_len)) { + if (procarch != NULL) { + goto cleanup_and_fail; + } + procarch = value; procarch_uq = unquote (procarch); if (procarch_uq != NULL) @@ -2672,7 +2680,8 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole continue; } - goto cleanup_and_fail; + // compat: If we got here, the attribute name is unknown to us. Ignore it. + tmp++; } /* if retargetable flag is set, then we must have a fully qualified name */ diff --git a/src/mono/mono/metadata/assembly.h b/src/mono/mono/metadata/assembly.h index bffe668a05333..9f55a3db8114c 100644 --- a/src/mono/mono/metadata/assembly.h +++ b/src/mono/mono/metadata/assembly.h @@ -2,7 +2,7 @@ * \file */ -#ifndef _MONONET_METADATA_ASSEMBLY_H_ +#ifndef _MONONET_METADATA_ASSEMBLY_H_ #define _MONONET_METADATA_ASSEMBLY_H_ #include @@ -21,12 +21,12 @@ MonoAssembly *mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, mono_bool refonly); MONO_API MONO_RT_EXTERNAL_ONLY -MonoAssembly* mono_assembly_load (MonoAssemblyName *aname, - const char *basedir, +MonoAssembly* mono_assembly_load (MonoAssemblyName *aname, + const char *basedir, MonoImageOpenStatus *status); MONO_API MONO_RT_EXTERNAL_ONLY MonoAssembly* mono_assembly_load_full (MonoAssemblyName *aname, - const char *basedir, + const char *basedir, MonoImageOpenStatus *status, mono_bool refonly); MONO_API MONO_RT_EXTERNAL_ONLY @@ -68,8 +68,8 @@ typedef void (*MonoAssemblyLoadFunc) (MonoAssembly *assembly, void* use MONO_API MONO_RT_EXTERNAL_ONLY void mono_install_assembly_load_hook (MonoAssemblyLoadFunc func, void* user_data); -/* - * Installs a new function which is used to search the list of loaded +/* + * Installs a new function which is used to search the list of loaded * assemblies for a given assembly name. */ typedef MonoAssembly *(*MonoAssemblySearchFunc) (MonoAssemblyName *aname, void* user_data); @@ -82,7 +82,7 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoAssembly* mono_assembly_invoke_search_hook (MonoAssemblyName *aname); /* - * Installs a new search function which is used as a last resort when loading + * Installs a new search function which is used as a last resort when loading * an assembly fails. This could invoke AssemblyResolve events. */ MONO_API MONO_RT_EXTERNAL_ONLY diff --git a/src/mono/mono/metadata/attrdefs.h b/src/mono/mono/metadata/attrdefs.h index 504c6c65fc6d2..a3a47493e2a5a 100644 --- a/src/mono/mono/metadata/attrdefs.h +++ b/src/mono/mono/metadata/attrdefs.h @@ -12,12 +12,12 @@ * * From the ECMA documentation */ - + #ifndef _MONO_METADATA_ATTRDEFS_H_ #define _MONO_METADATA_ATTRDEFS_H_ /* - * 23.1.1 Values for AssemblyHashAlgorithm + * 23.1.1 Values for AssemblyHashAlgorithm */ enum { MONO_ASSEMBLY_HASH_NONE, @@ -186,7 +186,7 @@ enum { MONO_METHOD_IMPL_ATTR_INTERNAL_CALL = 0x1000, MONO_METHOD_IMPL_ATTR_SYNCHRONIZED = 0x0020, MONO_METHOD_IMPL_ATTR_NOINLINING = 0x0008, - MONO_METHOD_IMPL_ATTR_NOOPTIMIZATION = 0x0040, + MONO_METHOD_IMPL_ATTR_NOOPTIMIZATION = 0x0040, MONO_METHOD_IMPL_ATTR_MAX_METHOD_IMPL_VAL = 0xffff }; diff --git a/src/mono/mono/metadata/boehm-gc.c b/src/mono/mono/metadata/boehm-gc.c index bdda3e69b8b02..34c85e2a84ec0 100644 --- a/src/mono/mono/metadata/boehm-gc.c +++ b/src/mono/mono/metadata/boehm-gc.c @@ -89,7 +89,7 @@ typedef struct { #define EMPTY_HANDLE_DATA(type) {NULL, NULL, 0, (type), 0, NULL} -/* weak and weak-track arrays will be allocated in malloc memory +/* weak and weak-track arrays will be allocated in malloc memory */ static HandleData gc_handles [] = { EMPTY_HANDLE_DATA (HANDLE_WEAK), @@ -254,7 +254,7 @@ mono_gc_max_generation (void) } guint64 -mono_gc_get_allocated_bytes_for_current_thread (void) +mono_gc_get_allocated_bytes_for_current_thread (void) { return 0; } @@ -1226,10 +1226,10 @@ void mono_gc_set_string_length (MonoString *str, gint32 new_length) { mono_unichar2 *new_end = str->chars + new_length; - - /* zero the discarded string. This null-delimits the string and allows + + /* zero the discarded string. This null-delimits the string and allows * the space to be reclaimed by SGen. */ - + memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2)); str->length = new_length; } @@ -1468,12 +1468,12 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) * This returns a handle that wraps the object, this is used to keep a * reference to a managed object from the unmanaged world and preventing the * object from being disposed. - * + * * If \p pinned is false the address of the object can not be obtained, if it is * true the address of the object can be obtained. This will also pin the * object so it will not be possible by a moving garbage collector to move the - * object. - * + * object. + * * \returns a handle that can be used to access the object from * unmanaged code. */ @@ -1493,14 +1493,14 @@ mono_gchandle_new_internal (MonoObject *obj, gboolean pinned) * Unlike the \c mono_gchandle_new_internal the object can be reclaimed by the * garbage collector. In this case the value of the GCHandle will be * set to zero. - * + * * If \p track_resurrection is TRUE the object will be tracked through * finalization and if the object is resurrected during the execution * of the finalizer, then the returned weakref will continue to hold * a reference to the object. If \p track_resurrection is FALSE, then * the weak reference's target will become NULL as soon as the object * is passed on to the finalizer. - * + * * \returns a handle that can be used to access the object from * unmanaged code. */ @@ -1589,7 +1589,7 @@ mono_gc_is_null (void) * * Frees the \p gchandle handle. If there are no outstanding * references, the garbage collector can reclaim the memory of the - * object wrapped. + * object wrapped. */ void mono_gchandle_free_internal (MonoGCHandle gch) @@ -1625,7 +1625,7 @@ mono_gchandle_free_internal (MonoGCHandle gch) } guint64 -mono_gc_get_total_allocated_bytes (MonoBoolean precise) +mono_gc_get_total_allocated_bytes (MonoBoolean precise) { return 0; } diff --git a/src/mono/mono/metadata/cil-coff.h b/src/mono/mono/metadata/cil-coff.h index d6e966ee83c70..8751f8daa5614 100644 --- a/src/mono/mono/metadata/cil-coff.h +++ b/src/mono/mono/metadata/cil-coff.h @@ -186,7 +186,7 @@ typedef struct { #define MONO_PE_RES_DIR_ENTRY_DIR_OFFSET(d) (GUINT32_FROM_LE((d).dir) & 0x7fffffff) #define MONO_PE_RES_DIR_ENTRY_SET_DIR(d,i,o) ((d).dir = GUINT32_TO_LE(((guint32)((i)?1:0) << 31) | ((o) & 0x7fffffff))) -typedef struct +typedef struct { guint32 res_characteristics; guint32 res_date_stamp; diff --git a/src/mono/mono/metadata/class-accessors.c b/src/mono/mono/metadata/class-accessors.c index 76065cb45c456..457292de55074 100644 --- a/src/mono/mono/metadata/class-accessors.c +++ b/src/mono/mono/metadata/class-accessors.c @@ -26,9 +26,10 @@ typedef enum { PROP_DECLSEC_FLAGS = 8, /* guint32 */ PROP_WEAK_BITMAP = 9, PROP_DIM_CONFLICTS = 10, /* GSList of MonoMethod* */ - PROP_FIELD_DEF_VALUES_2BYTESWIZZLE = 11, /* MonoFieldDefaultValue* with default values swizzled at 2 byte boundaries*/ - PROP_FIELD_DEF_VALUES_4BYTESWIZZLE = 12, /* MonoFieldDefaultValue* with default values swizzled at 4 byte boundaries*/ - PROP_FIELD_DEF_VALUES_8BYTESWIZZLE = 13 /* MonoFieldDefaultValue* with default values swizzled at 8 byte boundaries*/ + PROP_FIELD_DEF_VALUES_2BYTESWIZZLE = 11, /* MonoFieldDefaultValue* with default values swizzled at 2 byte boundaries*/ + PROP_FIELD_DEF_VALUES_4BYTESWIZZLE = 12, /* MonoFieldDefaultValue* with default values swizzled at 4 byte boundaries*/ + PROP_FIELD_DEF_VALUES_8BYTESWIZZLE = 13, /* MonoFieldDefaultValue* with default values swizzled at 8 byte boundaries*/ + PROP_METADATA_UPDATE_INFO = 14, /* MonoClassMetadataUpdateInfo* */ } InfrequentDataKind; /* Accessors based on class kind*/ @@ -67,7 +68,9 @@ mono_class_try_get_generic_class (MonoClass *klass) guint32 mono_class_get_flags (MonoClass *klass) { - switch (m_class_get_class_kind (klass)) { + g_assert (klass); + guint32 kind = m_class_get_class_kind (klass); + switch (kind) { case MONO_CLASS_DEF: case MONO_CLASS_GTD: return m_classdef_get_flags ((MonoClassDef*)klass); @@ -393,7 +396,7 @@ mono_class_get_field_def_values_with_swizzle (MonoClass *klass, int swizzle) dataKind = PROP_FIELD_DEF_VALUES_2BYTESWIZZLE; else if (swizzle == 4) dataKind = PROP_FIELD_DEF_VALUES_4BYTESWIZZLE; - else + else if (swizzle == 8) dataKind = PROP_FIELD_DEF_VALUES_8BYTESWIZZLE; return (MonoFieldDefaultValue*)get_pointer_property (klass, dataKind); } @@ -413,7 +416,7 @@ mono_class_set_field_def_values_with_swizzle (MonoClass *klass, MonoFieldDefault dataKind = PROP_FIELD_DEF_VALUES_2BYTESWIZZLE; else if (swizzle == 4) dataKind = PROP_FIELD_DEF_VALUES_4BYTESWIZZLE; - else + else if (swizzle == 8) dataKind = PROP_FIELD_DEF_VALUES_8BYTESWIZZLE; set_pointer_property (klass, dataKind, values); } @@ -589,6 +592,67 @@ mono_class_publish_gc_descriptor (MonoClass *klass, MonoGCDescriptor gc_descr) return ret; } +MonoClassMetadataUpdateInfo* +mono_class_get_metadata_update_info (MonoClass *klass) +{ + switch (m_class_get_class_kind (klass)) { + case MONO_CLASS_GTD: + return NULL; + case MONO_CLASS_DEF: + return (MonoClassMetadataUpdateInfo *)get_pointer_property (klass, PROP_METADATA_UPDATE_INFO); + case MONO_CLASS_GINST: + case MONO_CLASS_GPARAM: + case MONO_CLASS_POINTER: + case MONO_CLASS_GC_FILLER: + return NULL; + default: + g_assert_not_reached (); + } +} + +/* + * LOCKING: assumes the loader lock is held + */ +void +mono_class_set_metadata_update_info (MonoClass *klass, MonoClassMetadataUpdateInfo *value) +{ + switch (m_class_get_class_kind (klass)) { + case MONO_CLASS_GTD: + g_assertf (0, "%s: EnC metadata update info on generic types is not supported", __func__); + break; + case MONO_CLASS_DEF: + set_pointer_property (klass, PROP_METADATA_UPDATE_INFO, value); + return; + case MONO_CLASS_GINST: + case MONO_CLASS_GPARAM: + case MONO_CLASS_POINTER: + case MONO_CLASS_GC_FILLER: + g_assert_not_reached (); + break; + default: + g_assert_not_reached (); + } +} + +gboolean +mono_class_has_metadata_update_info (MonoClass *klass) +{ + switch (m_class_get_class_kind (klass)) { + case MONO_CLASS_GTD: + return FALSE; + case MONO_CLASS_DEF: + return get_pointer_property (klass, PROP_METADATA_UPDATE_INFO) != NULL; + case MONO_CLASS_GINST: + case MONO_CLASS_GPARAM: + case MONO_CLASS_POINTER: + case MONO_CLASS_GC_FILLER: + return FALSE; + default: + g_assert_not_reached (); + } +} + + #ifdef MONO_CLASS_DEF_PRIVATE #define MONO_CLASS_GETTER(funcname, rettype, optref, argtype, fieldname) rettype funcname (argtype *klass) { return optref klass-> fieldname ; } #define MONO_CLASS_OFFSET(funcname, argtype, fieldname) intptr_t funcname (void) { return MONO_STRUCT_OFFSET (argtype, fieldname); } diff --git a/src/mono/mono/metadata/class-getters.h b/src/mono/mono/metadata/class-getters.h index 0dc97fca5807d..98363a33952aa 100644 --- a/src/mono/mono/metadata/class-getters.h +++ b/src/mono/mono/metadata/class-getters.h @@ -1,4 +1,4 @@ -/* +/* * \file Definitions of getters for the fields of struct _MonoClass * * Copyright 2018 Microsoft @@ -8,7 +8,7 @@ /* No include guards - this file is meant to be included multiple times. * Before including the file define the following macros: * MONO_CLASS_GETTER(funcname, rettype, optref, argtype, fieldname) - * + * * MONO_CLASS_OFFSET(funcname, argtype, fieldname) */ @@ -24,6 +24,7 @@ MONO_CLASS_GETTER(m_class_is_size_inited, gboolean, , MonoClass, size_inited) MONO_CLASS_GETTER(m_class_is_valuetype, gboolean, , MonoClass, valuetype) MONO_CLASS_GETTER(m_class_is_enumtype, gboolean, , MonoClass, enumtype) MONO_CLASS_GETTER(m_class_is_blittable, gboolean, , MonoClass, blittable) +MONO_CLASS_GETTER(m_class_any_field_has_auto_layout, gboolean, , MonoClass, any_field_has_auto_layout) MONO_CLASS_GETTER(m_class_is_unicode, gboolean, , MonoClass, unicode) MONO_CLASS_GETTER(m_class_was_typebuilder, gboolean, , MonoClass, wastypebuilder) MONO_CLASS_GETTER(m_class_is_array_special_interface, gboolean, , MonoClass, is_array_special_interface) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 6164476ba9a91..00ab30ffbd76f 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -96,7 +96,7 @@ To load TextBoxBase<> to do so it must resolve the parent which is TextInput it must resolve TextInput<> and TextBox. To load TextBox it must resolve the parent which is TextBoxBase. -At this point the runtime must instantiate TextBoxBase. Both types are partially loaded +At this point the runtime must instantiate TextBoxBase. Both types are partially loaded at this point, iow, both are registered in the type map and both and a NULL parent. This means that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage. @@ -108,7 +108,7 @@ static int record_gclass_instantiation; static GSList *gclass_recorded_list; typedef gboolean (*gclass_record_func) (MonoClass*, void*); -/* +/* * LOCKING: loader lock must be held until pairing disable_gclass_recording is called. */ static void @@ -117,7 +117,7 @@ enable_gclass_recording (void) ++record_gclass_instantiation; } -/* +/* * LOCKING: loader lock must be held since pairing enable_gclass_recording was called. */ static void @@ -364,6 +364,14 @@ mono_class_setup_fields (MonoClass *klass) g_free (type_name); break; } + if (m_type_is_byref (field->type)) { + if (!m_class_is_byreflike (klass)) { + char *class_name = mono_type_get_full_name (klass); + mono_class_set_type_load_failure (klass, "Type %s is not a ByRefLike type so ref field, '%s', is invalid", class_name, field->name); + g_free (class_name); + break; + } + } /* The def_value of fields is compute lazily during vtable creation */ } @@ -426,7 +434,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError guint tidx = mono_metadata_token_index (type_token); MonoGenericContext *context = NULL; const char *name, *nspace; - guint icount = 0; + guint icount = 0; MonoClass **interfaces; guint32 field_last, method_last; guint32 nesting_tokeen; @@ -434,7 +442,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError error_init (error); /* FIXME: metadata-update - this function needs extensive work */ - if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > table_info_get_rows (tt)) { + if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || mono_metadata_table_bounds_check (image, MONO_TABLE_TYPEDEF, tidx)) { mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token); return NULL; } @@ -447,7 +455,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE); - + name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]); nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); @@ -528,7 +536,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (mono_class_is_gtd (klass)) disable_gclass_recording (fix_gclass_incomplete_instantiation, klass); - /* + /* * This might access klass->_byval_arg for recursion generated by generic constraints, * so it has to come after setup_mono_type (). */ @@ -614,27 +622,33 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError /* * Compute the field and method lists */ - int first_field_idx; - first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1; - mono_class_set_first_field_idx (klass, first_field_idx); - int first_method_idx; - first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1; - mono_class_set_first_method_idx (klass, first_method_idx); - - if (table_info_get_rows (tt) > tidx){ - mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE); - field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1; - method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1; - } else { - field_last = table_info_get_rows (&image->tables [MONO_TABLE_FIELD]); - method_last = table_info_get_rows (&image->tables [MONO_TABLE_METHOD]); - } + /* + * EnC metadata-update: new classes are added with method and field indices set to 0, new + * methods are added using the EnCLog AddMethod or AddField functions that will be added to + * MonoClassMetadataUpdateInfo + */ + if (G_LIKELY (cols [MONO_TYPEDEF_FIELD_LIST] != 0 || cols [MONO_TYPEDEF_METHOD_LIST] != 0)) { + int first_field_idx; + first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1; + mono_class_set_first_field_idx (klass, first_field_idx); + int first_method_idx; + first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1; + mono_class_set_first_method_idx (klass, first_method_idx); + if (table_info_get_rows (tt) > tidx) { + mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE); + field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1; + method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1; + } else { + field_last = table_info_get_rows (&image->tables [MONO_TABLE_FIELD]); + method_last = table_info_get_rows (&image->tables [MONO_TABLE_METHOD]); + } - if (cols [MONO_TYPEDEF_FIELD_LIST] && - cols [MONO_TYPEDEF_FIELD_LIST] <= table_info_get_rows (&image->tables [MONO_TABLE_FIELD])) - mono_class_set_field_count (klass, field_last - first_field_idx); - if (cols [MONO_TYPEDEF_METHOD_LIST] <= table_info_get_rows (&image->tables [MONO_TABLE_METHOD])) - mono_class_set_method_count (klass, method_last - first_method_idx); + if (cols [MONO_TYPEDEF_FIELD_LIST] && + cols [MONO_TYPEDEF_FIELD_LIST] <= table_info_get_rows (&image->tables [MONO_TABLE_FIELD])) + mono_class_set_field_count (klass, field_last - first_field_idx); + if (cols [MONO_TYPEDEF_METHOD_LIST] <= table_info_get_rows (&image->tables [MONO_TABLE_METHOD])) + mono_class_set_method_count (klass, method_last - first_method_idx); + } /* reserve space to store vector pointer in arrays */ if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) { @@ -680,8 +694,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError // compute is_byreflike if (m_class_is_valuetype (klass)) if (class_has_isbyreflike_attribute (klass)) - klass->is_byreflike = 1; - + klass->is_byreflike = 1; + mono_loader_unlock (); MONO_PROFILER_RAISE (class_loaded, (klass)); @@ -835,7 +849,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) klass->name = gklass->name; klass->name_space = gklass->name_space; - + klass->image = gklass->image; klass->type_token = gklass->type_token; @@ -883,7 +897,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) if (klass->enumtype) { /* - * For enums, gklass->fields might not been set, but instance_size etc. is + * For enums, gklass->fields might not been set, but instance_size etc. is * already set in mono_reflection_create_internal_class (). For non-enums, * these will be computed normally in mono_class_layout_fields (). */ @@ -930,7 +944,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) ++class_ginst_count; inflated_classes_size += sizeof (MonoClassGenericInst); - + mono_loader_unlock (); return klass; @@ -988,10 +1002,10 @@ class_kind_may_contain_generic_instances (MonoTypeKind kind) /** * mono_class_create_bounded_array: - * \param element_class element class + * \param element_class element class * \param rank the dimension of the array class * \param bounded whenever the array has non-zero bounds - * \returns A class object describing the array with element type \p element_type and + * \returns A class object describing the array with element type \p element_type and * dimension \p rank. */ MonoClass * @@ -1237,9 +1251,9 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound /** * mono_class_create_array: - * \param element_class element class + * \param element_class element class * \param rank the dimension of the array class - * \returns A class object describing the array with element type \p element_type and + * \returns A class object describing the array with element type \p element_type and * dimension \p rank. */ MonoClass * @@ -1434,7 +1448,7 @@ mono_class_create_ptr (MonoType *type) } mono_image_unlock (image); } - + result = mm ? (MonoClass *)mono_mem_manager_alloc0 (mm, sizeof (MonoClassPointer)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer)); UnlockedAdd (&classes_size, sizeof (MonoClassPointer)); @@ -1559,7 +1573,7 @@ mono_class_create_fnptr (MonoMethodSignature *sig) } -static gboolean +static gboolean method_is_reabstracted (guint16 flags) { if ((flags & METHOD_ATTRIBUTE_ABSTRACT && flags & METHOD_ATTRIBUTE_FINAL)) @@ -1874,7 +1888,7 @@ mono_class_is_gparam_with_nonblittable_parent (MonoClass *klass) * \param field_offsets Offsets of the klass' fields relative to the start of layout_check * \param field_count Count of klass fields * \param invalid_field_offset When the layout is invalid it will be set to the offset of the field which is invalid - * + * * \return True if the layout of the struct is valid, otherwise false. */ static gboolean @@ -1968,6 +1982,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ gboolean has_static_refs = FALSE; MonoClassField *field; gboolean blittable; + gboolean any_field_has_auto_layout; int instance_size = base_instance_size; int element_size = -1; int class_size, min_align; @@ -2002,6 +2017,12 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ min_align = 16; */ + /* Respect the specified packing size at least to the extent necessary to align double variables. + * This should avoid any GC problems, and will allow packing_size to be respected to support + * CreateSpan + */ + min_align = MIN (MONO_ABI_ALIGNOF (double), MAX (min_align, packing_size)); + /* * When we do generic sharing we need to have layout * information for open generic classes (either with a generic @@ -2026,7 +2047,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ /* * Enable GC aware auto layout: in this mode, reference - * fields are grouped together inside objects, increasing collector + * fields are grouped together inside objects, increasing collector * performance. * Requires that all classes whose layout is known to native code be annotated * with [StructLayout (LayoutKind.Sequential)] @@ -2039,12 +2060,17 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ gc_aware_layout = TRUE; } - /* Compute klass->blittable */ + /* Compute klass->blittable and klass->any_field_has_auto_layout */ blittable = TRUE; - if (klass->parent) + any_field_has_auto_layout = FALSE; + if (klass->parent) { blittable = klass->parent->blittable; - if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top) + any_field_has_auto_layout = klass->parent->any_field_has_auto_layout; + } + if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top) { blittable = FALSE; + any_field_has_auto_layout = TRUE; // If a type is auto-layout, treat it as having an auto-layout field in its layout. + } for (i = 0; i < top; i++) { field = &klass->fields [i]; @@ -2074,8 +2100,12 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ blittable = FALSE; } } - if (klass->enumtype) - blittable = klass->element_class->blittable; + if (!any_field_has_auto_layout && field->type->type == MONO_TYPE_VALUETYPE && m_class_any_field_has_auto_layout (mono_class_from_mono_type_internal (field->type))) + any_field_has_auto_layout = TRUE; + } + if (klass->enumtype) { + blittable = klass->element_class->blittable; + any_field_has_auto_layout = klass->element_class->any_field_has_auto_layout; } if (mono_class_has_failure (klass)) return; @@ -2083,7 +2113,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ blittable = FALSE; /* Compute klass->has_references */ - /* + /* * Process non-static fields first, since static fields might recursively * refer to the class itself. */ @@ -2159,7 +2189,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ } size = mono_type_size (field->type, &align); - + /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */ align = packing_size ? MIN (packing_size, align): align; /* if the field has managed references, we need to force-align it @@ -2180,7 +2210,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ } instance_size = MAX (real_size, instance_size); - + if (instance_size & (min_align - 1)) { instance_size += min_align - 1; instance_size &= ~(min_align - 1); @@ -2260,7 +2290,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ * enable it when a MONO_DEBUG property is set. * * For small structs, set min_align to at least the struct size to improve - * performance, and since the JIT memset/memcpy code assumes this and generates + * performance, and since the JIT memset/memcpy code assumes this and generates * unaligned accesses otherwise. See #78990 for a testcase. */ if (mono_align_small_structs && top) { @@ -2302,6 +2332,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ klass->has_references = has_references; klass->packing_size = packing_size; klass->min_align = min_align; + klass->any_field_has_auto_layout = any_field_has_auto_layout; for (i = 0; i < top; ++i) { field = &klass->fields [i]; if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) @@ -2326,7 +2357,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ guint32 size; field = &klass->fields [i]; - + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL) continue; if (mono_field_is_deleted (field)) @@ -2613,7 +2644,7 @@ generic_array_methods (MonoClass *klass) if (!iface || !check_method_exists (iface, mname)) continue; - + generic_array_method_info [i].array_method = m; name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1); @@ -2719,7 +2750,7 @@ static guint32 mono_get_unique_iid (MonoClass *klass) { int iid; - + g_assert (MONO_CLASS_IS_INTERFACE_INTERNAL (klass)); classes_lock (); @@ -2780,8 +2811,8 @@ mono_get_unique_iid (MonoClass *klass) * mono_class_init_internal: * \param klass the class to initialize * - * Compute the \c instance_size, \c class_size and other infos that cannot be - * computed at \c mono_class_get time. Also compute vtable_size if possible. + * Compute the \c instance_size, \c class_size and other infos that cannot be + * computed at \c mono_class_get time. Also compute vtable_size if possible. * Initializes the following fields in \p klass: * - all the fields initialized by \c mono_class_init_sizes * - has_cctor @@ -2803,7 +2834,7 @@ mono_class_init_internal (MonoClass *klass) gboolean ghcimpl = FALSE; gboolean has_cctor = FALSE; int first_iface_slot = 0; - + g_assert (klass); /* Double-checking locking pattern */ @@ -2834,7 +2865,7 @@ mono_class_init_internal (MonoClass *klass) MonoClass *element_class = klass->element_class; MonoClass *cast_class = klass->cast_class; - if (!element_class->inited) + if (!element_class->inited) mono_class_init_internal (element_class); if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class")) goto leave; @@ -2871,7 +2902,7 @@ mono_class_init_internal (MonoClass *klass) initialize_object_slots (klass); - /* + /* * Initialize the rest of the data without creating a generic vtable if possible. * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can * also avoid computing a generic vtable. @@ -2942,7 +2973,7 @@ mono_class_init_internal (MonoClass *klass) int mcount = mono_class_get_method_count (klass); for (i = 0; i < mcount; ++i) { MonoMethod *method = klass->methods [i]; - if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && + if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && (strcmp (".cctor", method->name) == 0)) { has_cctor = 1; break; @@ -3042,7 +3073,7 @@ mono_class_init_checked (MonoClass *klass, MonoError *error) /* * COM initialization is delayed until needed. * However when a [ComImport] attribute is present on a type it will trigger - * the initialization. This is not a problem unless the BCL being executed + * the initialization. This is not a problem unless the BCL being executed * lacks the types that COM depends on (e.g. Variant on Silverlight). */ static void @@ -3106,13 +3137,13 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent)) mono_class_set_is_com_object (klass); - + if (system_namespace) { - if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) + if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) klass->delegate = 1; } - if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && + if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) klass->valuetype = 1; if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) { @@ -3206,7 +3237,7 @@ mono_class_setup_mono_type (MonoClass *klass) t = MONO_TYPE_BOOLEAN; } else if (!strcmp(name, "Byte")) { t = MONO_TYPE_U1; - klass->blittable = TRUE; + klass->blittable = TRUE; } break; case 'C': @@ -3217,7 +3248,7 @@ mono_class_setup_mono_type (MonoClass *klass) case 'D': if (!strcmp (name, "Double")) { t = MONO_TYPE_R8; - klass->blittable = TRUE; + klass->blittable = TRUE; } break; case 'I': @@ -3238,7 +3269,7 @@ mono_class_setup_mono_type (MonoClass *klass) case 'S': if (!strcmp (name, "Single")) { t = MONO_TYPE_R4; - klass->blittable = TRUE; + klass->blittable = TRUE; } else if (!strcmp(name, "SByte")) { t = MONO_TYPE_I1; klass->blittable = TRUE; @@ -3307,7 +3338,7 @@ create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *si * @class: a class * * Initializes the 'methods' array in CLASS. - * Calling this method should be avoided if possible since it allocates a lot + * Calling this method should be avoided if possible since it allocates a lot * of long-living MonoMethod structures. * Methods belonging to an interface are assigned a sequential slot starting * from 0. @@ -3346,7 +3377,7 @@ mono_class_setup_methods (MonoClass *klass) g_free (method); mono_error_cleanup (error); - return; + return; } } } else if (klass->rank) { @@ -3919,7 +3950,7 @@ mono_class_setup_has_finalizer (MonoClass *klass) * hierarchy + 1 * - supertypes: array of classes: each element has a class in the hierarchy * starting from @class up to System.Object - * + * * LOCKING: Acquires the loader lock. */ void @@ -4080,16 +4111,3 @@ mono_classes_init (void) mono_counters_register ("MonoClass size", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size); } - -void -m_field_set_parent (MonoClassField *field, MonoClass *klass) -{ - uintptr_t old_flags = m_field_get_meta_flags (field); - field->parent_and_flags = ((uintptr_t)klass) | old_flags; -} - -void -m_field_set_meta_flags (MonoClassField *field, unsigned int flags) -{ - field->parent_and_flags |= (field->parent_and_flags & ~MONO_CLASS_FIELD_META_FLAG_MASK) | flags; -} diff --git a/src/mono/mono/metadata/class-inlines.h b/src/mono/mono/metadata/class-inlines.h index a9aa3c992a541..e45350a8bc4aa 100644 --- a/src/mono/mono/metadata/class-inlines.h +++ b/src/mono/mono/metadata/class-inlines.h @@ -253,4 +253,18 @@ m_method_is_wrapper (MonoMethod *method) return method->wrapper_type != 0; } + +static inline void +m_field_set_parent (MonoClassField *field, MonoClass *klass) +{ + uintptr_t old_flags = m_field_get_meta_flags (field); + field->parent_and_flags = ((uintptr_t)klass) | old_flags; +} + +static inline void +m_field_set_meta_flags (MonoClassField *field, unsigned int flags) +{ + field->parent_and_flags |= (field->parent_and_flags & ~MONO_CLASS_FIELD_META_FLAG_MASK) | flags; +} + #endif diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 01104274c1f3b..c45c242393e2d 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -35,7 +35,7 @@ typedef struct _MonoDynamicMethod MonoDynamicMethod; /* Properties that applies to a group of structs should better use a higher number * to avoid colision with type specific properties. - * + * * This prop applies to class, method, property, event, assembly and image. */ #define MONO_PROP_DYNAMIC_CATTR 0x1000 @@ -87,7 +87,7 @@ struct _MonoMethod { signed int slot : 16; /* - * If is_generic is TRUE, the generic_container is stored in image->property_hash, + * If is_generic is TRUE, the generic_container is stored in image->property_hash, * using the key MONO_METHOD_PROP_GENERIC_CONTAINER. */ }; @@ -115,9 +115,9 @@ struct _MonoMethodPInvoke { guint32 implmap_idx; /* index into IMPLMAP */ }; -/* +/* * Stores the default value / RVA of fields. - * This information is rarely needed, so it is stored separately from + * This information is rarely needed, so it is stored separately from * MonoClassField. */ typedef struct MonoFieldDefaultValue { @@ -358,7 +358,7 @@ struct MonoVTable { /* do not add any fields after vtable, the structure is dynamically extended */ /* vtable contains function pointers to methods or their trampolines, at the end there may be a slot containing the pointer to the static fields */ - gpointer vtable [MONO_ZERO_LEN_ARRAY]; + gpointer vtable [MONO_ZERO_LEN_ARRAY]; }; #define MONO_SIZEOF_VTABLE (sizeof (MonoVTable) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P) @@ -647,7 +647,7 @@ typedef struct { gboolean enabled; } MonoStats; -/* +/* * new structure to hold performace counters values that are exported * to managed code. * Note: never remove fields from this structure and only add them to the end. @@ -802,7 +802,7 @@ mono_class_has_special_static_fields (MonoClass *klass); const char* mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type); -MONO_COMPONENT_API MonoProperty* +MONO_COMPONENT_API MonoProperty* mono_class_get_property_from_name_internal (MonoClass *klass, const char *name); const char* @@ -1231,7 +1231,7 @@ mono_class_get_generic_container (MonoClass *klass); gpointer mono_class_alloc (MonoClass *klass, int size); -gpointer +MONO_COMPONENT_API gpointer mono_class_alloc0 (MonoClass *klass, int size); #define mono_class_alloc0(klass, size) (g_cast (mono_class_alloc0 ((klass), (size)))) @@ -1260,7 +1260,7 @@ mono_class_has_variant_generic_params (MonoClass *klass); gboolean mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv); -gboolean +gboolean mono_class_is_subclass_of_internal (MonoClass *klass, MonoClass *klassc, gboolean check_interfaces); MONO_COMPONENT_API mono_bool @@ -1455,6 +1455,18 @@ mono_class_set_dim_conflicts (MonoClass *klass, GSList *conflicts); GSList* mono_class_get_dim_conflicts (MonoClass *klass); +/* opaque struct of class specific hot reload info */ +typedef struct _MonoClassMetadataUpdateInfo MonoClassMetadataUpdateInfo; + +MONO_COMPONENT_API gboolean +mono_class_has_metadata_update_info (MonoClass *klass); + +MONO_COMPONENT_API MonoClassMetadataUpdateInfo * +mono_class_get_metadata_update_info (MonoClass *klass); + +MONO_COMPONENT_API void +mono_class_set_metadata_update_info (MonoClass *klass, MonoClassMetadataUpdateInfo *value); + MONO_COMPONENT_API MonoMethod * mono_class_get_method_from_name_checked (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error); @@ -1492,7 +1504,7 @@ mono_class_get_default_finalize_method (void); const char * mono_field_get_rva (MonoClassField *field, int swizzle); -void +MONO_COMPONENT_API void mono_field_resolve_type (MonoClassField *field, MonoError *error); gboolean @@ -1575,12 +1587,6 @@ m_field_get_meta_flags (MonoClassField *field) return (unsigned int)(field->parent_and_flags & MONO_CLASS_FIELD_META_FLAG_MASK); } -void -m_field_set_parent (MonoClassField *field, MonoClass *klass); - -void -m_field_set_meta_flags (MonoClassField *field, unsigned int flags); - static inline gboolean m_field_get_offset (MonoClassField *field) { diff --git a/src/mono/mono/metadata/class-private-definition.h b/src/mono/mono/metadata/class-private-definition.h index 4724df84b7f8c..949c71d71f6e2 100644 --- a/src/mono/mono/metadata/class-private-definition.h +++ b/src/mono/mono/metadata/class-private-definition.h @@ -13,9 +13,9 @@ struct _MonoClass { /* element class for arrays and enum basetype for enums */ - MonoClass *element_class; + MonoClass *element_class; /* used for subtype checks */ - MonoClass *cast_class; + MonoClass *cast_class; /* for fast subtype checks */ MonoClass **supertypes; @@ -33,10 +33,10 @@ struct _MonoClass { /* A class contains static and non static data. Static data can be * of the same type as the class itselfs, but it does not influence - * the instance size of the class. To avoid cyclic calls to + * the instance size of the class. To avoid cyclic calls to * mono_class_init_internal (from mono_class_instance_size ()) we first - * initialise all non static fields. After that we set size_inited - * to 1, because we know the instance size now. After that we + * initialise all non static fields. After that we set size_inited + * to 1, because we know the instance size now. After that we * initialise all static fields. */ @@ -55,8 +55,8 @@ struct _MonoClass { /* next byte */ guint packing_size : 4; - guint ghcimpl : 1; /* class has its own GetHashCode impl */ - guint has_finalize : 1; /* class has its own Finalize impl */ + guint ghcimpl : 1; /* class has its own GetHashCode impl */ + guint has_finalize : 1; /* class has its own Finalize impl */ /* next byte */ guint delegate : 1; /* class is a Delegate */ guint gc_descr_inited : 1; /* gc_descr is initialized */ @@ -69,7 +69,7 @@ struct _MonoClass { * for COM Interop. set this flag on loading so all we need is a quick check * during object creation rather than having to traverse supertypes */ - guint is_com_object : 1; + guint is_com_object : 1; guint nested_classes_inited : 1; /* Whenever nested_class is initialized */ /* next byte*/ @@ -80,6 +80,7 @@ struct _MonoClass { guint has_failure : 1; /* See mono_class_get_exception_data () for a MonoErrorBoxed with the details */ guint has_weak_fields : 1; /* class has weak reference fields */ guint has_dim_conflicts : 1; /* Class has conflicting default interface methods */ + guint any_field_has_auto_layout : 1; /* a field in this type's layout uses auto-layout */ MonoClass *parent; MonoClass *nested_in; @@ -94,7 +95,7 @@ struct _MonoClass { guint16 interface_count; guint32 interface_id; /* unique inderface id (for interfaces) */ guint32 max_interface_id; - + guint16 interface_offsets_count; MonoClass **interfaces_packed; guint16 *interface_offsets_packed; diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index e1d66fe05eb1e..a0b7128ce0705 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -242,7 +242,7 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, gbo for (i = 0; i < ifaces->len; ++i) { int io; ic = (MonoClass *)g_ptr_array_index (ifaces, i); - + /*Force the sharing of interface offsets between parent and subtypes.*/ io = mono_class_interface_offset (k, ic); g_assertf (io >= 0, "class %s parent %s has no offset for iface %s", @@ -337,7 +337,7 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, gbo } g_free (ifaces_array); } - + //printf ("JUST DONE: "); //print_implemented_interfaces (klass); @@ -345,7 +345,7 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, gbo } /* - * Setup interface offsets for interfaces. + * Setup interface offsets for interfaces. * Initializes: * - klass->max_interface_id * - klass->interface_offsets_count @@ -409,7 +409,7 @@ mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespa int i; char *result; GString *res = g_string_new (""); - + g_string_append_c (res, '('); for (i = 0; i < sig->param_count; ++i) { if (i > 0) @@ -433,7 +433,7 @@ print_method_signatures (MonoMethod *im, MonoMethod *cm) { printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig); g_free (im_sig); g_free (cm_sig); - + } #endif @@ -545,7 +545,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c const char *ic_name_space = ic->name_space; const char *ic_name = ic->name; char *subname; - + if (! require_newslot) { TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]")); return FALSE; @@ -579,7 +579,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]")); return FALSE; } - + subname = (char*)strstr (cm->name, ic_name_space); if (subname != cm->name) { TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]")); @@ -615,7 +615,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c g_free (decl_name); return FALSE; } - + return TRUE; } } @@ -652,14 +652,14 @@ print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_no char *full_name = mono_type_full_name (m_class_get_byval_arg (klass)); int i; int parent_size; - + printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size); - + if (print_interfaces) { print_implemented_interfaces (klass); printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size); } - + if (klass->parent) { parent_size = klass->parent->vtable_size; } else { @@ -699,7 +699,7 @@ mono_class_verify_vtable (MonoClass *klass) printf ("*** Verifying VTable of class '%s' \n", full_name); g_free (full_name); full_name = NULL; - + if (!klass->methods) return; @@ -840,7 +840,7 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup) } return TRUE; } - + /* * mono_class_setup_vtable: * @@ -959,10 +959,10 @@ apply_override (MonoClass *klass, MonoClass *override_class, MonoMethod **vtable dslot += mono_class_interface_offset (klass, decl->klass); - //check if the override comes from an interface and the overrided method is from a class, if this is the case it shouldn't be changed + //check if the override comes from an interface and the overrided method is from a class, if this is the case it shouldn't be changed if (vtable [dslot] && vtable [dslot]->klass && MONO_CLASS_IS_INTERFACE_INTERNAL (override->klass) && !MONO_CLASS_IS_INTERFACE_INTERNAL (vtable [dslot]->klass)) return TRUE; - + vtable [dslot] = override; if (!MONO_CLASS_IS_INTERFACE_INTERNAL (override->klass)) { /* @@ -1110,7 +1110,7 @@ print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, Mono int index, mcount; char *method_signature; char *type_name; - + for (index = 0; index < onum; ++index) { mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name, overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot); @@ -1266,15 +1266,15 @@ print_vtable_layout_result (MonoClass *klass, MonoMethod **vtable, int cur_slot) for (i = 0; i < klass->interface_count; i++) { MonoClass *ic = klass->interfaces [i]; - printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n", + printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n", mono_class_interface_offset (klass, ic), mono_class_setup_count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic))); } for (MonoClass *k = klass->parent; k ; k = k->parent) { for (i = 0; i < k->interface_count; i++) { - MonoClass *ic = k->interfaces [i]; - printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n", + MonoClass *ic = k->interfaces [i]; + printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n", mono_class_interface_offset (klass, ic), mono_class_setup_count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic))); } @@ -1285,10 +1285,10 @@ print_vtable_layout_result (MonoClass *klass, MonoMethod **vtable, int cur_slot) /* * LOCKING: this is supposed to be called with the loader lock held. */ -static int +static int setup_class_vtsize (MonoClass *klass, GList *in_setup, int *cur_slot, int *stelemref_slot, MonoError *error) { - GPtrArray *ifaces = NULL; + GPtrArray *ifaces = NULL; int i, max_vtsize = 0; ifaces = mono_class_get_implemented_interfaces (klass, error); if (!is_ok (error)) { @@ -1305,7 +1305,7 @@ setup_class_vtsize (MonoClass *klass, GList *in_setup, int *cur_slot, int *stele g_ptr_array_free (ifaces, TRUE); ifaces = NULL; } - + if (klass->parent) { mono_class_init_internal (klass->parent); mono_class_setup_vtable_full (klass->parent, in_setup); @@ -1381,14 +1381,14 @@ mono_class_setup_vtable_ginst (MonoClass *klass, GList *in_setup) #ifdef FEATURE_COVARIANT_RETURNS /* * vtable_slot_has_preserve_base_overrides_attribute: - * + * * Needs to walk up the class hierarchy looking for the methods in this slot to * see if any are tagged with PreserveBaseOverrideAtrribute. */ static gboolean vtable_slot_has_preserve_base_overrides_attribute (MonoClass *klass, int slot, MonoClass **out_klass) { - /* + /* * FIXME: it's slow to do this loop every time. A faster way would be * to hang a boolean in the image of the parent class if it or any of * its ancestors have the attribute. @@ -1695,7 +1695,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o max_vtsize = setup_class_vtsize (klass, in_setup, &cur_slot, &stelemref_slot, error); if (max_vtsize == -1) return; - + cur_slot = mono_class_setup_interface_offsets_internal (klass, cur_slot, TRUE); if (cur_slot == -1) /*setup_interface_offsets fails the type.*/ return; @@ -1768,7 +1768,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE)); /* - * Create a list of virtual methods to avoid calling + * Create a list of virtual methods to avoid calling * mono_class_get_virtual_methods () which is slow because of the metadata * optimization. */ @@ -1823,14 +1823,14 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o } else { interface_is_explicitly_implemented_by_class = TRUE; } - + // Loop on all interface methods... int mcount = mono_class_get_method_count (ic); for (im_index = 0; im_index < mcount; im_index++) { MonoMethod *im = ic->methods [im_index]; int im_slot = ic_offset + im->slot; MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL; - + if (!m_method_is_virtual (im)) continue; @@ -1867,14 +1867,14 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/ goto fail; } - + // If the slot is still empty, look in all the inherited virtual methods... if ((vtable [im_slot] == NULL) && klass->parent != NULL) { MonoClass *parent = klass->parent; // Reverse order, so that last added methods are preferred for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) { MonoMethod *cm = parent->vtable [cm_index]; - + TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name)); if ((cm != NULL) && check_interface_method_override (klass, im, cm, MONO_ITF_OVERRIDE_SLOT_EMPTY)) { TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING\n")); @@ -1902,7 +1902,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o } } } - + // If the class is not abstract, check that all its interface slots are full. // The check is done here and not directly at the end of the loop above because // it can happen (for injected generic array interfaces) that the same slot is @@ -1913,15 +1913,15 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o for (i = 0; i < klass->interface_offsets_count; i++) { int ic_offset; int im_index; - + ic = klass->interfaces_packed [i]; ic_offset = mono_class_interface_offset (klass, ic); - + int mcount = mono_class_get_method_count (ic); for (im_index = 0; im_index < mcount; im_index++) { MonoMethod *im = ic->methods [im_index]; int im_slot = ic_offset + im->slot; - + if (!m_method_is_virtual (im)) continue; if (mono_method_get_is_reabstracted (im)) @@ -1960,7 +1960,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (!cmsig || !m1sig) /* FIXME proper error message, use signature_checked? */ goto fail; - if (!strcmp(cm->name, m1->name) && + if (!strcmp(cm->name, m1->name) && mono_metadata_signature_equal (cmsig, m1sig)) { slot = mono_method_get_vtable_slot (m1); @@ -1996,8 +1996,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o } if (mono_class_has_failure (k)) goto fail; - - if (slot >= 0) + + if (slot >= 0) break; } if (slot >= 0) @@ -2033,7 +2033,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o #endif if (!override_map) override_map = g_hash_table_new (mono_aligned_addr_hash, NULL); - TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", + TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", mono_method_full_name (decl, 1), decl, mono_method_full_name (impl, 1), impl)); g_hash_table_insert (override_map, decl, impl); diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 04af2642f252d..eceb20cf4d0f6 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -2401,6 +2402,10 @@ mono_class_get_field_idx (MonoClass *klass, int idx) return &klass_fields [idx - first_field_idx]; } } + if (G_UNLIKELY (m_class_get_image (klass)->has_updates && mono_class_has_metadata_update_info (klass))) { + uint32_t token = mono_metadata_make_token (MONO_TABLE_FIELD, idx + 1); + return mono_metadata_update_get_field (klass, token); + } } klass = m_class_get_parent (klass); } @@ -4621,13 +4626,20 @@ mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class, case MONO_TOKEN_TYPE_REF: case MONO_TOKEN_TYPE_SPEC: { MonoType *type; + MonoClass *klass; if (handle_class) *handle_class = mono_defaults.typehandle_class; type = mono_type_get_checked (image, token, context, error); if (!type) return NULL; - mono_class_init_internal (mono_class_from_mono_type_internal (type)); + klass = mono_class_from_mono_type_internal (type); + mono_class_init_internal (klass); + if (mono_class_has_failure (klass)) { + mono_error_set_for_class_failure (error, klass); + return NULL; + } + /* We return a MonoType* as handle */ return type; } @@ -5715,6 +5727,14 @@ mono_find_method_in_metadata (MonoClass *klass, const char *name, int param_coun } } + if (G_UNLIKELY (!res && klass_image->has_updates)) { + if (mono_class_has_metadata_update_info (klass)) { + ERROR_DECL (error); + res = mono_metadata_update_find_method_by_name (klass, name, param_count, flags, error); + mono_error_cleanup (error); + } + } + return res; } @@ -5777,7 +5797,8 @@ mono_class_get_method_from_name_checked (MonoClass *klass, const char *name, FIXME we should better report this error to the caller */ MonoMethod **klass_methods = m_class_get_methods (klass); - if (!klass_methods) + gboolean has_updates = m_class_get_image (klass)->has_updates; + if (!klass_methods && !has_updates) return NULL; int mcount = mono_class_get_method_count (klass); for (i = 0; i < mcount; ++i) { @@ -5791,6 +5812,9 @@ mono_class_get_method_from_name_checked (MonoClass *klass, const char *name, break; } } + if (G_UNLIKELY (!res && has_updates && mono_class_has_metadata_update_info (klass))) { + res = mono_metadata_update_find_method_by_name (klass, name, param_count, flags, error); + } } else { res = mono_find_method_in_metadata (klass, name, param_count, flags); @@ -6417,11 +6441,18 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) MonoImage *image = m_class_get_image (klass); MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL; MonoType *ftype; - int field_idx = field - m_class_get_fields (klass); + int field_idx; + + if (G_UNLIKELY (m_field_is_from_update (field))) { + field_idx = -1; + } else { + field_idx = field - m_class_get_fields (klass); + } error_init (error); if (gtd) { + g_assert (field_idx != -1); MonoClassField *gfield = &m_class_get_fields (gtd) [field_idx]; MonoType *gtype = mono_field_get_type_checked (gfield, error); if (!is_ok (error)) { @@ -6440,7 +6471,13 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) const char *sig; guint32 cols [MONO_FIELD_SIZE]; MonoGenericContainer *container = NULL; - int idx = mono_class_get_first_field_idx (klass) + field_idx; + int idx; + + if (G_UNLIKELY (m_field_is_from_update (field))) { + idx = mono_metadata_update_get_field_idx (field) - 1; + } else { + idx = mono_class_get_first_field_idx (klass) + field_idx; + } /*FIXME, in theory we do not lazy load SRE fields*/ g_assert (!image_is_dynamic (image)); diff --git a/src/mono/mono/metadata/class.h b/src/mono/mono/metadata/class.h index 8966e029b7c6c..a9fada0d31a3c 100644 --- a/src/mono/mono/metadata/class.h +++ b/src/mono/mono/metadata/class.h @@ -127,7 +127,7 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoClass * mono_class_from_mono_type (MonoType *type); MONO_API MONO_RT_EXTERNAL_ONLY mono_bool -mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, +mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, mono_bool check_interfaces); MONO_API MONO_RT_EXTERNAL_ONLY mono_bool @@ -140,7 +140,7 @@ mono_ldtoken (MonoImage *image, uint32_t token, MonoClass **retcla MONO_API char * mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format); -MONO_API char* +MONO_API char* mono_type_get_name (MonoType *type); MONO_API MonoType* diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c index ddeeaccb73502..ff2de267ddfd6 100644 --- a/src/mono/mono/metadata/cominterop.c +++ b/src/mono/mono/metadata/cominterop.c @@ -1,7 +1,7 @@ /** * \file * COM Interop Support - * + * * * (C) 2002 Ximian, Inc. http://www.ximian.com * @@ -267,7 +267,7 @@ mono_class_try_get_com_object_class (void) * cominterop_method_signature: * @method: a method * - * Returns: the corresponding unmanaged method signature for a managed COM + * Returns: the corresponding unmanaged method signature for a managed COM * method. */ static MonoMethodSignature* @@ -380,7 +380,7 @@ cominterop_get_com_slot_begin (MonoClass* klass) { ERROR_DECL (error); MonoCustomAttrInfo *cinfo = NULL; - MonoInterfaceTypeAttribute* itf_attr = NULL; + MonoInterfaceTypeAttribute* itf_attr = NULL; cinfo = mono_custom_attrs_from_class_checked (klass, error); mono_error_assert_ok (error); @@ -760,7 +760,7 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: { guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; - MonoClass *klass = NULL; + MonoClass *klass = NULL; klass = mono_class_from_mono_type_internal (type); @@ -845,13 +845,13 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, mono_mb_emit_byte (mb, CEE_CONV_U); mono_mb_emit_byte (mb, CEE_STIND_I); - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); // if null just break, dst was already inited to 0 pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_icall (mb, cominterop_object_is_rcw); pos_rcw = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); @@ -860,7 +860,7 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, mono_mb_emit_ldloc (mb, 1); // load src - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp)); mono_mb_emit_byte (mb, CEE_LDIND_REF); @@ -894,15 +894,15 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, } mono_mb_emit_byte (mb, CEE_STIND_I); pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - + // if not rcw mono_mb_patch_short_branch (mb, pos_rcw); /* load dst to store later */ mono_mb_emit_ldloc (mb, 1); /* load src */ - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); - + if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) mono_mb_emit_ptr (mb, mono_type_get_class_internal (type)); else if (conv == MONO_MARSHAL_CONV_OBJECT_IUNKNOWN) @@ -991,7 +991,7 @@ cominterop_get_native_wrapper_adjusted (MonoMethod *method) if (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) { // move return spec to last param - if (!MONO_TYPE_IS_VOID (sig->ret) && mspecs[0] == NULL) { + if (!MONO_TYPE_IS_VOID (sig->ret) && mspecs[0] == NULL) { // default object to VARIANT if (sig->ret->type == MONO_TYPE_OBJECT) { mspecs[0] = g_new0 (MonoMarshalSpec, 1); @@ -1012,9 +1012,9 @@ cominterop_get_native_wrapper_adjusted (MonoMethod *method) } } - mono_marshal_emit_native_wrapper (m_class_get_image (method->klass), mb_native, sig_native, piinfo, mspecs, piinfo->addr, EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS); + mono_marshal_emit_native_wrapper (m_class_get_image (method->klass), mb_native, sig_native, piinfo, mspecs, piinfo->addr, EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS | EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED); - res = mono_mb_create_method (mb_native, sig_native, sig_native->param_count + 16); + res = mono_mb_create_method (mb_native, sig_native, sig_native->param_count + 16); mono_mb_free (mb_native); @@ -1048,7 +1048,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) if (!m_class_get_vtable (method->klass)) mono_class_setup_vtable (method->klass); - + if (!m_class_get_methods (method->klass)) mono_class_setup_methods (method->klass); g_assert (!mono_class_has_failure (method->klass)); /*FIXME do proper error handling*/ @@ -1119,7 +1119,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) // push managed return value as byref last argument if (!MONO_TYPE_IS_VOID (sig->ret) && !preserve_sig) mono_mb_emit_ldloc_addr (mb, retval); - + adjusted_method = cominterop_get_native_wrapper_adjusted (method); mono_mb_emit_managed_call (mb, adjusted_method, NULL); @@ -1142,8 +1142,8 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) mono_mb_emit_byte (mb, CEE_RET); } - - + + } /* Does this case ever get hit? */ else { @@ -1175,7 +1175,7 @@ mono_cominterop_get_invoke (MonoMethod *method) MonoMethod *res; int i; GHashTable* cache; - + cache = mono_marshal_get_cache (&mono_method_get_wrapper_cache (method)->cominterop_invoke_cache, mono_aligned_addr_hash, NULL); g_assert (method); @@ -1243,14 +1243,14 @@ mono_cominterop_get_invoke (MonoMethod *method) return res; } -/* Maps a managed object to its unmanaged representation - * i.e. it's COM Callable Wrapper (CCW). +/* Maps a managed object to its unmanaged representation + * i.e. it's COM Callable Wrapper (CCW). * Key: MonoObject* * Value: MonoCCW* */ static GHashTable* ccw_hash = NULL; -/* Maps a CCW interface to it's containing CCW. +/* Maps a CCW interface to it's containing CCW. * Note that a CCW support many interfaces. * Key: MonoCCW* * Value: MonoCCWInterface* @@ -1277,10 +1277,10 @@ mono_get_addref (void) } int -mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, +mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -1334,13 +1334,13 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, conv_arg = mono_mb_add_local (mb, int_type); mono_mb_emit_ptr (mb, NULL); - mono_mb_emit_stloc (mb, conv_arg); + mono_mb_emit_stloc (mb, conv_arg); /* we dont need any conversions for out parameters */ if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) break; - mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldarg (mb, argnum); if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); /* if null just break, conv arg was already inited to 0 */ @@ -1472,7 +1472,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, /* case if null */ mono_mb_patch_short_branch (mb, pos_null); break; - } + } case MARSHAL_ACTION_MANAGED_CONV_IN: { int ccw_obj; @@ -1534,11 +1534,11 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, mono_mb_emit_byte (mb, CEE_LDC_I4_0); mono_mb_emit_byte (mb, CEE_STIND_I); - mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, conv_arg); pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); /* to store later */ - mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); if (klass && klass != mono_defaults.object_class) { mono_mb_emit_ptr (mb, t); @@ -1595,7 +1595,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, g_assert_not_reached (); mono_mb_emit_stloc (mb, 3); mono_mb_emit_ldloc (mb, 3); - + mono_mb_emit_managed_call (mb, mono_get_addref (), NULL); mono_mb_emit_byte (mb, CEE_POP); @@ -1794,7 +1794,7 @@ ves_icall_System_ComObject_CreateRCW (MonoReflectionTypeHandle ref_type, MonoErr return mono_object_new_alloc_by_vtable (vtable, error); } -static gboolean +static gboolean cominterop_rcw_interface_finalizer (gpointer key, gpointer value, gpointer user_data) { mono_IUnknown_Release ((MonoIUnknown*)value); @@ -1928,7 +1928,7 @@ cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method) /* FIXME: which to use? */ csig = mono_metadata_signature_dup_full (method_klass_image, sig); /* csig = mono_metadata_signature_dup (sig); */ - + /* STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM */ #ifdef HOST_WIN32 csig->call_convention = MONO_CALL_STDCALL; @@ -2103,6 +2103,7 @@ cominterop_get_ccw_method (MonoClass *iface, MonoMethod *method, MonoError *erro cominterop_setup_marshal_context (&m, adjust_method); m.mb = mb; + m.runtime_marshalling_enabled = TRUE; mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, 0); mono_cominterop_lock (); wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16); @@ -2553,10 +2554,10 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE; main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset; main_clause->data.catch_class = mono_defaults.object_class; - + /* handler code */ main_clause->handler_offset = mono_mb_get_label (mb); - + if (!preserve_sig || (sig->ret && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U4 || sig->ret->type == MONO_TYPE_I4))) { mono_mb_emit_managed_call (mb, get_hr_for_exception, NULL); mono_mb_emit_stloc (mb, hr); @@ -2583,7 +2584,7 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) #endif /* DISABLE_JIT */ mono_cominterop_lock (); - res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16); + res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16); mono_cominterop_unlock (); mono_mb_free (mb); @@ -2604,10 +2605,10 @@ cominterop_class_guid_equal (const guint8* guid, MonoClass* klass) return FALSE; } -static int STDCALL +static int STDCALL cominterop_ccw_addref_impl (MonoCCWInterface* ccwe); -static int STDCALL +static int STDCALL cominterop_ccw_addref (MonoCCWInterface* ccwe) { int result; @@ -2620,7 +2621,7 @@ cominterop_ccw_addref (MonoCCWInterface* ccwe) return result; } -static int STDCALL +static int STDCALL cominterop_ccw_addref_impl (MonoCCWInterface* ccwe) { MONO_REQ_GC_UNSAFE_MODE; @@ -2638,10 +2639,10 @@ cominterop_ccw_addref_impl (MonoCCWInterface* ccwe) return ref_count; } -static int STDCALL +static int STDCALL cominterop_ccw_release_impl (MonoCCWInterface* ccwe); -static int STDCALL +static int STDCALL cominterop_ccw_release (MonoCCWInterface* ccwe) { int result; @@ -2654,7 +2655,7 @@ cominterop_ccw_release (MonoCCWInterface* ccwe) return result; } -static int STDCALL +static int STDCALL cominterop_ccw_release_impl (MonoCCWInterface* ccwe) { MONO_REQ_GC_UNSAFE_MODE; @@ -2690,10 +2691,10 @@ cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObjectHandle object, } #endif -static int STDCALL +static int STDCALL cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv); -static int STDCALL +static int STDCALL cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv) { int result; @@ -2706,7 +2707,7 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, const guint8* riid, gpoin return result; } -static int STDCALL +static int STDCALL cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv) { MONO_REQ_GC_UNSAFE_MODE; @@ -2717,7 +2718,7 @@ cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, MonoCCW* ccw = ccwe->ccw; MonoClass* klass_iter = NULL; MonoObjectHandle object = mono_gchandle_get_target_handle (ccw->gc_handle); - + g_assert (!MONO_HANDLE_IS_NULL (object)); MonoClass* const klass = mono_handle_class (object); @@ -2740,7 +2741,7 @@ cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, if (cominterop_class_guid_equal (riid, mono_class_get_idispatch_class ())) { if (!cominterop_can_support_dispatch (klass)) return MONO_E_NOINTERFACE; - + *ppv = cominterop_get_ccw_checked (object, mono_class_get_idispatch_class (), error); mono_error_assert_ok (error); /* remember to addref on QI */ @@ -2791,7 +2792,7 @@ cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, return MONO_E_NOINTERFACE; } -static int STDCALL +static int STDCALL cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo) { if(!pctinfo) @@ -2802,19 +2803,19 @@ cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo) return MONO_S_OK; } -static int STDCALL +static int STDCALL cominterop_ccw_get_type_info (MonoCCWInterface* ccwe, guint32 iTInfo, guint32 lcid, gpointer *ppTInfo) { return MONO_E_NOTIMPL; } -static int STDCALL +static int STDCALL cominterop_ccw_get_ids_of_names_impl (MonoCCWInterface* ccwe, gpointer riid, gunichar2** rgszNames, guint32 cNames, guint32 lcid, gint32 *rgDispId); -static int STDCALL +static int STDCALL cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid, gunichar2** rgszNames, guint32 cNames, guint32 lcid, gint32 *rgDispId) @@ -2829,7 +2830,7 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid, return result; } -static int STDCALL +static int STDCALL cominterop_ccw_get_ids_of_names_impl (MonoCCWInterface* ccwe, gpointer riid, gunichar2** rgszNames, guint32 cNames, guint32 lcid, gint32 *rgDispId) @@ -2890,7 +2891,7 @@ cominterop_ccw_get_ids_of_names_impl (MonoCCWInterface* ccwe, gpointer riid, return ret; } -static int STDCALL +static int STDCALL cominterop_ccw_invoke (MonoCCWInterface* ccwe, guint32 dispIdMember, gpointer riid, guint32 lcid, guint16 wFlags, gpointer pDispParams, @@ -3164,7 +3165,7 @@ mono_string_from_bstr_icall_impl (mono_bstr_const bstr, MonoError *error) return mono_string_from_bstr_checked (bstr, error); } -MONO_API void +MONO_API void mono_free_bstr (/*mono_bstr_const*/gpointer bstr) { if (!bstr) @@ -3396,7 +3397,7 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT result.SetValueImpl(elem, index); } ++index; - } + } while (mono_marshal_safearray_next(safearray, indices)); } // label2 mono_marshal_safearray_end(safearray, indices); @@ -3706,7 +3707,7 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer * gboolean bounded = FALSE; #ifndef HOST_WIN32 - // If not on windows, check that the MS provider is used as it is + // If not on windows, check that the MS provider is used as it is // required for SAFEARRAY support. // If SAFEARRAYs are not supported, returning FALSE from this // function will prevent the other mono_marshal_safearray_xxx functions @@ -3831,7 +3832,7 @@ mono_marshal_safearray_get_value (gpointer safearray, gpointer indices) #endif /* HOST_WIN32 */ /* This is an icall */ -static +static gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices) { ERROR_DECL (error); @@ -3949,7 +3950,7 @@ static gboolean mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointer *indices, gpointer empty) { #ifndef HOST_WIN32 - // If not on windows, check that the MS provider is used as it is + // If not on windows, check that the MS provider is used as it is // required for SAFEARRAY support. // If SAFEARRAYs are not supported, returning FALSE from this // function will prevent the other mono_marshal_safearray_xxx functions @@ -4022,7 +4023,7 @@ mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer } } -static +static void mono_marshal_safearray_free_indices (gpointer indices) { g_free (indices); diff --git a/src/mono/mono/metadata/cominterop.h b/src/mono/mono/metadata/cominterop.h index ea6118b7e362d..2bd129ca7d7cd 100644 --- a/src/mono/mono/metadata/cominterop.h +++ b/src/mono/mono/metadata/cominterop.h @@ -1,7 +1,7 @@ /** * \file * COM Interop Support - * + * * * (C) 2002 Ximian, Inc. http://www.ximian.com * @@ -39,16 +39,16 @@ MonoMethod * mono_cominterop_get_invoke (MonoMethod *method); int -mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, +mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action); int mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); @@ -58,7 +58,7 @@ mono_string_from_bstr (/*mono_bstr*/gpointer bstr); MonoStringHandle mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error); -MONO_API void +MONO_API void mono_free_bstr (/*mono_bstr_const*/gpointer bstr); MonoClass* diff --git a/src/mono/mono/metadata/coree.c b/src/mono/mono/metadata/coree.c index 0d2be4aab223f..be6ce1434544c 100644 --- a/src/mono/mono/metadata/coree.c +++ b/src/mono/mono/metadata/coree.c @@ -432,7 +432,7 @@ HMODULE WINAPI MonoLoadImage(LPCWSTR FileName) if (FileHandle == INVALID_HANDLE_VALUE) return NULL; - FileSize = GetFileSize(FileHandle, NULL); + FileSize = GetFileSize(FileHandle, NULL); if (FileSize == INVALID_FILE_SIZE) goto CloseFile; diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 580a51b497d37..59a3ce25983e1 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -25,6 +25,7 @@ #include "mono/metadata/tabledefs.h" #include "mono/metadata/tokentype.h" #include "mono/metadata/icall-decl.h" +#include "mono/metadata/metadata-update.h" #include "mono/utils/checked-build.h" #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a)) @@ -150,6 +151,8 @@ free_param_data (MonoMethodSignature *sig, void **params) { */ static guint32 find_field_index (MonoClass *klass, MonoClassField *field) { + if (G_UNLIKELY (m_field_is_from_update (field))) + return mono_metadata_update_get_field_idx (field); int fcount = mono_class_get_field_count (klass); MonoClassField *klass_fields = m_class_get_fields (klass); int index = field - klass_fields; @@ -1626,8 +1629,6 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig error_init (error); ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE]; - /* FIXME: metadata-update */ - int rows = table_info_get_rows (ca); i = mono_metadata_custom_attrs_from_index (image, idx); if (!i) @@ -1635,9 +1636,17 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig i --; // initial size chosen arbitrarily, but default is 16 which is rather small attr_array = g_array_sized_new (TRUE, TRUE, sizeof (guint32), 128); - while (i < rows) { - if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx) - break; + while (!mono_metadata_table_bounds_check (image, MONO_TABLE_CUSTOMATTRIBUTE, i + 1)) { + if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx) { + if (G_LIKELY (!image->has_updates)) { + break; + } else { + // if there are updates, the new custom attributes are not sorted, + // so we have to go until the end. + ++i; + continue; + } + } attr_array = g_array_append_val (attr_array, i); ++i; } diff --git a/src/mono/mono/metadata/debug-helpers.c b/src/mono/mono/metadata/debug-helpers.c index b2743a89b0326..c3c706b754c6d 100644 --- a/src/mono/mono/metadata/debug-helpers.c +++ b/src/mono/mono/metadata/debug-helpers.c @@ -88,7 +88,7 @@ append_class_name (GString *res, MonoClass *klass, gboolean include_namespace) static MonoClass* find_system_class (const char *name) { - if (!strcmp (name, "void")) + if (!strcmp (name, "void")) return mono_defaults.void_class; else if (!strcmp (name, "char")) return mono_defaults.char_class; else if (!strcmp (name, "bool")) return mono_defaults.boolean_class; @@ -335,7 +335,7 @@ mono_context_get_desc (MonoGenericContext *context) res = g_strdup (str->str); g_string_free (str, TRUE); return res; -} +} /** * mono_method_desc_new: @@ -360,7 +360,7 @@ mono_method_desc_new (const char *name, gboolean include_namespace) char *class_name, *class_nspace, *method_name, *use_args, *end; int use_namespace; int generic_delim_stack; - + class_nspace = g_strdup (name); use_args = strchr (class_nspace, '('); if (use_args) { @@ -429,7 +429,7 @@ MonoMethodDesc* mono_method_desc_from_method (MonoMethod *method) { MonoMethodDesc *result; - + result = g_new0 (MonoMethodDesc, 1); result->include_namespace = TRUE; result->name = g_strdup (method->name); @@ -583,7 +583,7 @@ mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass) { MonoMethod* m; gpointer iter = NULL; - + while ((m = mono_class_get_methods (klass, &iter))) if (mono_method_desc_match (desc, m)) return m; @@ -663,7 +663,7 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha } if (dh->label_format) g_string_append_printf (str, dh->label_format, label); - + i = mono_opcode_value (&ip, end); ip++; opcode = &mono_opcodes [i]; @@ -833,7 +833,7 @@ mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, c ip = dis_one (res, dh, method, ip, ip + 2); if (endp) *endp = ip; - + result = res->str; g_string_free (res, FALSE); return result; @@ -853,7 +853,7 @@ mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const while (ip < end) { ip = dis_one (res, dh, method, ip, end); } - + result = res->str; g_string_free (res, FALSE); return result; diff --git a/src/mono/mono/metadata/debug-mono-ppdb.h b/src/mono/mono/metadata/debug-mono-ppdb.h index d26c16446a49a..1a011a1030778 100644 --- a/src/mono/mono/metadata/debug-mono-ppdb.h +++ b/src/mono/mono/metadata/debug-mono-ppdb.h @@ -50,7 +50,7 @@ mono_ppdb_lookup_location_enc (MonoPPDBFile *ppdb_file, int idx, uint32_t offset void mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points); -gboolean +gboolean mono_ppdb_get_seq_points_enc (MonoDebugMethodInfo *minfo, MonoPPDBFile *ppdb_file, int idx, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points); MonoDebugLocalsInfo* @@ -68,7 +68,7 @@ mono_ppdb_get_image (MonoPPDBFile *ppdb); char * mono_ppdb_get_sourcelink (MonoDebugHandle *handle); -gboolean +gboolean mono_ppdb_is_embedded (MonoPPDBFile *ppdb); MONO_COMPONENT_API MonoPPDBFile* diff --git a/src/mono/mono/metadata/debug-mono-symfile.c b/src/mono/mono/metadata/debug-mono-symfile.c index d8eed685da2b5..72925b73a68fe 100644 --- a/src/mono/mono/metadata/debug-mono-symfile.c +++ b/src/mono/mono/metadata/debug-mono-symfile.c @@ -176,7 +176,7 @@ mono_debug_open_mono_symbols (MonoDebugHandle *handle, const uint8_t *raw_conten mono_file_map_close (f); } } - + if (load_symfile (handle, symfile, in_the_debugger)) { mono_debugger_unlock (); return symfile; @@ -233,7 +233,7 @@ read_leb128 (const uint8_t *ptr, const uint8_t **rptr) do { b = *ptr++; - + ret = ret | ((b & 0x7f) << shift); shift += 7; } while ((b & 0x80) == 0x80); @@ -290,7 +290,7 @@ check_line (StatementMachine *stm, int offset, MonoDebugSourceLocation **locatio } if (stm->last_line == 0) { - /* + /* * The IL offset is less than the first IL offset which has a corresponding * source line. */ @@ -658,7 +658,7 @@ mono_debug_symfile_get_seq_points (MonoDebugMethodInfo *minfo, char **source_fil if (source_files) (*source_files) [i] = (*source_file_list)->len - 1; } - } + } if (n_seq_points) { g_assert (seq_points); diff --git a/src/mono/mono/metadata/domain-internals.h b/src/mono/mono/metadata/domain-internals.h index 398898c6e609a..65a44da3a28b4 100644 --- a/src/mono/mono/metadata/domain-internals.h +++ b/src/mono/mono/metadata/domain-internals.h @@ -29,7 +29,7 @@ G_BEGIN_DECLS * unloaded, and assemblies loaded by the appdomain are not unloaded either. This * allows us to use typed gc in non-default appdomains too, leading to increased * performance. - */ + */ extern gboolean mono_dont_free_domains; struct _MonoAppContext { @@ -136,7 +136,7 @@ mono_runtime_register_runtimeconfig_json_properties (MonovmRuntimeConfigArgument void mono_runtime_install_appctx_properties (void); -MONO_COMPONENT_API void +MONO_COMPONENT_API void mono_domain_set_fast (MonoDomain *domain); G_END_DECLS diff --git a/src/mono/mono/metadata/dynamic-image.c b/src/mono/mono/metadata/dynamic-image.c index 0eef174335576..706d4ed209a9f 100644 --- a/src/mono/mono/metadata/dynamic-image.c +++ b/src/mono/mono/metadata/dynamic-image.c @@ -1,8 +1,8 @@ /** * \file * Images created at runtime. - * - * + * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -213,11 +213,11 @@ mono_dynamic_image_get_registered_token (MonoDynamicImage *dynimage, guint32 tok #endif /** - * + * * mono_dynamic_image_is_valid_token: - * + * * Returns TRUE if token is valid in the given image. - * + * */ gboolean mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token) @@ -234,7 +234,7 @@ mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token) * mono_reflection_lookup_dynamic_token: * * Finish the Builder object pointed to by TOKEN and return the corresponding - * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by + * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object * mapping table. * @@ -250,7 +250,7 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean MonoClass *klass; error_init (error); - + lookup_dyn_token (assembly, token, &obj); if (MONO_HANDLE_IS_NULL (obj)) { if (valid_token) @@ -343,7 +343,7 @@ mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, c image = g_new0 (MonoDynamicImage, 1); MONO_PROFILER_RAISE (image_loading, (&image->image)); - + /*g_print ("created image %p\n", image);*/ /* keep in sync with image.c */ image->image.name = assembly_name; @@ -392,7 +392,7 @@ mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, c image->image.assembly = (MonoAssembly*)assembly; image->pe_kind = 0x1; /* ILOnly */ image->machine = 0x14c; /* I386 */ - + MONO_PROFILER_RAISE (image_loaded, (&image->image)); dynamic_images_lock (); diff --git a/src/mono/mono/metadata/dynamic-stream.c b/src/mono/mono/metadata/dynamic-stream.c index e33bec79d3fa1..940532bdd96c8 100644 --- a/src/mono/mono/metadata/dynamic-stream.c +++ b/src/mono/mono/metadata/dynamic-stream.c @@ -34,14 +34,14 @@ make_room_in_stream (MonoDynamicStream *stream, int size) if (size <= stream->alloc_size) return; - + while (stream->alloc_size <= size) { if (stream->alloc_size < 4096) stream->alloc_size = 4096; else stream->alloc_size *= 2; } - + stream->data = (char *)g_realloc (stream->data, stream->alloc_size); } @@ -59,7 +59,7 @@ mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str) len = strlen (str) + 1; idx = sh->index; - + make_room_in_stream (sh, idx + len); /* @@ -93,12 +93,12 @@ mono_dynstream_add_data (MonoDynamicStream *stream, gconstpointer data, guint32 MONO_REQ_GC_NEUTRAL_MODE; guint32 idx; - + make_room_in_stream (stream, stream->index + len); memcpy (stream->data + stream->index, data, len); idx = stream->index; stream->index += len; - /* + /* * align index? Not without adding an additional param that controls it since * we may store a blob value in pieces. */ @@ -111,7 +111,7 @@ mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len) MONO_REQ_GC_NEUTRAL_MODE; guint32 idx; - + make_room_in_stream (stream, stream->index + len); memset (stream->data + stream->index, 0, len); idx = stream->index; diff --git a/src/mono/mono/metadata/exception.c b/src/mono/mono/metadata/exception.c index f1aaba68de069..340ab7d466452 100644 --- a/src/mono/mono/metadata/exception.c +++ b/src/mono/mono/metadata/exception.c @@ -101,7 +101,7 @@ mono_exception_from_name (MonoImage *image, const char *name_space, * \returns the initialized exception instance. */ MonoException * -mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, +mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, const char* name_space, const char *name) { HANDLE_FUNCTION_ENTER (); @@ -148,14 +148,14 @@ create_exception_two_strings (MonoClass *klass, MonoStringHandle a1, MonoStringH int const count = 1 + !MONO_HANDLE_IS_NULL (a2); gpointer iter; MonoMethod *m; - + MonoObjectHandle o = mono_object_new_handle (klass, error); mono_error_assert_ok (error); iter = NULL; while ((m = mono_class_get_methods (klass, &iter))) { MonoMethodSignature *sig; - + if (strcmp (".ctor", mono_method_get_name (m))) continue; sig = mono_method_signature_internal (m); @@ -862,7 +862,7 @@ MonoException * mono_get_exception_bad_image_format (const char *msg) { return mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", msg); -} +} /** * mono_get_exception_bad_image_format2: @@ -896,7 +896,7 @@ mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname_raw) MonoException * mono_get_exception_stack_overflow (void) { - return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException"); + return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException"); } /** @@ -1222,7 +1222,7 @@ mono_invoke_unhandled_exception_hook (MonoObject *exc) MonoObject *other = NULL; MonoString *str = mono_object_try_to_string (exc, &other, inner_error); char *msg = NULL; - + if (str && is_ok (inner_error)) { msg = mono_string_to_utf8_checked_internal (str, inner_error); if (!is_ok (inner_error)) { diff --git a/src/mono/mono/metadata/exception.h b/src/mono/mono/metadata/exception.h index 155c23c7e7747..0876657ac2e60 100644 --- a/src/mono/mono/metadata/exception.h +++ b/src/mono/mono/metadata/exception.h @@ -12,8 +12,8 @@ MONO_BEGIN_DECLS MONO_API MonoException * -mono_exception_from_name (MonoImage *image, - const char* name_space, +mono_exception_from_name (MonoImage *image, + const char* name_space, const char *name); MONO_API MonoException * @@ -34,8 +34,8 @@ mono_exception_from_token_two_strings (MonoImage *image, uint32_t token, MonoString *a1, MonoString *a2); MONO_API MonoException * -mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, - const char* name_space, +mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, + const char* name_space, const char *name); MONO_API MonoException * diff --git a/src/mono/mono/metadata/external-only.c b/src/mono/mono/metadata/external-only.c index 19999e384c776..2b65cf280fb4f 100644 --- a/src/mono/mono/metadata/external-only.c +++ b/src/mono/mono/metadata/external-only.c @@ -275,7 +275,7 @@ mono_g_hash_table_new_type (GHashFunc hash_func, GEqualFunc key_equal_func, Mono /** * mono_config_for_assembly: */ -void +void mono_config_for_assembly (MonoImage *assembly) { } @@ -618,8 +618,8 @@ mono_context_init (MonoDomain *domain) * * Used to set the system configuration for an appdomain * - * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException: - * Error Initializing the configuration system. ---> System.ArgumentException: + * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException: + * Error Initializing the configuration system. ---> System.ArgumentException: * The 'ExeConfigFilename' argument cannot be null.' for some managed calls. */ void diff --git a/src/mono/mono/metadata/gc-internals.h b/src/mono/mono/metadata/gc-internals.h index 60e2d79d0ff3c..466c3be715dc0 100644 --- a/src/mono/mono/metadata/gc-internals.h +++ b/src/mono/mono/metadata/gc-internals.h @@ -182,7 +182,7 @@ void mono_gc_clear_domain (MonoDomain * domain); void mono_gc_suspend_finalizers (void); -/* +/* * Register a root which can only be written using a write barrier. * Writes to the root must be done using a write barrier (MONO_ROOT_SETREF). * If the root uses an user defined mark routine, the writes are not required to be @@ -235,30 +235,30 @@ typedef void (*MonoRangeCopyFunction)(gpointer, gconstpointer, int size); MonoRangeCopyFunction mono_gc_get_range_copy_func (void); -/* +/* * Functions supplied by the runtime and called by the GC. Currently only used * by SGEN. */ typedef struct { - /* - * Function called during thread startup/attach to allocate thread-local data + /* + * Function called during thread startup/attach to allocate thread-local data * needed by the other functions. */ gpointer (*thread_attach_func) (void); - /* + /* * Function called during thread deatch to free the data allocated by * thread_attach_func. */ void (*thread_detach_func) (gpointer user_data); - /* + /* * Function called from every thread when suspending for GC. It can save - * data needed for marking from thread stacks. user_data is the data returned + * data needed for marking from thread stacks. user_data is the data returned * by attach_func. This might called with GC locks held and the word stopped, * so it shouldn't do any synchronization etc. */ void (*thread_suspend_func) (gpointer user_data, void *sigcontext, MonoContext *ctx); - /* - * Function called to mark from thread stacks. user_data is the data returned + /* + * Function called to mark from thread stacks. user_data is the data returned * by attach_func. This is called twice, with the word stopped: * - in the first pass, it should mark areas of the stack using * conservative marking by calling mono_gc_conservatively_scan_area (). diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index 8c0745705e861..5144e40eeec43 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -175,7 +175,7 @@ coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 return res; } -/* +/* * actually, we might want to queue the finalize requests in a separate thread, * but we need to be careful about the execution domain of the thread... */ @@ -253,7 +253,7 @@ mono_gc_run_finalize (void *obj, void *data) * These can't be finalized during unloading/shutdown, since that would * free the native code which can still be referenced by other * finalizers. - * FIXME: This is not perfect, objects dying at the same time as + * FIXME: This is not perfect, objects dying at the same time as * dynamic methods can still reference them even when !shutdown. */ return; @@ -293,7 +293,7 @@ mono_gc_run_finalize (void *obj, void *data) return; } - /* + /* * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (), * create and precompile a wrapper which calls the finalize method using * a CALLVIRT. @@ -356,7 +356,7 @@ mono_gc_run_finalize (void *obj, void *data) * (because of the GetHashCode hack), but we need to pass the real address to register_finalizer. * This also means that in the callback we need to adjust the pointer to get back the real * MonoObject*. - * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer, + * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer, * since that, too, can cause the underlying pointer to be offset. */ static void @@ -386,7 +386,7 @@ object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*)) * * Records that object \p obj has a finalizer, this will call the * Finalize method when the garbage collector disposes the object. - * + * */ void mono_object_register_finalizer_handle (MonoObjectHandle obj) @@ -420,7 +420,7 @@ mono_object_register_finalizer (MonoObject *obj) * \returns TRUE if succeeded, FALSE if there was a timeout */ gboolean -mono_domain_finalize (MonoDomain *domain, guint32 timeout) +mono_domain_finalize (MonoDomain *domain, guint32 timeout) { DomainFinalizationReq *req; MonoInternalThread *thread = mono_thread_internal_current (); @@ -432,11 +432,11 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) /* We are called from inside a finalizer, not much we can do here */ return FALSE; - /* + /* * No need to create another thread 'cause the finalizer thread * is still working and will take care of running the finalizers - */ - + */ + if (gc_disabled) return TRUE; @@ -453,7 +453,7 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) if (domain == mono_get_root_domain ()) finalizing_root_domain = TRUE; - + mono_finalizer_lock (); domains_to_finalize = g_slist_append (domains_to_finalize, req); @@ -702,7 +702,9 @@ mono_gc_finalize_notify (void) if (mono_gc_is_null ()) return; -#ifdef HOST_WASM +#if defined(HOST_WASI) + // TODO: Schedule the background job on WASI. Threads aren't yet supported in this build. +#elif defined(HOST_WASM) mono_threads_schedule_background_job (mono_runtime_do_background_work); #else mono_coop_sem_post (&finalizer_sem); @@ -787,7 +789,7 @@ finalize_domain_objects (void) while (g_hash_table_size (finalizable_objects_hash) > 0) { int i; GPtrArray *objs; - /* + /* * Since the domain is unloading, nobody is allowed to put * new entries into the hash table. But finalize_object might * remove entries from the hash table, so we make a copy. @@ -811,7 +813,7 @@ finalize_domain_objects (void) /* cleanup the reference queue */ reference_queue_clear_for_domain (domain); - + /* printf ("DONE.\n"); */ mono_coop_sem_post (&req->done); @@ -1000,7 +1002,7 @@ mono_gc_is_finalizer_internal_thread (MonoInternalThread *thread) * In Mono objects are finalized asynchronously on a separate thread. * This routine tests whether the \p thread argument represents the * finalization thread. - * + * * \returns TRUE if \p thread is the finalization thread. */ gboolean diff --git a/src/mono/mono/metadata/handle.c b/src/mono/mono/metadata/handle.c index d6af32f73b291..8474c385007b2 100644 --- a/src/mono/mono/metadata/handle.c +++ b/src/mono/mono/metadata/handle.c @@ -49,7 +49,7 @@ Combine: MonoDefaults, GENERATE_GET_CLASS_WITH_CACHE, TYPED_HANDLE_DECL and frie /* * NOTE: Async suspend - * + * * If we are running with cooperative GC, all the handle stack * manipulation will complete before a GC thread scans the handle * stack. If we are using async suspend, however, a thread may be @@ -362,7 +362,7 @@ mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, c /* * Pop the stack until @stackmark and make @value the top value. * - * @return the new handle for what @value points to + * @return the new handle for what @value points to */ MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value) diff --git a/src/mono/mono/metadata/handle.h b/src/mono/mono/metadata/handle.h index 5628d3b179276..46f69c5124bbf 100644 --- a/src/mono/mono/metadata/handle.h +++ b/src/mono/mono/metadata/handle.h @@ -32,7 +32,7 @@ The handle stack is designed so it's efficient to pop a large amount of entries The stack is made out of a series of fixed size segments. To do bulk operations you use a stack mark. - + */ /* diff --git a/src/mono/mono/metadata/icall-decl.h b/src/mono/mono/metadata/icall-decl.h index d99cf1cee6c32..1a960fdaa8655 100644 --- a/src/mono/mono/metadata/icall-decl.h +++ b/src/mono/mono/metadata/icall-decl.h @@ -60,7 +60,6 @@ typedef enum { // This is sorted. // grep ICALL_EXPORT | sort | uniq ICALL_EXPORT MonoAssemblyName* ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly*); -ICALL_EXPORT MonoBoolean ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char*, MonoAssemblyName*, MonoBoolean*, MonoBoolean* is_token_defined_arg); ICALL_EXPORT MonoBoolean ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void); ICALL_EXPORT MonoBoolean ves_icall_System_Threading_Thread_YieldInternal (void); ICALL_EXPORT MonoThread *ves_icall_System_Threading_Thread_GetCurrentThread (void); @@ -68,7 +67,6 @@ ICALL_EXPORT void ves_icall_System_ArgIterator_Setup (MonoArgIterator*, char*, c ICALL_EXPORT MonoType* ves_icall_System_ArgIterator_IntGetNextArgType (MonoArgIterator*); ICALL_EXPORT void ves_icall_System_ArgIterator_IntGetNextArg (MonoArgIterator*, MonoTypedRef*); ICALL_EXPORT void ves_icall_System_ArgIterator_IntGetNextArgWithType (MonoArgIterator*, MonoTypedRef*, MonoType*); -ICALL_EXPORT double ves_icall_System_Math_Abs_double (double); ICALL_EXPORT double ves_icall_System_Math_Acos (double); ICALL_EXPORT double ves_icall_System_Math_Acosh (double); ICALL_EXPORT double ves_icall_System_Math_Asin (double); @@ -116,7 +114,6 @@ ICALL_EXPORT float ves_icall_System_MathF_Sinh (float); ICALL_EXPORT float ves_icall_System_MathF_Sqrt (float); ICALL_EXPORT float ves_icall_System_MathF_Tan (float); ICALL_EXPORT float ves_icall_System_MathF_Tanh (float); -ICALL_EXPORT float ves_icall_System_Math_Abs_single (float); ICALL_EXPORT double ves_icall_System_Math_Log2 (double); ICALL_EXPORT double ves_icall_System_Math_FusedMultiplyAdd (double, double, double); ICALL_EXPORT float ves_icall_System_MathF_Log2 (float); diff --git a/src/mono/mono/metadata/icall-def-netcore.h b/src/mono/mono/metadata/icall-def-netcore.h index 3dde98a274d3d..b26f5cc8fec63 100644 --- a/src/mono/mono/metadata/icall-def-netcore.h +++ b/src/mono/mono/metadata/icall-def-netcore.h @@ -108,9 +108,7 @@ ICALL_TYPE(STREAM, "System.IO.Stream", STREAM_1) HANDLES(STREAM_1, "HasOverriddenBeginEndRead", ves_icall_System_IO_Stream_HasOverriddenBeginEndRead, MonoBoolean, 1, (MonoObject)) HANDLES(STREAM_2, "HasOverriddenBeginEndWrite", ves_icall_System_IO_Stream_HasOverriddenBeginEndWrite, MonoBoolean, 1, (MonoObject)) -ICALL_TYPE(MATH, "System.Math", MATH_19) -NOHANDLES(ICALL(MATH_19, "Abs(double)", ves_icall_System_Math_Abs_double)) -NOHANDLES(ICALL(MATH_20, "Abs(single)", ves_icall_System_Math_Abs_single)) +ICALL_TYPE(MATH, "System.Math", MATH_1) NOHANDLES(ICALL(MATH_1, "Acos", ves_icall_System_Math_Acos)) NOHANDLES(ICALL(MATH_1a, "Acosh", ves_icall_System_Math_Acosh)) NOHANDLES(ICALL(MATH_2, "Asin", ves_icall_System_Math_Asin)) @@ -172,14 +170,11 @@ ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_2) HANDLES(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly, MonoReflectionAssembly, 0, ()) HANDLES(ASSEM_3, "GetEntryAssemblyNative", ves_icall_System_Reflection_Assembly_GetEntryAssembly, MonoReflectionAssembly, 0, ()) HANDLES(ASSEM_4, "GetExecutingAssembly", ves_icall_System_Reflection_Assembly_GetExecutingAssembly, MonoReflectionAssembly, 1, (MonoStackCrawlMark_ptr)) -HANDLES(ASSEM_5, "InternalGetAssemblyName", ves_icall_System_Reflection_Assembly_InternalGetAssemblyName, void, 3, (MonoString, MonoAssemblyName_ref, MonoStringOut)) HANDLES(ASSEM_6, "InternalGetType", ves_icall_System_Reflection_Assembly_InternalGetType, MonoReflectionType, 5, (MonoReflectionAssembly, MonoReflectionModule, MonoString, MonoBoolean, MonoBoolean)) HANDLES(ASSEM_7, "InternalLoad", ves_icall_System_Reflection_Assembly_InternalLoad, MonoReflectionAssembly, 3, (MonoString, MonoStackCrawlMark_ptr, gpointer)) ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0) NOHANDLES(ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)) -NOHANDLES(ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName)) -NOHANDLES(ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)) ICALL_TYPE(MCATTR, "System.Reflection.CustomAttribute", MCATTR_1) HANDLES(MCATTR_1, "GetCustomAttributesDataInternal", ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal, MonoArray, 1, (MonoObject)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 39806dd249178..8bd911b7830aa 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -4990,60 +4990,6 @@ ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass) return &mass->aname; } -void -ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle fname, MonoAssemblyName *name, MonoStringHandleOut normalized_codebase, MonoError *error) -{ - char *filename; - MonoImageOpenStatus status = MONO_IMAGE_OK; - char *codebase = NULL; - gboolean res; - MonoImage *image; - - filename = mono_string_handle_to_utf8 (fname, error); - return_if_nok (error); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "InternalGetAssemblyName (\"%s\")", filename); - - MonoAssemblyLoadContext *alc = mono_alc_get_default (); - image = mono_image_open_a_lot (alc, filename, &status); - - if (!image){ - if (status == MONO_IMAGE_IMAGE_INVALID) - mono_error_set_bad_image_by_name (error, filename, "Invalid Image: %s", filename); - else - mono_error_set_simple_file_not_found (error, filename); - g_free (filename); - return; - } - - res = mono_assembly_fill_assembly_name_full (image, name, TRUE); - if (!res) { - mono_image_close (image); - g_free (filename); - mono_error_set_argument (error, "assemblyFile", "The file does not contain a manifest"); - return; - } - - if (filename != NULL && *filename != '\0') { - gchar *result; - - codebase = g_strdup (filename); - - mono_icall_make_platform_path (codebase); - - const gchar *prepend = mono_icall_get_file_path_prefix (codebase); - - result = g_strconcat (prepend, codebase, (const char*)NULL); - g_free (codebase); - codebase = result; - } - MONO_HANDLE_ASSIGN (normalized_codebase, mono_string_new_handle (codebase, error)); - g_free (codebase); - - mono_image_close (image); - g_free (filename); -} - static gboolean mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type) { @@ -5379,21 +5325,6 @@ gint32 ves_icall_AssemblyExtensions_ApplyUpdateEnabled (gint32 just_component_ch return mono_metadata_update_available () && (just_component_check || mono_metadata_update_enabled (NULL)); } -MonoBoolean -ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, MonoBoolean *is_version_defined_arg, MonoBoolean *is_token_defined_arg) -{ - gboolean is_version_defined = FALSE; - gboolean is_token_defined = FALSE; - gboolean result = FALSE; - - result = mono_assembly_name_parse_full (name, aname, TRUE, &is_version_defined, &is_token_defined); - - *is_version_defined_arg = (MonoBoolean)is_version_defined; - *is_token_defined_arg = (MonoBoolean)is_token_defined; - - return result; -} - MonoReflectionTypeHandle ves_icall_System_Reflection_RuntimeModule_GetGlobalType (MonoImage *image, MonoError *error) { diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index ee77f79966982..4b2efe2b37659 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -2,7 +2,7 @@ * \file * Routines for manipulating an image stored in an * extended PE/COFF file. - * + * * Authors: * Miguel de Icaza (miguel@ximian.com) * Paolo Molaro (lupus@ximian.com) @@ -127,7 +127,7 @@ void mono_install_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data) { ImageUnloadHook *hook; - + g_return_if_fail (func != NULL); hook = g_new0 (ImageUnloadHook, 1); @@ -206,10 +206,10 @@ mono_cli_rva_image_map (MonoImage *image, guint32 addr) * \param addr relative virtual address (RVA) * * This is a low-level routine used by the runtime to map relative - * virtual address (RVA) into their location in memory. + * virtual address (RVA) into their location in memory. * * \returns the address in memory for the given RVA, or NULL if the - * RVA is not valid for this image. + * RVA is not valid for this image. */ char * mono_image_rva_map (MonoImage *image, guint32 addr) @@ -288,14 +288,14 @@ mono_image_ensure_section_idx (MonoImage *image, int section) { MonoCLIImageInfo *iinfo = image->image_info; MonoSectionTable *sect; - + g_return_val_if_fail (section < iinfo->cli_section_count, FALSE); if (iinfo->cli_sections [section] != NULL) return TRUE; sect = &iinfo->cli_section_tables [section]; - + if (sect->st_raw_data_ptr + sect->st_raw_data_size > image->raw_data_len) return FALSE; #ifdef HOST_WIN32 @@ -323,11 +323,11 @@ mono_image_ensure_section (MonoImage *image, const char *section) { MonoCLIImageInfo *ii = image->image_info; int i; - + for (i = 0; i < ii->cli_section_count; i++){ if (strncmp (ii->cli_section_tables [i].st_name, section, 8) != 0) continue; - + return mono_image_ensure_section_idx (image, i); } return FALSE; @@ -342,7 +342,7 @@ load_section_tables (MonoImage *image, MonoCLIImageInfo *iinfo, guint32 offset) iinfo->cli_section_count = top; iinfo->cli_section_tables = g_new0 (MonoSectionTable, top); iinfo->cli_sections = g_new0 (void *, top); - + for (i = 0; i < top; i++){ MonoSectionTable *t = &iinfo->cli_section_tables [i]; @@ -372,7 +372,7 @@ gboolean mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo) { guint32 offset; - + offset = mono_cli_rva_image_map (image, iinfo->cli_header.datadir.pe_cli_header.rva); if (offset == INVALID_ADDRESS) return FALSE; @@ -428,7 +428,7 @@ mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo) /* g_warning ("Some fields in the CLI header which should have been zero are not zero"); */ } - + return TRUE; } @@ -455,7 +455,7 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) int i; guint32 pad; char *ptr; - + offset = mono_cli_rva_image_map (image, iinfo->cli_cli_header.ch_metadata.rva); if (offset == INVALID_ADDRESS) return FALSE; @@ -490,7 +490,7 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) /* skip over flags */ ptr += 2; - + streams = read16 (ptr); ptr += 2; @@ -591,7 +591,7 @@ load_tables (MonoImage *image) guint64 valid_mask; int valid = 0, table; int heap_sizes; - + heap_sizes = heap_tables [6]; image->idx_string_wide = ((heap_sizes & 0x01) == 1); image->idx_guid_wide = ((heap_sizes & 0x02) == 2); @@ -603,10 +603,10 @@ load_tables (MonoImage *image) g_assert (image->idx_guid_wide); g_assert (image->idx_blob_wide); } - + valid_mask = read64 (heap_tables + 8); rows = (const guint32 *) (heap_tables + 24); - + for (table = 0; table < 64; table++){ if ((valid_mask & ((guint64) 1 << table)) == 0){ if (table > MONO_TABLE_LAST) @@ -677,7 +677,7 @@ mono_image_check_for_module_cctor (MonoImage *image) guint32 last_method; if (table_info_get_rows (t) > 1) last_method = mono_metadata_decode_row_col (t, 1, MONO_TYPEDEF_METHOD_LIST) - 1; - else + else last_method = table_info_get_rows (mt); for (; first_method < last_method; first_method++) { nameidx = mono_metadata_decode_row_col (mt, first_method, MONO_METHOD_NAME); @@ -777,7 +777,7 @@ mono_image_init (MonoImage *image) #define SWAPPDE(x) #endif -static int +static int do_load_header_internal (const char *raw_data, guint32 raw_data_len, MonoDotNetHeader *header, int offset, gboolean image_is_module_handle) { MonoDotNetHeader64 header64; @@ -910,12 +910,12 @@ do_load_header_internal (const char *raw_data, guint32 raw_data_len, MonoDotNetH static int do_load_header (MonoImage *image, MonoDotNetHeader *header, int offset) { - offset = do_load_header_internal (image->raw_data, image->raw_data_len, header, offset, + offset = do_load_header_internal (image->raw_data, image->raw_data_len, header, offset, #ifdef HOST_WIN32 m_image_is_module_handle (image)); #else FALSE); -#endif +#endif #ifdef HOST_WIN32 if (m_image_is_module_handle (image)) @@ -924,7 +924,7 @@ do_load_header (MonoImage *image, MonoDotNetHeader *header, int offset) return offset; } -mono_bool +mono_bool mono_has_pdb_checksum (char *raw_data, uint32_t raw_data_len) { MonoDotNetHeader cli_header; @@ -934,11 +934,11 @@ mono_has_pdb_checksum (char *raw_data, uint32_t raw_data_len) int offset = 0; memcpy (&msdos, raw_data + offset, sizeof (msdos)); - + if (!(msdos.msdos_sig [0] == 'M' && msdos.msdos_sig [1] == 'Z')) { return FALSE; } - + msdos.pe_offset = GUINT32_FROM_LE (msdos.pe_offset); offset = msdos.pe_offset; @@ -959,7 +959,7 @@ mono_has_pdb_checksum (char *raw_data, uint32_t raw_data_len) if (ret + sizeof (MonoSectionTable) > raw_data_len) { return FALSE; } - + memcpy (&t, raw_data + ret, sizeof (MonoSectionTable)); ret += sizeof (MonoSectionTable); @@ -1014,10 +1014,10 @@ pe_image_load_pe_data (MonoImage *image) goto invalid_image; memcpy (&msdos, image->raw_data + offset, sizeof (msdos)); - + if (!(msdos.msdos_sig [0] == 'M' && msdos.msdos_sig [1] == 'Z')) goto invalid_image; - + msdos.pe_offset = GUINT32_FROM_LE (msdos.pe_offset); offset = msdos.pe_offset; @@ -1052,7 +1052,7 @@ pe_image_load_pe_data (MonoImage *image) /* * FIXME: byte swap all addresses here for header. */ - + if (!load_section_tables (image, iinfo, offset)) goto invalid_image; @@ -1104,7 +1104,7 @@ mono_image_load_names (MonoImage *image) { /* modules don't have an assembly table row */ if (table_info_get_rows (&image->tables [MONO_TABLE_ASSEMBLY])) { - image->assembly_name = mono_metadata_string_heap (image, + image->assembly_name = mono_metadata_string_heap (image, mono_metadata_decode_row_col (&image->tables [MONO_TABLE_ASSEMBLY], 0, MONO_ASSEMBLY_NAME)); } @@ -1314,7 +1314,7 @@ mono_image_storage_dtor (gpointer self) MonoImageStorage *storage = (MonoImageStorage *)self; mono_image_storage_unpublish (storage); - + #ifdef HOST_WIN32 if (storage->is_module_handle && !storage->has_entry_point) { mono_images_lock (); @@ -1369,7 +1369,7 @@ mono_image_storage_open (const char *fname) g_free (key); return published_storage; } - + MonoFileMap *filed; if ((filed = mono_file_map_open (fname)) == NULL){ g_free (key); @@ -1390,7 +1390,7 @@ mono_image_storage_open (const char *fname) mono_file_map_close (filed); storage->key = key; - + MonoImageStorage *other_storage = NULL; if (!mono_image_storage_trypublish (storage, &other_storage)) { mono_image_storage_close (storage); @@ -1789,7 +1789,7 @@ mono_image_open_a_lot_parameterized (MonoLoadedImages *li, MonoAssemblyLoadConte char *absfname; g_return_val_if_fail (fname != NULL, NULL); - + #ifdef HOST_WIN32 // Win32 path: If we are running with mixed-mode assemblies enabled (ie have loaded mscoree.dll), // then assemblies need to be loaded with LoadLibrary: @@ -1901,8 +1901,8 @@ mono_image_open_a_lot (MonoAssemblyLoadContext *alc, const char *fname, MonoImag * mono_image_open: * \param fname filename that points to the module we want to open * \param status An error condition is returned in this field - * \returns An open image of type \c MonoImage or NULL on error. - * The caller holds a temporary reference to the returned image which should be cleared + * \returns An open image of type \c MonoImage or NULL on error. + * The caller holds a temporary reference to the returned image which should be cleared * when no longer needed by calling \c mono_image_close. * if NULL, then check the value of \p status for details on the error */ @@ -1926,7 +1926,7 @@ MonoImage * mono_pe_file_open (const char *fname, MonoImageOpenStatus *status) { g_return_val_if_fail (fname != NULL, NULL); - + return do_mono_image_open (mono_alc_get_default (), fname, status, FALSE, TRUE, FALSE); } @@ -1935,13 +1935,13 @@ mono_pe_file_open (const char *fname, MonoImageOpenStatus *status) * \param fname filename that points to the module we want to open * \param status An error condition is returned in this field * \returns an image without loading neither pe or cli data. - * Use mono_image_load_pe_data and mono_image_load_cli_data to load them. + * Use mono_image_load_pe_data and mono_image_load_cli_data to load them. */ MonoImage * mono_image_open_raw (MonoAssemblyLoadContext *alc, const char *fname, MonoImageOpenStatus *status) { g_return_val_if_fail (fname != NULL, NULL); - + return do_mono_image_open (alc, fname, status, FALSE, FALSE, FALSE); } @@ -1980,7 +1980,7 @@ mono_image_fixup_vtable (MonoImage *image) vtfixup = (MonoVTableFixup*) mono_image_rva_map (image, de->rva); if (!vtfixup) return; - + count = de->size / sizeof (MonoVTableFixup); while (count--) { if (!vtfixup->rva || !vtfixup->count) @@ -2039,7 +2039,7 @@ void mono_image_addref (MonoImage *image) { mono_atomic_inc_i32 (&image->ref_count); -} +} void mono_dynamic_stream_reset (MonoDynamicStream* stream) @@ -2068,7 +2068,7 @@ mono_wrapper_caches_free (MonoWrapperCaches *cache) free_hash (cache->delegate_end_invoke_cache); free_hash (cache->delegate_bound_static_invoke_cache); free_hash (cache->runtime_invoke_signature_cache); - + free_hash (cache->delegate_abstract_invoke_cache); free_hash (cache->runtime_invoke_method_cache); @@ -2139,7 +2139,7 @@ mono_image_close_except_pools (MonoImage *image) mono_metadata_update_cleanup_on_close (image); /* - * The caches inside a MonoImage might refer to metadata which is stored in referenced + * The caches inside a MonoImage might refer to metadata which is stored in referenced * assemblies, so we can't release these references in mono_assembly_close () since the * MonoImage might outlive its associated MonoAssembly. */ @@ -2340,7 +2340,7 @@ mono_image_close (MonoImage *image) mono_image_close_finish (image); } -/** +/** * mono_image_strerror: * \param status an code indicating the result from a recent operation * \returns a string describing the error @@ -2415,7 +2415,7 @@ mono_image_walk_resource_tree (MonoCLIImageInfo *info, guint32 res_id, for(i=0; ires_named_entries) + GUINT16_FROM_LE (resource_dir->res_id_entries); res_entries=(MonoPEResourceDirEntry *)(resource_dir+1); - + for(i=0; ich_resources.rva || offset + 4 > ch->ch_resources.size) return NULL; - + data = mono_image_rva_map (image, ch->ch_resources.rva); if (!data) return NULL; @@ -2698,10 +2698,10 @@ mono_image_strong_name_position (MonoImage *image, guint32 *size) * \param size a \c guint32 pointer, or NULL. * * This is used to obtain the public key in the \p image. - * + * * If the image has a public key, and \p size is not NULL, the value * pointed to by size will have the size of the public key. - * + * * \returns NULL if the image does not have a public key, or a pointer * to the public key. */ @@ -2797,7 +2797,7 @@ mono_table_info_get_rows (const MonoTableInfo *table) * Use this routine to get the assembly that owns this image. * \returns the assembly that holds this image. */ -MonoAssembly* +MonoAssembly* mono_image_get_assembly (MonoImage *image) { return image->assembly; @@ -2911,7 +2911,7 @@ GList* mono_g_list_prepend_image (MonoImage *image, GList *list, gpointer data) { GList *new_list; - + new_list = (GList *)mono_image_alloc (image, sizeof (GList)); new_list->data = data; new_list->prev = list ? list->prev : NULL; @@ -2956,7 +2956,7 @@ mono_image_unlock (MonoImage *image) * * LOCKING: Takes the image lock */ -gpointer +gpointer mono_image_property_lookup (MonoImage *image, gpointer subject, guint32 property) { gpointer res; diff --git a/src/mono/mono/metadata/image.h b/src/mono/mono/metadata/image.h index 3049bcc973f32..4b43eefaf05e9 100644 --- a/src/mono/mono/metadata/image.h +++ b/src/mono/mono/metadata/image.h @@ -2,7 +2,7 @@ * \file */ -#ifndef _MONONET_METADATA_IMAGE_H_ +#ifndef _MONONET_METADATA_IMAGE_H_ #define _MONONET_METADATA_IMAGE_H_ #include @@ -88,7 +88,7 @@ MONO_API void* mono_image_lookup_resource (MonoImage *image, uint32_t res_i MONO_API const char* mono_image_get_public_key (MonoImage *image, uint32_t *size); MONO_API const char* mono_image_get_strong_name (MonoImage *image, uint32_t *size); MONO_API uint32_t mono_image_strong_name_position (MonoImage *image, uint32_t *size); -MONO_API void mono_image_add_to_name_cache (MonoImage *image, +MONO_API void mono_image_add_to_name_cache (MonoImage *image, const char *nspace, const char *name, uint32_t idx); MONO_API mono_bool mono_image_has_authenticode_entry (MonoImage *image); diff --git a/src/mono/mono/metadata/jit-info.c b/src/mono/mono/metadata/jit-info.c index 4dd455987afc3..a36af20affb79 100644 --- a/src/mono/mono/metadata/jit-info.c +++ b/src/mono/mono/metadata/jit-info.c @@ -335,7 +335,7 @@ mono_jit_info_table_find_internal (gpointer addr, gboolean try_aot, gboolean all if (ji && ji->is_trampoline && !allow_trampolines) return NULL; - + return ji; } diff --git a/src/mono/mono/metadata/jit-info.h b/src/mono/mono/metadata/jit-info.h index c380a23216c65..bdf6572de173c 100644 --- a/src/mono/mono/metadata/jit-info.h +++ b/src/mono/mono/metadata/jit-info.h @@ -222,7 +222,7 @@ struct _MonoJitInfo { gpointer gc_info; /* Currently only used by SGen */ gpointer seq_points; - + MonoJitExceptionInfo clauses [MONO_ZERO_LEN_ARRAY]; /* There is an optional MonoGenericJitInfo after the clauses */ /* There is an optional MonoTryBlockHoleTableJitInfo after MonoGenericJitInfo clauses*/ @@ -278,7 +278,7 @@ mono_jit_info_get_thunk_info (MonoJitInfo *ji); MonoUnwindJitInfo* mono_jit_info_get_unwind_info (MonoJitInfo *ji); -/* +/* * Installs a new function which is used to return a MonoJitInfo for a method inside * an AOT module. */ diff --git a/src/mono/mono/metadata/loaded-images.c b/src/mono/mono/metadata/loaded-images.c index 821e8f391f08d..9108a297d21f3 100644 --- a/src/mono/mono/metadata/loaded-images.c +++ b/src/mono/mono/metadata/loaded-images.c @@ -117,7 +117,7 @@ mono_loaded_images_remove_image (MonoImage *image) mono_images_unlock (); return proceed; - + } MonoLoadedImages* diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index bc79d38d4eb5b..772c2dc875ebb 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -356,6 +356,18 @@ mono_mem_manager_get_generic (MonoImage **images, int nimages); MonoMemoryManager* mono_mem_manager_merge (MonoMemoryManager *mm1, MonoMemoryManager *mm2); +static inline GSList* +g_slist_prepend_mem_manager (MonoMemoryManager *memory_manager, GSList *list, gpointer data) +{ + GSList *new_list; + + new_list = (GSList *) mono_mem_manager_alloc (memory_manager, sizeof (GSList)); + new_list->data = data; + new_list->next = list; + + return new_list; +} + G_END_DECLS #endif diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c index e0ce3f575ae06..df93bf6864844 100644 --- a/src/mono/mono/metadata/loader.c +++ b/src/mono/mono/metadata/loader.c @@ -53,7 +53,7 @@ #include /* - * This lock protects the hash tables inside MonoImage used by the metadata + * This lock protects the hash tables inside MonoImage used by the metadata * loading functions in class.c and loader.c. * * See domain-internals.h for locking policy in combination with the @@ -65,7 +65,7 @@ static gboolean loader_lock_inited; static gboolean loader_lock_track_ownership; /* - * This TLS variable holds how many times the current thread has acquired the loader + * This TLS variable holds how many times the current thread has acquired the loader * lock. */ static MonoNativeTlsKey loader_lock_nest_id; @@ -156,7 +156,7 @@ mono_loader_unlock (void) * * Set whenever the runtime should track ownership of the loader lock. If set to TRUE, * the mono_loader_lock_is_owned_by_self () can be called to query whenever the current - * thread owns the loader lock. + * thread owns the loader lock. */ void mono_loader_lock_track_ownership (gboolean track) @@ -203,9 +203,9 @@ mono_loader_unlock_if_inited (void) * * Return a cached copy of the memberref signature identified by SIG_IDX. * We use a gpointer since the cache stores both MonoTypes and MonoMethodSignatures. - * A cache is needed since the type/signature parsing routines allocate everything - * from a mempool, so without a cache, multiple requests for the same signature would - * lead to unbounded memory growth. For normal methods/fields this is not a problem + * A cache is needed since the type/signature parsing routines allocate everything + * from a mempool, so without a cache, multiple requests for the same signature would + * lead to unbounded memory growth. For normal methods/fields this is not a problem * since the resulting methods/fields are cached, but inflated methods/fields cannot * be cached. * LOCKING: Acquires the loader lock. @@ -412,7 +412,7 @@ mono_metadata_signature_vararg_match (MonoMethodSignature *sig1, MonoMethodSigna sig1->sentinelpos != sig2->sentinelpos) return FALSE; - for (i = 0; i < sig1->sentinelpos; i++) { + for (i = 0; i < sig1->sentinelpos; i++) { MonoType *p1 = sig1->params[i]; MonoType *p2 = sig2->params[i]; @@ -465,7 +465,7 @@ find_method_in_class (MonoClass *klass, const char *name, const char *qname, con if (method) { other_sig = mono_method_signature_checked (method, error); if (!is_ok (error)) //bail out if we hit a loader error - return NULL; + return NULL; if (other_sig && (sig->call_convention != MONO_CALL_VARARG) && mono_metadata_signature_equal (sig, other_sig)) return method; } @@ -500,7 +500,7 @@ find_method_in_class (MonoClass *klass, const char *name, const char *qname, con (name && !strcmp (m->name, name)))) continue; msig = mono_method_signature_checked (m, error); - if (!is_ok (error)) //bail out if we hit a loader error + if (!is_ok (error)) //bail out if we hit a loader error return NULL; if (!msig) @@ -570,7 +570,7 @@ find_method (MonoClass *in_class, MonoClass *ic, const char* name, MonoMethodSig MonoClass *in_ic = in_class_interfaces_packed [i]; MonoClass *from_ic = from_class_interfaces_packed [i]; char *ic_qname, *ic_fqname, *ic_class_name; - + ic_class_name = mono_type_get_name_full (m_class_get_byval_arg (in_ic), MONO_TYPE_NAME_FORMAT_IL); ic_qname = g_strconcat (ic_class_name, ".", name, (const char*)NULL); const char *in_ic_name_space = m_class_get_name_space (in_ic); @@ -598,7 +598,7 @@ find_method (MonoClass *in_class, MonoClass *ic, const char* name, MonoMethodSig //we did not find the method if (!result && is_ok (error)) mono_error_set_method_missing (error, initial_class, name, sig, NULL); - + out: g_free (class_name); g_free (fqname); @@ -677,7 +677,7 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context, M { size_t locals_size = sizeof (gpointer) * header->num_locals; size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause); - size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size; + size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size; MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size); res->num_locals = header->num_locals; res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ; @@ -1097,8 +1097,8 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, container = mono_class_try_get_generic_container (klass); - /* - * load_generic_params does a binary search so only call it if the method + /* + * load_generic_params does a binary search so only call it if the method * is generic. */ if (*sig & 0x10) { @@ -1293,7 +1293,7 @@ get_method_constrained (MonoImage *image, MonoMethod *method, MonoClass *constra mono_error_set_for_class_failure (error, constrained_class); return NULL; } - + /* Get the slot of the method in the interface. Then get the * interface base in constrained_class */ int itf_slot = mono_method_get_vtable_index (method); @@ -1366,20 +1366,20 @@ mono_free_method (MonoMethod *method) return; MONO_PROFILER_RAISE (method_free, (method)); - + /* FIXME: This hack will go away when the profiler will support freeing methods */ if (G_UNLIKELY (mono_profiler_installed ())) return; - + if (method->signature) { - /* + /* * FIXME: This causes crashes because the types inside signatures and * locals are shared. */ /* mono_metadata_free_method_signature (method->signature); */ /* g_free (method->signature); */ } - + if (method_is_dynamic (method)) { MonoMethodWrapper *mw = (MonoMethodWrapper*)method; int i; @@ -1438,7 +1438,7 @@ mono_method_get_param_names (MonoMethod *method, const char **names) MonoImage *klass_image = m_class_get_image (klass); if (image_is_dynamic (klass_image)) { - MonoReflectionMethodAux *method_aux = + MonoReflectionMethodAux *method_aux = (MonoReflectionMethodAux *)g_hash_table_lookup ( ((MonoDynamicImage*)m_class_get_image (method->klass))->method_aux_hash, method); if (method_aux && method_aux->param_names) { @@ -1535,7 +1535,7 @@ mono_method_get_marshal_info (MonoMethod *method, MonoMarshalSpec **mspecs) mspecs [i] = NULL; if (image_is_dynamic (m_class_get_image (method->klass))) { - MonoReflectionMethodAux *method_aux = + MonoReflectionMethodAux *method_aux = (MonoReflectionMethodAux *)g_hash_table_lookup ( ((MonoDynamicImage*)m_class_get_image (method->klass))->method_aux_hash, method); if (method_aux && method_aux->param_marshall) { @@ -1601,7 +1601,7 @@ mono_method_has_marshal_info (MonoMethod *method) guint32 idx; if (image_is_dynamic (m_class_get_image (method->klass))) { - MonoReflectionMethodAux *method_aux = + MonoReflectionMethodAux *method_aux = (MonoReflectionMethodAux *)g_hash_table_lookup ( ((MonoDynamicImage*)m_class_get_image (method->klass))->method_aux_hash, method); MonoMarshalSpec **dyn_specs = method_aux->param_marshall; @@ -1785,7 +1785,7 @@ mono_method_signature_checked_slow (MonoMethod *m, MonoError *error) MonoMethodSignature *signature = NULL, *sig2; guint32 sig_offset; - /* We need memory barriers below because of the double-checked locking pattern */ + /* We need memory barriers below because of the double-checked locking pattern */ error_init (error); @@ -2041,7 +2041,7 @@ mono_method_get_header_internal (MonoMethod *method, MonoError *error) return mw->header; } - /* + /* * We don't need locks here: the new header is allocated from malloc memory * and is not stored anywhere in the runtime, the user needs to free it. */ diff --git a/src/mono/mono/metadata/loader.h b/src/mono/mono/metadata/loader.h index 42c89288fcc6e..c1468257867a7 100644 --- a/src/mono/mono/metadata/loader.h +++ b/src/mono/mono/metadata/loader.h @@ -25,7 +25,7 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoMethod * mono_get_method_constrained (MonoImage *image, uint32_t token, MonoClass *constrained_class, MonoGenericContext *context, MonoMethod **cil_method); -MONO_API void +MONO_API void mono_free_method (MonoMethod *method); MONO_API MONO_RT_EXTERNAL_ONLY MonoMethodSignature* diff --git a/src/mono/mono/metadata/lock-tracer.c b/src/mono/mono/metadata/lock-tracer.c index 302c29f2c9aa8..13283f13de5d0 100644 --- a/src/mono/mono/metadata/lock-tracer.c +++ b/src/mono/mono/metadata/lock-tracer.c @@ -4,7 +4,7 @@ * * Authors: * Rodrigo Kumpera (rkumpera@novell.com) - * + * */ #include @@ -29,7 +29,7 @@ /* * This is a very simple lock trace implementation. It can be used to verify that the runtime is * correctly following all locking rules. - * + * * To log more kind of locks just do the following: * - add an entry into the RuntimeLocks enum * - change mono_os_mutex_lock(mutex) to mono_locks_os_acquire (mutex, LockName) @@ -44,7 +44,7 @@ * - Enable tracing of more runtime locks * - Add lock check assertions (must_not_hold_any_lock_but, must_hold_lock, etc) * This should be used to verify methods that expect that a given lock is held at entrypoint, for example. - * + * * To use the trace, define LOCK_TRACER in lock-trace.h and when running mono define MONO_ENABLE_LOCK_TRACER. * This will produce a locks.ZZZ where ZZZ is the pid of the mono process. * Use the decoder to verify the result. diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c index b8a12826aac4b..8061e75fc778e 100644 --- a/src/mono/mono/metadata/marshal-ilgen.c +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -348,7 +348,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv /* create a new array */ mono_mb_emit_ldloc (mb, 1); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); - mono_mb_emit_op (mb, CEE_NEWARR, eklass); + mono_mb_emit_op (mb, CEE_NEWARR, eklass); mono_mb_emit_byte (mb, CEE_STIND_REF); if (m_class_is_blittable (eklass)) { @@ -360,7 +360,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 0); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize); mono_mb_emit_byte (mb, CEE_PREFIX1); - mono_mb_emit_byte (mb, CEE_CPBLK); + mono_mb_emit_byte (mb, CEE_CPBLK); } else { int array_var, src_var, dst_var, index_var; @@ -375,7 +375,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 1); mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_stloc (mb, array_var); - + /* save the old src pointer */ mono_mb_emit_ldloc (mb, 0); mono_mb_emit_stloc (mb, src_var); @@ -412,7 +412,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_branch_label (mb, CEE_BR, label2); mono_mb_patch_branch (mb, label3); - + /* restore the old src pointer */ mono_mb_emit_ldloc (mb, src_var); mono_mb_emit_stloc (mb, 0); @@ -428,7 +428,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv /* create a new array */ mono_mb_emit_ldloc (mb, 1); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); - mono_mb_emit_op (mb, CEE_NEWARR, eclass); + mono_mb_emit_op (mb, CEE_NEWARR, eclass); mono_mb_emit_byte (mb, CEE_STIND_REF); mono_mb_emit_ldloc (mb, 1); @@ -438,7 +438,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_icall (mb, mono_byvalarray_to_byte_array); break; } - case MONO_MARSHAL_CONV_STR_BYVALSTR: + case MONO_MARSHAL_CONV_STR_BYVALSTR: if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) { mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); @@ -449,7 +449,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 0); mono_mb_emit_icall (mb, ves_icall_string_new_wrapper); } - mono_mb_emit_byte (mb, CEE_STIND_REF); + mono_mb_emit_byte (mb, CEE_STIND_REF); break; case MONO_MARSHAL_CONV_STR_BYVALWSTR: if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) { @@ -462,8 +462,8 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 0); mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16); } - mono_mb_emit_byte (mb, CEE_STIND_REF); - break; + mono_mb_emit_byte (mb, CEE_STIND_REF); + break; case MONO_MARSHAL_CONV_STR_ANSIBSTR: case MONO_MARSHAL_CONV_STR_TBSTR: @@ -487,13 +487,13 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv MonoType *int_type = mono_get_int_type (); src_var = mono_mb_add_local (mb, int_type); dst_var = mono_mb_add_local (mb, int_type); - + /* *dst = new object */ mono_mb_emit_ldloc (mb, 1); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); mono_mb_emit_byte (mb, CEE_STIND_REF); - + /* save the old src pointer */ mono_mb_emit_ldloc (mb, 0); mono_mb_emit_stloc (mb, src_var); @@ -506,10 +506,10 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_byte (mb, CEE_ADD); - mono_mb_emit_stloc (mb, 1); + mono_mb_emit_stloc (mb, 1); emit_struct_conv (mb, klass, TRUE); - + /* restore the old src pointer */ mono_mb_emit_ldloc (mb, src_var); mono_mb_emit_stloc (mb, 0); @@ -550,7 +550,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv * to change the SafeHandle value. If the value is changed, * we should issue a diagnostic exception (NotSupportedException) * that informs the user that changes to handles in unmanaged code - * is not supported. + * is not supported. * * Since we currently have no access to the original * SafeHandle that was used during the marshalling, @@ -559,15 +559,15 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv */ break; } - + case MONO_MARSHAL_CONV_HANDLEREF: { /* - * Passing HandleRefs in a struct that is ref()ed does not + * Passing HandleRefs in a struct that is ref()ed does not * copy the values back to the HandleRef */ break; } - + case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY: default: { char *msg = g_strdup_printf ("marshaling conversion %d not implemented", conv); @@ -837,12 +837,12 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op)); mono_mb_emit_byte (mb, stind_op); break; - case MONO_MARSHAL_CONV_STR_BYVALSTR: + case MONO_MARSHAL_CONV_STR_BYVALSTR: case MONO_MARSHAL_CONV_STR_BYVALWSTR: { g_assert (mspec); mono_mb_emit_ldloc (mb, 1); /* dst */ - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); /* src String */ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL)); @@ -872,12 +872,12 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv if (m_class_is_blittable (eklass)) { mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoArray, vector)); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize); mono_mb_emit_byte (mb, CEE_PREFIX1); - mono_mb_emit_byte (mb, CEE_CPBLK); + mono_mb_emit_byte (mb, CEE_CPBLK); } else { int array_var, src_var, dst_var, index_var; guint32 label2, label3; @@ -889,7 +889,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv dst_var = mono_mb_add_local (mb, int_type); /* set array_var */ - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_stloc (mb, array_var); @@ -929,7 +929,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_branch_label (mb, CEE_BR, label2); mono_mb_patch_branch (mb, label3); - + /* restore the old src pointer */ mono_mb_emit_ldloc (mb, src_var); mono_mb_emit_stloc (mb, 0); @@ -947,7 +947,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); mono_mb_emit_icall (mb, mono_array_to_byte_byvalarray); @@ -960,11 +960,11 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv MonoType *int_type = mono_get_int_type (); src_var = mono_mb_add_local (mb, int_type); dst_var = mono_mb_add_local (mb, int_type); - + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_I); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); - + /* save the old src pointer */ mono_mb_emit_ldloc (mb, 0); mono_mb_emit_stloc (mb, src_var); @@ -974,13 +974,13 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv /* src = pointer to object data */ mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_byte (mb, CEE_ADD); - mono_mb_emit_stloc (mb, 0); + mono_mb_emit_stloc (mb, 0); emit_struct_conv (mb, mono_class_from_mono_type_internal (type), FALSE); - + /* restore the old src pointer */ mono_mb_emit_ldloc (mb, src_var); mono_mb_emit_stloc (mb, 0); @@ -1002,13 +1002,13 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv case MONO_MARSHAL_CONV_SAFEHANDLE: { int pos; - + mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_I); pos = mono_mb_emit_branch (mb, CEE_BRTRUE); mono_mb_emit_exception (mb, "ArgumentNullException", NULL); mono_mb_patch_branch (mb, pos); - + /* Pull the handle field from SafeHandle */ mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); @@ -1028,7 +1028,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_byte (mb, CEE_STIND_I); break; } - + default: { g_error ("marshalling conversion %d not implemented", conv); } @@ -1143,11 +1143,11 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje } if (klass != mono_class_try_get_safehandle_class ()){ - /* - * FIXME: Should really check for usize==0 and msize>0, but we apply + /* + * FIXME: Should really check for usize==0 and msize>0, but we apply * the layout to the managed structure as well. */ - + if (mono_class_is_explicit_layout (klass) && (usize == 0)) { if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) || ((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type)))) @@ -1156,7 +1156,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje mono_type_full_name (m_class_get_byval_arg (klass))); } } - + switch (conv) { case MONO_MARSHAL_CONV_NONE: { int t; @@ -1223,7 +1223,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje MonoType *int_type = mono_get_int_type (); src_var = mono_mb_add_local (mb, int_type); dst_var = mono_mb_add_local (mb, int_type); - + /* save the old src pointer */ mono_mb_emit_ldloc (mb, 0); mono_mb_emit_stloc (mb, src_var); @@ -1269,7 +1269,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje break; } - default: + default: g_warning ("marshaling type %02x not implemented", ftype->type); g_assert_not_reached (); } @@ -1289,7 +1289,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje mono_mb_emit_ldloc (mb, 1); mono_mb_emit_stloc (mb, dst_var); - if (to_object) + if (to_object) emit_ptr_to_object_conv (mb, ftype, conv, info->fields [i].mspec); else emit_object_to_ptr_conv (mb, ftype, conv, info->fields [i].mspec); @@ -1309,7 +1309,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje } else { mono_mb_emit_add_to_local (mb, 0, msize); mono_mb_emit_add_to_local (mb, 1, usize); - } + } } } @@ -1360,7 +1360,7 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, MonoJitICallId che mono_mb_patch_branch (mb, pos_noex); mono_mb_emit_byte (mb, CEE_POP); - + mono_mb_patch_branch (mb, pos_noabort); } @@ -1370,7 +1370,7 @@ emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb) // FIXME Put a boolean in MonoMethodBuilder instead. if (strstr (mb->name, "mono_thread_interruption_checkpoint")) return; - + emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_interruption_checkpoint); } @@ -1452,10 +1452,10 @@ mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type) case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: /* nothing to do */ break; case MONO_TYPE_U1: @@ -1580,7 +1580,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, mono_mb_emit_byte (mb, mono_type_to_ldind (sig->params [i])); break; case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: + case MONO_TYPE_CLASS: case MONO_TYPE_ARRAY: case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: @@ -1618,7 +1618,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, g_assert_not_reached (); } } - + if (virtual_) { mono_mb_emit_op (mb, CEE_CALLVIRT, method); } else if (need_direct_wrapper) { @@ -1676,7 +1676,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (sig->ret)); break; case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: + case MONO_TYPE_CLASS: case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: case MONO_TYPE_OBJECT: @@ -1697,12 +1697,12 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, for (i = 0; i < sig->param_count; i++) { MonoType *t = sig->params [i]; - /* + /* * Box the result and put it back into the array, the caller will have * to obtain it from there. */ if (m_type_is_byref (t) && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) { - mono_mb_emit_ldarg (mb, 1); + mono_mb_emit_ldarg (mb, 1); mono_mb_emit_icon (mb, TARGET_SIZEOF_VOID_P * i); mono_mb_emit_byte (mb, CEE_ADD); @@ -1771,7 +1771,7 @@ emit_runtime_invoke_body_ilgen (MonoMethodBuilder *mb, const char **param_names, clause->handler_offset = mono_mb_get_label (mb); /* handler code */ - mono_mb_emit_stloc (mb, loc_exc); + mono_mb_emit_stloc (mb, loc_exc); mono_mb_emit_byte (mb, CEE_LDARG_2); mono_mb_emit_ldloc (mb, loc_exc); mono_mb_emit_byte (mb, CEE_STIND_REF); @@ -1812,7 +1812,7 @@ emit_runtime_invoke_dynamic_ilgen (MonoMethodBuilder *mb) /* cond set *exc to null */ mono_mb_emit_byte (mb, CEE_LDARG_1); mono_mb_emit_byte (mb, CEE_BRFALSE_S); - mono_mb_emit_byte (mb, 3); + mono_mb_emit_byte (mb, 3); mono_mb_emit_byte (mb, CEE_LDARG_1); mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_byte (mb, CEE_STIND_REF); @@ -1832,7 +1832,7 @@ emit_runtime_invoke_dynamic_ilgen (MonoMethodBuilder *mb) /* filter code */ clause->data.filter_offset = mono_mb_get_label (mb); - + mono_mb_emit_byte (mb, CEE_POP); mono_mb_emit_byte (mb, CEE_LDARG_1); mono_mb_emit_byte (mb, CEE_LDC_I4_0); @@ -1846,7 +1846,7 @@ emit_runtime_invoke_dynamic_ilgen (MonoMethodBuilder *mb) /* handler code */ /* store exception */ mono_mb_emit_stloc (mb, 1); - + mono_mb_emit_byte (mb, CEE_LDARG_1); mono_mb_emit_ldloc (mb, 1); mono_mb_emit_byte (mb, CEE_STIND_REF); @@ -1991,6 +1991,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi gboolean func_param = (flags & EMIT_NATIVE_WRAPPER_FUNC_PARAM) != 0; gboolean func_param_unboxed = (flags & EMIT_NATIVE_WRAPPER_FUNC_PARAM_UNBOXED) != 0; gboolean skip_gc_trans = (flags & EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS) != 0; + gboolean runtime_marshalling_enabled = (flags & EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED) != 0; EmitMarshalContext m; MonoMethodSignature *csig; MonoClass *klass; @@ -2001,6 +2002,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi GCSafeTransitionBuilder gc_safe_transition_builder; memset (&m, 0, sizeof (m)); + m.runtime_marshalling_enabled = runtime_marshalling_enabled; m.mb = mb; m.sig = sig; m.piinfo = piinfo; @@ -2016,6 +2018,8 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi } csig = mono_metadata_signature_dup_full (get_method_image (mb->method), sig); csig->pinvoke = 1; + if (!runtime_marshalling_enabled) + csig->marshalling_disabled = 1; m.csig = csig; m.image = image; @@ -2102,6 +2106,10 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi csig->ret = int_type; } + // Check if SetLastError usage is valid early so we don't try to throw an exception after transitioning GC modes. + if (piinfo && (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) && !m.runtime_marshalling_enabled) + mono_mb_emit_exception_marshal_directive(mb, g_strdup("Setting SetLastError=true is not supported when runtime marshalling is disabled.")); + /* we first do all conversions */ tmp_locals = g_newa (int, sig->param_count); m.orig_conv_args = g_newa (int, sig->param_count + 1); @@ -2121,7 +2129,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi for (i = 0; i < sig->param_count; i++) { mono_emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_PUSH); - } + } /* call the native method */ if (func_param) { @@ -2229,7 +2237,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi break; case MONO_TYPE_TYPEDBYREF: default: - g_warning ("return type 0x%02x unknown", sig->ret->type); + g_warning ("return type 0x%02x unknown", sig->ret->type); g_assert_not_reached (); } } @@ -2237,8 +2245,8 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi mono_mb_emit_stloc (mb, 3); } - /* - * Need to call this after converting the result since MONO_VTADDR needs + /* + * Need to call this after converting the result since MONO_VTADDR needs * to be adjacent to the call instruction. */ if (check_exceptions) @@ -2346,7 +2354,7 @@ emit_castclass_ilgen (MonoMethodBuilder *mb) const int class_arg_position = TYPECHECK_CLASS_ARG_POS; const int cache_arg_position = TYPECHECK_CACHE_ARG_POS; - generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position, + generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position, &return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb); invalid_cast_pos = mono_mb_emit_branch (mb, CEE_BRFALSE); @@ -2374,7 +2382,7 @@ emit_isinst_ilgen (MonoMethodBuilder *mb) const int class_arg_position = TYPECHECK_CLASS_ARG_POS; const int cache_arg_position = TYPECHECK_CACHE_ARG_POS; - generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position, + generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position, &return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb); // Return the object gotten via the slow path. mono_mb_emit_byte (mb, CEE_RET); @@ -2425,8 +2433,8 @@ load_value_class (MonoMethodBuilder *mb, int vklass) static int emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -2517,7 +2525,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, dest_ptr); /* Emit marshalling loop */ - index_var = mono_mb_add_local (mb, int_type); + index_var = mono_mb_add_local (mb, int_type); mono_mb_emit_byte (mb, CEE_LDC_I4_0); mono_mb_emit_stloc (mb, index_var); label2 = mono_mb_get_label (mb); @@ -2553,7 +2561,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_add_to_local (mb, index_var, 1); mono_mb_emit_add_to_local (mb, dest_ptr, esize); - + mono_mb_emit_branch_label (mb, CEE_BR, label2); mono_mb_patch_branch (mb, label3); @@ -2629,7 +2637,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, src_ptr); /* Emit marshalling loop */ - index_var = mono_mb_add_local (mb, int_type); + index_var = mono_mb_add_local (mb, int_type); mono_mb_emit_byte (mb, CEE_LDC_I4_0); mono_mb_emit_stloc (mb, index_var); label2 = mono_mb_get_label (mb); @@ -2713,7 +2721,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_patch_branch (mb, label3); } #endif - + if (m_class_is_blittable (eklass)) { /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */ @@ -2746,7 +2754,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, int index_var, src_ptr, esize, param_num, num_elem; MonoMarshalConv conv; gboolean is_string = FALSE; - + conv_arg = mono_mb_add_local (mb, object_type); *conv_arg_type = int_type; @@ -2860,8 +2868,8 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, src_ptr); /* Create managed array */ - /* - * The LPArray marshalling spec says that sometimes param_num starts + /* + * The LPArray marshalling spec says that sometimes param_num starts * from 1, sometimes it starts from 0. But MS seems to allways start * from 0. */ @@ -2938,7 +2946,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_patch_branch (mb, label1); mono_mb_patch_branch (mb, label3); #endif - + break; } case MARSHAL_ACTION_MANAGED_CONV_OUT: { @@ -2950,7 +2958,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (!spec) /* Already handled in CONV_IN */ break; - + /* These are already checked in CONV_IN */ g_assert (!m_type_is_byref (t)); g_assert (spec->native == MONO_NATIVE_LPARRAY); @@ -3014,7 +3022,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_icon (mb, esize); mono_mb_emit_byte (mb, CEE_MUL); mono_mb_emit_byte (mb, CEE_PREFIX1); - mono_mb_emit_byte (mb, CEE_CPBLK); + mono_mb_emit_byte (mb, CEE_CPBLK); mono_mb_patch_branch (mb, label1); break; } @@ -3070,7 +3078,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, int index_var, src, dest, esize; MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID; gboolean is_string = FALSE; - + g_assert (!m_type_is_byref (t)); mono_marshal_load_type_info (eklass); @@ -3092,7 +3100,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, src = mono_mb_add_local (mb, object_type); dest = mono_mb_add_local (mb, int_type); - + mono_mb_emit_stloc (mb, src); mono_mb_emit_ldloc (mb, src); mono_mb_emit_stloc (mb, 3); @@ -3167,8 +3175,8 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } static int -emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -3200,8 +3208,8 @@ emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } static int -emit_marshal_scalar_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +emit_marshal_scalar_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -3224,8 +3232,8 @@ emit_marshal_scalar_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -3244,7 +3252,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, else *conv_arg_type = local_type; conv_arg = mono_mb_add_local (mb, local_type); - + mono_mb_emit_ldarg (mb, argnum); if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I1); @@ -3264,7 +3272,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); - + label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_byte (mb, CEE_LDC_I4_1); @@ -3306,7 +3314,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); - + /* Check null */ if (m_type_is_byref (t)) { label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); @@ -3320,7 +3328,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, conv_arg); mono_mb_patch_branch (mb, label_false); - if (m_type_is_byref (t)) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, label_null); break; } @@ -3346,7 +3354,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; } } - + /* Check null */ mono_mb_emit_ldarg (mb, argnum); label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); @@ -3374,8 +3382,8 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } static int -emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -3815,50 +3823,50 @@ emit_stelemref_ilgen (MonoMethodBuilder *mb) guint32 copy_pos; int aklass, vklass; int array_slot_addr; - + MonoType *int_type = mono_get_int_type (); MonoType *object_type_byref = mono_class_get_byref_type (mono_defaults.object_class); aklass = mono_mb_add_local (mb, int_type); vklass = mono_mb_add_local (mb, int_type); array_slot_addr = mono_mb_add_local (mb, object_type_byref); - + /* the method: if (!value) goto store; - + aklass = array->vtable->m_class_get_element_class (klass); vklass = value->vtable->klass; - + if (vklass->idepth < aklass->idepth) goto long; - + if (vklass->supertypes [aklass->idepth - 1] != aklass) goto long; - + store: *array_slot_addr = value; return; - + long: if (mono_object_isinst (value, aklass)) goto store; - + throw new ArrayTypeMismatchException (); */ - + /* ldelema (implicit bound check) */ mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldarg (mb, 1); mono_mb_emit_op (mb, CEE_LDELEMA, mono_defaults.object_class); mono_mb_emit_stloc (mb, array_slot_addr); - + /* if (!value) goto do_store */ mono_mb_emit_ldarg (mb, 2); b1 = mono_mb_emit_branch (mb, CEE_BRFALSE); - + /* aklass = array->vtable->klass->element_class */ mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable)); @@ -3868,7 +3876,7 @@ emit_stelemref_ilgen (MonoMethodBuilder *mb) mono_mb_emit_ldflda (mb, m_class_offsetof_element_class ()); mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, aklass); - + /* vklass = value->vtable->klass */ mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable)); @@ -3876,23 +3884,23 @@ emit_stelemref_ilgen (MonoMethodBuilder *mb) mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoVTable, klass)); mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, vklass); - + /* if (vklass->idepth < aklass->idepth) goto failue */ mono_mb_emit_ldloc (mb, vklass); mono_mb_emit_ldflda (mb, m_class_offsetof_idepth ()); mono_mb_emit_byte (mb, CEE_LDIND_U2); - + mono_mb_emit_ldloc (mb, aklass); mono_mb_emit_ldflda (mb, m_class_offsetof_idepth ()); mono_mb_emit_byte (mb, CEE_LDIND_U2); - + b2 = mono_mb_emit_branch (mb, CEE_BLT_UN); - + /* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */ mono_mb_emit_ldloc (mb, vklass); mono_mb_emit_ldflda (mb, m_class_offsetof_supertypes ()); mono_mb_emit_byte (mb, CEE_LDIND_I); - + mono_mb_emit_ldloc (mb, aklass); mono_mb_emit_ldflda (mb, m_class_offsetof_idepth ()); mono_mb_emit_byte (mb, CEE_LDIND_U2); @@ -3902,32 +3910,32 @@ emit_stelemref_ilgen (MonoMethodBuilder *mb) mono_mb_emit_byte (mb, CEE_MUL); mono_mb_emit_byte (mb, CEE_ADD); mono_mb_emit_byte (mb, CEE_LDIND_I); - + mono_mb_emit_ldloc (mb, aklass); - + b3 = mono_mb_emit_branch (mb, CEE_BNE_UN); - + copy_pos = mono_mb_get_label (mb); /* do_store */ mono_mb_patch_branch (mb, b1); mono_mb_emit_ldloc (mb, array_slot_addr); mono_mb_emit_ldarg (mb, 2); mono_mb_emit_byte (mb, CEE_STIND_REF); - + mono_mb_emit_byte (mb, CEE_RET); - + /* the hard way */ mono_mb_patch_branch (mb, b2); mono_mb_patch_branch (mb, b3); - + mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldloc (mb, aklass); mono_mb_emit_icall (mb, mono_object_isinst_icall); - + b4 = mono_mb_emit_branch (mb, CEE_BRTRUE); mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4)); mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL); - + mono_mb_emit_byte (mb, CEE_RET); } @@ -4157,7 +4165,7 @@ emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature mono_mb_emit_op (mb, CEE_MONO_CALLI_EXTRA_ARG, sig); mono_mb_emit_byte (mb, CEE_RET); } - + /* else [target == null] call this->method_ptr static */ mono_mb_patch_branch (mb, pos0); } @@ -4364,7 +4372,7 @@ emit_unbox_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method) { MonoMethodSignature *sig = mono_method_signature_internal (method); - mono_mb_emit_ldarg (mb, 0); + mono_mb_emit_ldarg (mb, 0); mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_byte (mb, CEE_ADD); for (int i = 0; i < sig->param_count; ++i) @@ -4544,8 +4552,8 @@ emit_marshal_custom_get_instance (MonoMethodBuilder *mb, MonoClass *klass, MonoM static int emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { ERROR_DECL (error); @@ -4648,7 +4656,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); emit_marshal_custom_get_instance (mb, mklass, spec); - + mono_mb_emit_ldarg (mb, argnum); if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); @@ -4710,7 +4718,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_RESULT: loc1 = mono_mb_add_local (mb, int_type); - + mono_mb_emit_stloc (mb, 3); mono_mb_emit_ldloc (mb, 3); @@ -4749,11 +4757,11 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); emit_marshal_custom_get_instance (mb, mklass, spec); - + mono_mb_emit_ldarg (mb, argnum); if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); - + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); mono_mb_emit_stloc (mb, conv_arg); @@ -4764,9 +4772,9 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, g_assert (!m_type_is_byref (t)); loc1 = mono_mb_add_local (mb, object_type); - + mono_mb_emit_stloc (mb, 3); - + mono_mb_emit_ldloc (mb, 3); mono_mb_emit_stloc (mb, loc1); @@ -4805,7 +4813,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* Call CleanUpManagedData */ emit_marshal_custom_get_instance (mb, mklass, spec); - + mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); @@ -4820,8 +4828,8 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -4866,8 +4874,8 @@ emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -4916,15 +4924,15 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; conv_arg = mono_mb_add_local (mb, int_type); - + /* store the address of the source into local variable 0 */ if (m_type_is_byref (t)) mono_mb_emit_ldarg (mb, argnum); else mono_mb_emit_ldarg_addr (mb, argnum); - + mono_mb_emit_stloc (mb, 0); - + /* allocate space for the native struct and * store the address into local variable 1 (dest) */ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); @@ -4976,7 +4984,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { mono_mb_emit_ldarg (mb, argnum); break; - } + } mono_mb_emit_ldloc (mb, conv_arg); if (!m_type_is_byref (t)) { mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); @@ -5029,7 +5037,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } emit_struct_free (mb, klass, conv_arg); - + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, pos); break; @@ -5048,7 +5056,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* set dst_ptr */ mono_mb_emit_ldloc_addr (mb, 3); mono_mb_emit_stloc (mb, 1); - + /* emit valuetype conversion code */ emit_struct_conv (mb, klass, TRUE); break; @@ -5064,7 +5072,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (t->attrs & PARAM_ATTRIBUTE_OUT) break; - if (m_type_is_byref (t)) + if (m_type_is_byref (t)) mono_mb_emit_ldarg (mb, argnum); else mono_mb_emit_ldarg_addr (mb, argnum); @@ -5073,7 +5081,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (m_type_is_byref (t)) { mono_mb_emit_ldloc (mb, 0); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); - } + } mono_mb_emit_ldloc_addr (mb, conv_arg); mono_mb_emit_stloc (mb, 1); @@ -5115,11 +5123,11 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, m->retobj_var = 0; break; } - + /* load pointer to returned value type */ g_assert (m->vtaddr_var); mono_mb_emit_ldloc (mb, m->vtaddr_var); - + /* store the address of the source into local variable 0 */ mono_mb_emit_stloc (mb, 0); /* allocate space for the native struct and @@ -5155,8 +5163,8 @@ emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv) static int emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -5176,7 +5184,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, CEE_LDIND_I); } else { mono_mb_emit_ldarg (mb, argnum); } @@ -5213,7 +5221,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MONO_STATIC_POINTER_INIT_END (MonoMethod, m) - /* + /* * Have to allocate a new string with the same length as the original, and * copy the contents of the buffer pointed to by CONV_ARG into it. */ @@ -5221,7 +5229,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_managed_call (mb, m, NULL); mono_mb_emit_icall (mb, mono_string_new_len_wrapper); mono_mb_emit_byte (mb, CEE_STIND_REF); @@ -5249,7 +5257,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_RESULT: mono_mb_emit_stloc (mb, 0); - + conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free); if (conv == MONO_MARSHAL_CONV_INVALID) { char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); @@ -5319,8 +5327,8 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int -emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -5340,7 +5348,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); pos = mono_mb_emit_branch (mb, CEE_BRTRUE); mono_mb_emit_exception (mb, "ArgumentNullException", NULL); - + mono_mb_patch_branch (mb, pos); /* Create local to hold the ref parameter to DangerousAddRef */ @@ -5391,7 +5399,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_PUSH: if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); - else + else mono_mb_emit_ldloc (mb, conv_arg); break; @@ -5417,7 +5425,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (is_out (t)) { ERROR_DECL (local_error); MonoMethod *ctor; - + /* * If the SafeHandle was marshalled on input we can skip the marshalling on * output if the handle value is identical. @@ -5431,7 +5439,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* * Create an empty SafeHandle (of correct derived type). - * + * * FIXME: If an out-of-memory situation or exception happens here we will * leak the handle. We should move the allocation of the SafeHandle to the * input marshalling code to prevent that. @@ -5468,12 +5476,12 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } break; } - + case MARSHAL_ACTION_CONV_RESULT: { ERROR_DECL (error); MonoMethod *ctor = NULL; int intptr_handle_slot; - + if (mono_class_is_abstract (t->data.klass)) { mono_mb_emit_byte (mb, CEE_POP); mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract")); @@ -5502,11 +5510,11 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_STIND_I); break; } - + case MARSHAL_ACTION_MANAGED_CONV_IN: fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); break; - + case MARSHAL_ACTION_MANAGED_CONV_OUT: fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); break; @@ -5522,8 +5530,8 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int -emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -5538,7 +5546,7 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); mono_mb_emit_exception_marshal_directive (mb, msg); break; - } + } mono_mb_emit_ldarg_addr (mb, argnum); mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle)); mono_mb_emit_byte (mb, CEE_ADD); @@ -5555,17 +5563,17 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* no resource release required */ break; } - + case MARSHAL_ACTION_CONV_RESULT: { char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); mono_mb_emit_exception_marshal_directive (mb, msg); break; } - + case MARSHAL_ACTION_MANAGED_CONV_IN: fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); break; - + case MARSHAL_ACTION_MANAGED_CONV_OUT: fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); break; @@ -5582,8 +5590,8 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { MonoMethodBuilder *mb = m->mb; @@ -5621,7 +5629,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, spec); MonoMarshalConv conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec); -#if 0 +#if 0 if (m_type_is_byref (t)) { if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented."); @@ -5668,7 +5676,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (t->attrs & PARAM_ATTRIBUTE_OUT) break; - mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, CEE_LDIND_I); } else { @@ -5676,7 +5684,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_OBJADDR); } - + /* store the address of the source into local variable 0 */ mono_mb_emit_stloc (mb, 0); mono_mb_emit_ldloc (mb, 0); @@ -5795,7 +5803,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_byte (mb, CEE_ADD); mono_mb_emit_stloc (mb, 1); - + /* src = tmp_locals [i] */ mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_stloc (mb, 0); @@ -5807,7 +5815,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, emit_struct_free (mb, klass, conv_arg); if (m->orig_conv_args [argnum]) { - /* + /* * If the native function changed the pointer, then free * the original structure plus the new pointer. */ @@ -5857,35 +5865,35 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } else { /* set src */ mono_mb_emit_stloc (mb, 0); - + /* Make a copy since emit_conv modifies local 0 */ loc = mono_mb_add_local (mb, int_type); mono_mb_emit_ldloc (mb, 0); mono_mb_emit_stloc (mb, loc); - + mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_stloc (mb, 3); - + mono_mb_emit_ldloc (mb, 0); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); - + /* allocate result object */ - + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); mono_mb_emit_stloc (mb, 3); - + /* set dst */ - + mono_mb_emit_ldloc (mb, 3); mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_stloc (mb, 1); - + /* emit conversion code */ emit_struct_conv (mb, klass, TRUE); - + emit_struct_free (mb, klass, loc); - + /* Free the pointer allocated by unmanaged code */ mono_mb_emit_ldloc (mb, loc); mono_mb_emit_icall (mb, mono_marshal_free); @@ -5949,7 +5957,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_patch_branch (mb, pos2); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, CEE_LDIND_I); - } + } mono_mb_emit_stloc (mb, 0); @@ -5961,11 +5969,11 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* Create and set dst */ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); mono_mb_emit_stloc (mb, conv_arg); mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - mono_mb_emit_stloc (mb, 1); + mono_mb_emit_stloc (mb, 1); /* emit valuetype conversion code */ emit_struct_conv (mb, klass, TRUE); @@ -5994,8 +6002,8 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_STIND_I); pos2 = mono_mb_emit_branch (mb, CEE_BR); - mono_mb_patch_branch (mb, pos); - + mono_mb_patch_branch (mb, pos); + /* Set src */ mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); @@ -6006,12 +6014,12 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_CONV_I); mono_mb_emit_icall (mb, ves_icall_marshal_alloc); mono_mb_emit_stloc (mb, 1); - + /* Update argument pointer */ mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, 1); mono_mb_emit_byte (mb, CEE_STIND_I); - + /* emit valuetype conversion code */ emit_struct_conv (mb, klass, FALSE); @@ -6031,10 +6039,10 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* Set dest */ mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_stloc (mb, 1); - + /* emit valuetype conversion code */ emit_struct_conv (mb, klass, FALSE); - } + } break; case MARSHAL_ACTION_MANAGED_CONV_RESULT: @@ -6086,8 +6094,8 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static int emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, MarshalAction action) { #ifndef DISABLE_COM @@ -6099,7 +6107,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, switch (action) { case MARSHAL_ACTION_CONV_IN: { conv_arg = mono_mb_add_local (mb, variant_type); - + if (m_type_is_byref (t)) *conv_arg_type = variant_type_byref; else @@ -6322,7 +6330,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) { mono_emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT); - } else if (!m_type_is_byref (sig->ret)) { + } else if (!m_type_is_byref (sig->ret)) { switch (sig->ret->type) { case MONO_TYPE_VOID: break; @@ -6354,7 +6362,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s mono_emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT); break; default: - g_warning ("return type 0x%02x unknown", sig->ret->type); + g_warning ("return type 0x%02x unknown", sig->ret->type); g_assert_not_reached (); } } else { @@ -6473,7 +6481,7 @@ emit_ptr_to_struct_ilgen (MonoMethodBuilder *mb, MonoClass *klass) mono_mb_add_local (mb, int_type); /* allocate local 1 (pointer) dst_ptr */ mono_mb_add_local (mb, m_class_get_this_arg (klass)); - + /* initialize src_ptr to point to the start of object data */ mono_mb_emit_byte (mb, CEE_LDARG_0); mono_mb_emit_stloc (mb, 0); @@ -6762,6 +6770,18 @@ mb_emit_exception_for_error_ilgen (MonoMethodBuilder *mb, const MonoError *error mono_mb_emit_exception_for_error (mb, (MonoError*)error); } +static void +emit_marshal_directive_exception_ilgen (EmitMarshalContext *m, int argnum, const char* msg) +{ + char* fullmsg = NULL; + if (argnum == 0) + fullmsg = g_strdup_printf("Error marshalling return value: %s", msg); + else + fullmsg = g_strdup_printf("Error marshalling parameter #%d: %s", argnum, msg); + + mono_mb_emit_exception_marshal_directive (m->mb, fullmsg); +} + static void emit_vtfixup_ftnptr_ilgen (MonoMethodBuilder *mb, MonoMethod *method, int param_count, guint16 type) { @@ -6850,6 +6870,7 @@ mono_marshal_ilgen_init (void) cb.mb_emit_exception = mb_emit_exception_ilgen; cb.mb_emit_exception_for_error = mb_emit_exception_for_error_ilgen; cb.mb_emit_byte = mb_emit_byte_ilgen; + cb.emit_marshal_directive_exception = emit_marshal_directive_exception_ilgen; #ifdef DISABLE_NONBLITTABLE mono_marshal_noilgen_init_blittable (&cb); #endif diff --git a/src/mono/mono/metadata/marshal-noilgen.c b/src/mono/mono/metadata/marshal-noilgen.c index 0cc81a3e5744b..7a004458bbfb7 100644 --- a/src/mono/mono/metadata/marshal-noilgen.c +++ b/src/mono/mono/metadata/marshal-noilgen.c @@ -246,6 +246,11 @@ mb_emit_exception_noilgen (MonoMethodBuilder *mb, const char *exc_nspace, const { } +static void +emit_marshal_directive_exception_noilgen (EmitMarshalContext *m, int argnum, const char* msg) +{ +} + static void mb_emit_exception_for_error_noilgen (MonoMethodBuilder *mb, const MonoError *error) { @@ -404,6 +409,7 @@ mono_marshal_noilgen_init (void) cb.mb_set_dynamic = mb_set_dynamic_noilgen; cb.mb_emit_exception = mb_emit_exception_noilgen; cb.mb_emit_exception_for_error = mb_emit_exception_for_error_noilgen; + cb.emit_marshal_directive_exception = emit_marshal_directive_exception_noilgen; cb.mb_emit_byte = mb_emit_byte_noilgen; mono_install_marshal_callbacks (&cb); } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 498f3ff563f10..8db72b61d9da9 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -2985,6 +2985,51 @@ mono_pinvoke_is_unicode (MonoMethodPInvoke *piinfo) } } +static GENERATE_TRY_GET_CLASS_WITH_CACHE (disable_runtime_marshalling_attr, "System.Runtime.CompilerServices", "DisableRuntimeMarshallingAttribute") + +/* + * runtime_marshalling_enabled: + * + * Determine whenever M's assembly has the runtime marshalling subsystem enabled. + */ +static gboolean +runtime_marshalling_enabled (MonoImage *img) +{ + ERROR_DECL (error); + MonoAssembly *ass = img->assembly; + MonoCustomAttrInfo* attrs; + MonoClass *klass; + int i; + gboolean runtime_marshalling_enabled = TRUE; + + g_assert (ass); + if (ass->runtime_marshalling_enabled_inited) + return ass->runtime_marshalling_enabled; + + klass = mono_class_try_get_disable_runtime_marshalling_attr_class (); + attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, error); + mono_error_cleanup (error); /* FIXME don't swallow the error */ + if (attrs && klass) { + for (i = 0; i < attrs->num_attrs; ++i) { + MonoCustomAttrEntry *attr = &attrs->attrs [i]; + if (attr->ctor && attr->ctor->klass == klass) { + runtime_marshalling_enabled = FALSE; + break; + } + } + } + + if (attrs) + mono_custom_attrs_free (attrs); + + ass->runtime_marshalling_enabled = runtime_marshalling_enabled; + mono_memory_barrier (); + ass->runtime_marshalling_enabled_inited = TRUE; + + return ass->runtime_marshalling_enabled; +} + + MonoType* mono_marshal_boolean_conv_in_get_local_type (MonoMarshalSpec *spec, guint8 *ldc_op /*out*/) { @@ -3031,6 +3076,76 @@ mono_marshal_boolean_managed_conv_in_get_conv_arg_class (MonoMarshalSpec *spec, return conv_arg_class; } +static int +mono_emit_disabled_marshal (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + // Some phases like MARSHAL_ACTION_PUSH need to still emit "correct" IL for the IL stack to be valid. + // For those phases, we won't emit the exception throw. + // In all other phases we'll emit the exception throw. + gboolean emit_exception = action == MARSHAL_ACTION_CONV_IN || action == MARSHAL_ACTION_CONV_RESULT; + + if (m_type_is_byref(t)) { + if (emit_exception) + get_marshal_cb ()->emit_marshal_directive_exception (m, argnum, "Cannot marshal managed references when the runtime marshalling system is disabled."); + else + get_marshal_cb ()->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + return conv_arg; + } + + switch (t->type) { + case MONO_TYPE_GENERICINST: + if (!mono_type_generic_inst_is_valuetype (t)) + break; + // fallthrough + case MONO_TYPE_VALUETYPE: { + MonoClass* c = mono_class_from_mono_type_internal (t); + if (m_class_has_references(c)) { + if (emit_exception) + get_marshal_cb ()->emit_marshal_directive_exception (m, argnum, "Cannot marshal managed types when the runtime marshalling system is disabled."); + else + get_marshal_cb ()->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + return conv_arg; + } + if (m_class_any_field_has_auto_layout(c)) { + if (emit_exception) + get_marshal_cb ()->emit_marshal_directive_exception (m, argnum, "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled."); + else + get_marshal_cb ()->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + return conv_arg; + } + } + // fallthrough + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_PTR: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_FNPTR: + return get_marshal_cb ()->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + default: + break; + } + + if (emit_exception) + get_marshal_cb ()->emit_marshal_directive_exception (m, argnum, "Cannot marshal managed types when the runtime marshalling system is disabled."); + else + get_marshal_cb ()->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + return conv_arg; +} + int mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, @@ -3039,6 +3154,9 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, /* Ensure that we have marshalling info for this param */ mono_marshal_load_type_info (mono_class_from_mono_type_internal (t)); + if (!m->runtime_marshalling_enabled) + return mono_emit_disabled_marshal (m, argnum, t, spec, conv_arg, conv_arg_type, action); + if (spec && spec->native == MONO_NATIVE_CUSTOM) return get_marshal_cb ()->emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action); @@ -3480,6 +3598,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0; flags |= check_exceptions ? EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS : (MonoNativeWrapperFlags)0; flags |= skip_gc_trans ? EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS : (MonoNativeWrapperFlags)0; + flags |= runtime_marshalling_enabled (get_method_image (method)) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0; mono_marshal_emit_native_wrapper (get_method_image (mb->method), mb, csig, piinfo, mspecs, piinfo->addr, flags); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_PINVOKE); @@ -3521,6 +3640,7 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig GHashTable *cache; gboolean found; char *name; + MonoNativeWrapperFlags flags; key.sig = sig; key.pointer = func; @@ -3536,7 +3656,10 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; - mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS); + flags = EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS; + flags |= runtime_marshalling_enabled (image) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0; + + mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, flags); csig = mono_metadata_signature_dup_full (image, sig); csig->pinvoke = 0; @@ -3575,6 +3698,7 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass) MonoMethod *invoke = mono_get_delegate_invoke_internal (klass); MonoImage *image = get_method_image (invoke); int i; + MonoNativeWrapperFlags flags; // FIXME: include UnmanagedFunctionPointerAttribute info @@ -3599,7 +3723,9 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass) mb = mono_mb_new (invoke->klass, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; - mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, NULL, EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS | EMIT_NATIVE_WRAPPER_FUNC_PARAM); + flags = EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS | EMIT_NATIVE_WRAPPER_FUNC_PARAM; + flags |= runtime_marshalling_enabled (image) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0; + mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, NULL, flags); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NATIVE_FUNC_AOT); info->d.managed_to_native.method = invoke; @@ -3677,12 +3803,15 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth mb->method->save_lmf = 1; WrapperInfo *info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT); - info->d.managed_to_native.method = NULL; + //info->d.managed_to_native.method = NULL; + info->d.native_func.klass = caller_class; + info->d.native_func.sig = sig; MonoMethodPInvoke *piinfo = NULL; MonoMarshalSpec **mspecs = g_new0 (MonoMarshalSpec *, 1 + sig->param_count); MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0; flags |= EMIT_NATIVE_WRAPPER_FUNC_PARAM | EMIT_NATIVE_WRAPPER_FUNC_PARAM_UNBOXED; + flags |= runtime_marshalling_enabled (image) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0; mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, /*func*/NULL, flags); g_free (mspecs); @@ -3745,19 +3874,70 @@ type_is_blittable (MonoType *type) } static gboolean -method_signature_is_blittable (MonoMethodSignature *sig) +check_all_types_in_method_signature (MonoMethodSignature *sig, gboolean (*validate) (MonoType *type)) { - if (!type_is_blittable (sig->ret)) + if (!validate (sig->ret)) return FALSE; for (int i = 0; i < sig->param_count; ++i) { MonoType *type = sig->params [i]; - if (!type_is_blittable (type)) + if (!validate (type)) return FALSE; } return TRUE; } +static gboolean +method_signature_is_blittable (MonoMethodSignature *sig) +{ + return check_all_types_in_method_signature (sig, &type_is_blittable); +} + +static gboolean +type_is_usable_when_marshalling_disabled (MonoType *type) +{ + switch (type->type) { + case MONO_TYPE_GENERICINST: + if (!mono_type_generic_inst_is_valuetype (type)) + return FALSE; + // fallthrough + case MONO_TYPE_VALUETYPE: { + MonoClass* c = mono_class_from_mono_type_internal (type); + if (m_class_has_references(c) || (m_class_is_auto_layout(c) && !m_class_is_enumtype(c))) { + return FALSE; + } + } + // fallthrough + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_PTR: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_FNPTR: + return TRUE; + default: + return FALSE; + } +} + + +static gboolean +method_signature_is_usable_when_marshalling_disabled (MonoMethodSignature *sig) +{ + return check_all_types_in_method_signature (sig, &type_is_usable_when_marshalling_disabled); +} + /** * mono_marshal_get_managed_wrapper: * Generates IL code to call managed methods from unmanaged code @@ -3777,6 +3957,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, GHashTable *cache; int i; EmitMarshalContext m; + gboolean marshalling_enabled; g_assert (method != NULL); error_init (error); @@ -3798,22 +3979,28 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, if (G_UNLIKELY (!delegate_klass)) { /* creating a wrapper for a function pointer with UnmanagedCallersOnlyAttribute */ - if (mono_method_has_marshal_info (method)) { - mono_error_set_invalid_program (error, "method %s with UnmanadedCallersOnlyAttribute has marshal specs", mono_method_full_name (method, TRUE)); - return NULL; - } + marshalling_enabled = runtime_marshalling_enabled(get_method_image(method)); invoke = NULL; invoke_sig = mono_method_signature_internal (method); if (invoke_sig->hasthis) { - mono_error_set_invalid_program (error, "method %s with UnamanagedCallersOnlyAttribute is an instance method", mono_method_full_name (method, TRUE)); + mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute is an instance method", mono_method_full_name (method, TRUE)); return NULL; } if (method->is_generic || method->is_inflated || mono_class_is_ginst (method->klass)) { - mono_error_set_invalid_program (error, "method %s with UnamangedCallersOnlyAttribute is generic", mono_method_full_name (method, TRUE)); + mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute is generic", mono_method_full_name (method, TRUE)); return NULL; } - if (!method_signature_is_blittable (invoke_sig)) { - mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute has non-blittable parameters or return type", mono_method_full_name (method, TRUE)); + if (marshalling_enabled) { + if (mono_method_has_marshal_info (method)) { + mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute has marshal specs", mono_method_full_name (method, TRUE)); + return NULL; + } + if (!method_signature_is_blittable (invoke_sig)) { + mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute has non-blittable parameters or return type", mono_method_full_name (method, TRUE)); + return NULL; + } + } else if (!method_signature_is_usable_when_marshalling_disabled(invoke_sig)) { + mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute has types not usable when marshalling is disabled", mono_method_full_name (method, TRUE)); return NULL; } mspecs = g_new0 (MonoMarshalSpec*, invoke_sig->param_count + 1); @@ -3822,6 +4009,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, invoke_sig = mono_method_signature_internal (invoke); mspecs = g_new0 (MonoMarshalSpec*, invoke_sig->param_count + 1); mono_method_get_marshal_info (invoke, mspecs); + marshalling_enabled = runtime_marshalling_enabled(m_class_get_image (delegate_klass)); } sig = mono_method_signature_internal (method); @@ -3840,6 +4028,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, csig->hasthis = 0; csig->pinvoke = 1; + if (!marshalling_enabled) + csig->marshalling_disabled = 1; + memset (&m, 0, sizeof (m)); m.mb = mb; m.sig = sig; @@ -3847,6 +4038,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, m.retobj_var = 0; m.csig = csig; m.image = get_method_image (method); + m.runtime_marshalling_enabled = marshalling_enabled; if (invoke) mono_marshal_set_callconv_from_modopt (invoke, csig, TRUE); @@ -3971,6 +4163,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) MonoMethodSignature *csig; MonoMarshalSpec **mspecs; EmitMarshalContext m; + gboolean marshalling_enabled = runtime_marshalling_enabled(image); sig = mono_method_signature_internal (method); g_assert (!sig->hasthis); @@ -3982,6 +4175,8 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) csig = mono_metadata_signature_dup_full (image, sig); csig->hasthis = 0; csig->pinvoke = 1; + if (!marshalling_enabled) + csig->marshalling_disabled = 1; memset (&m, 0, sizeof (m)); m.mb = mb; @@ -3990,6 +4185,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) m.retobj_var = 0; m.csig = csig; m.image = image; + m.runtime_marshalling_enabled = marshalling_enabled; mono_marshal_set_callconv_from_modopt (method, csig, TRUE); diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index a941934c56446..91bab1c8978aa 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -1,7 +1,7 @@ /** * \file * Routines for marshaling complex types in P/Invoke methods. - * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -50,6 +50,7 @@ typedef struct { MonoClass *retobj_class; MonoMethodSignature *csig; /* Might need to be changed due to MarshalAs directives */ MonoImage *image; /* The image to use for looking up custom marshallers */ + gboolean runtime_marshalling_enabled; } EmitMarshalContext; typedef enum { @@ -77,7 +78,7 @@ typedef enum { /* * The result from the unmanaged call is at the top of the stack when * this action is invoked. The result should be stored in the - * third local variable slot. + * third local variable slot. */ MARSHAL_ACTION_CONV_RESULT, @@ -232,6 +233,11 @@ typedef struct { MonoLLVMFuncWrapperSubtype subtype; } LLVMFuncWrapperInfo; +typedef struct { + MonoClass *klass; + MonoMethodSignature *sig; +} NativeFuncWrapperInfo; + /* * This structure contains additional information to uniquely identify a given wrapper * method. It can be retrieved by mono_marshal_get_wrapper_info () for certain types @@ -276,6 +282,8 @@ typedef struct { AOTInitWrapperInfo aot_init; /* LLVM_FUNC */ LLVMFuncWrapperInfo llvm_func; + /* NATIVE_FUNC_INDIRECT */ + NativeFuncWrapperInfo native_func; } d; } WrapperInfo; @@ -295,12 +303,13 @@ typedef enum { EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS = 0x02, EMIT_NATIVE_WRAPPER_FUNC_PARAM = 0x04, EMIT_NATIVE_WRAPPER_FUNC_PARAM_UNBOXED = 0x08, - EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS=0x10, + EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS = 0x10, + EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED = 0x20, } MonoNativeWrapperFlags; G_ENUM_FUNCTIONS(MonoNativeWrapperFlags); -#define MONO_MARSHAL_CALLBACKS_VERSION 5 +#define MONO_MARSHAL_CALLBACKS_VERSION 6 typedef struct { int version; @@ -347,6 +356,7 @@ typedef struct { void (*mb_emit_exception) (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg); void (*mb_emit_exception_for_error) (MonoMethodBuilder *mb, const MonoError *emitted_error); void (*mb_emit_byte) (MonoMethodBuilder *mb, guint8 op); + void (*emit_marshal_directive_exception) (EmitMarshalContext *m, int argnum, const char* msg); } MonoMarshalCallbacks; /*type of the function pointer of methods returned by mono_marshal_get_runtime_invoke*/ @@ -375,7 +385,7 @@ gint32 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, gboolean as_field, gboolean unicode); -int +int mono_type_native_stack_size (MonoType *type, guint32 *alignment); mono_bstr @@ -539,18 +549,18 @@ mono_marshal_unlock_internal (void); /* marshaling internal calls */ -void * +void * mono_marshal_alloc (gsize size, MonoError *error); ICALL_EXPORT -void +void mono_marshal_free (gpointer ptr); ICALL_EXPORT void mono_marshal_free_array (gpointer *ptr, int size); -gboolean +gboolean mono_marshal_free_ccw (MonoObject* obj); MONO_API void * @@ -561,12 +571,12 @@ void mono_marshal_set_last_error_windows (int error); ICALL_EXPORT -void +void mono_struct_delete_old (MonoClass *klass, char *ptr); int -mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); ICALL_EXPORT diff --git a/src/mono/mono/metadata/mempool-internals.h b/src/mono/mono/metadata/mempool-internals.h index c16e83438e443..fb09d2ecda04b 100644 --- a/src/mono/mono/metadata/mempool-internals.h +++ b/src/mono/mono/metadata/mempool-internals.h @@ -14,7 +14,7 @@ static inline GList* g_list_prepend_mempool (MonoMemPool *mp, GList *list, gpointer data) { GList *new_list; - + new_list = (GList *) mono_mempool_alloc (mp, sizeof (GList)); new_list->data = data; new_list->prev = list ? list->prev : NULL; @@ -32,7 +32,7 @@ static inline GSList* g_slist_prepend_mempool (MonoMemPool *mp, GSList *list, gpointer data) { GSList *new_list; - + new_list = (GSList *) mono_mempool_alloc (mp, sizeof (GSList)); new_list->data = data; new_list->next = list; diff --git a/src/mono/mono/metadata/mempool.c b/src/mono/mono/metadata/mempool.c index ab9fc28bccc35..6a2698a5385f9 100644 --- a/src/mono/mono/metadata/mempool.c +++ b/src/mono/mono/metadata/mempool.c @@ -113,7 +113,7 @@ mono_mempool_new_size (int initial_size) pool->next = NULL; pool->pos = (guint8*)pool + SIZEOF_MEM_POOL; // Start after header - pool->end = (guint8*)pool + initial_size; // End at end of allocated space + pool->end = (guint8*)pool + initial_size; // End at end of allocated space pool->d.allocated = pool->size = initial_size; UnlockedAdd64 (&total_bytes_allocated, initial_size); return pool; diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 4e5ddf40abe86..ed4627d4bab07 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -32,7 +32,7 @@ struct _MonoType { } data; unsigned int attrs : 16; /* param attributes or field flags */ MonoTypeEnum type : 8; - unsigned int has_cmods : 1; + unsigned int has_cmods : 1; unsigned int byref__ : 1; /* don't access directly, use m_type_is_byref */ unsigned int pinned : 1; /* valid when included in a local var signature */ }; @@ -130,14 +130,14 @@ mono_type_get_custom_modifier (const MonoType *ty, uint8_t idx, gboolean *requir // memory unsafety on the stack and/or heap, when we try to traverse // this array. // -// Use mono_sizeof_monotype +// Use mono_sizeof_monotype // to get the size of the memory to copy. #define MONO_SIZEOF_TYPE sizeof (MonoType) -size_t +size_t mono_sizeof_type_with_mods (uint8_t num_mods, gboolean aggregate); -size_t +size_t mono_sizeof_type (const MonoType *ty); size_t @@ -192,8 +192,8 @@ typedef struct _MonoAssemblyContext { } MonoAssemblyContext; struct _MonoAssembly { - /* - * The number of appdomains which have this assembly loaded plus the number of + /* + * The number of appdomains which have this assembly loaded plus the number of * assemblies referencing this assembly through an entry in their image->references * arrays. The latter is needed because entries in the image->references array * might point to assemblies which are only loaded in some appdomains, and without @@ -213,6 +213,8 @@ struct _MonoAssembly { guint8 wrap_non_exception_throws_inited; guint8 jit_optimizer_disabled; guint8 jit_optimizer_disabled_inited; + guint8 runtime_marshalling_enabled; + guint8 runtime_marshalling_enabled_inited; /* security manager flags (one bit is for lazy initialization) */ guint32 skipverification:2; /* Has SecurityPermissionFlag.SkipVerification permission */ }; @@ -236,7 +238,7 @@ struct _MonoTableInfo { * A 32 bit value can encode the resulting size * * The top eight bits encode the number of columns in the table. - * we only need 4, but 8 is aligned no shift required. + * we only need 4, but 8 is aligned no shift required. */ guint32 size_bitfield; }; @@ -348,14 +350,14 @@ struct _MonoImage { MonoMemPool *mempool; /*protected by the image lock*/ char *raw_metadata; - + MonoStreamHeader heap_strings; MonoStreamHeader heap_us; MonoStreamHeader heap_blob; MonoStreamHeader heap_guid; MonoStreamHeader heap_tables; MonoStreamHeader heap_pdb; - + const char *tables_base; /* For PPDB files */ @@ -445,7 +447,7 @@ struct _MonoImage { GHashTable *native_func_wrapper_cache; /* - * indexed by MonoMethod pointers + * indexed by MonoMethod pointers */ GHashTable *wrapper_param_names; GHashTable *array_accessor_cache; @@ -657,6 +659,7 @@ struct _MonoMethodSignature { unsigned int is_inflated : 1; unsigned int has_type_parameters : 1; unsigned int suppress_gc_transition : 1; + unsigned int marshalling_disabled : 1; MonoType *params [MONO_ZERO_LEN_ARRAY]; }; @@ -896,7 +899,7 @@ mono_metadata_parse_mh_full (MonoImage *image, const char *ptr, MonoError *error); -MonoMethodSignature *mono_metadata_parse_signature_checked (MonoImage *image, +MonoMethodSignature *mono_metadata_parse_signature_checked (MonoImage *image, uint32_t token, MonoError *error); @@ -945,7 +948,7 @@ void mono_dynamic_stream_reset (MonoDynamicStream* stream); void mono_assembly_load_friends (MonoAssembly* ass); gboolean mono_assembly_has_skip_verification (MonoAssembly* ass); -MONO_API gint32 +MONO_API gint32 mono_assembly_addref (MonoAssembly *assembly); gint32 mono_assembly_decref (MonoAssembly *assembly); @@ -1007,7 +1010,7 @@ mono_metadata_signature_equal_no_ret (MonoMethodSignature *sig1, MonoMethodSigna MONO_API void mono_metadata_field_info_with_mempool ( - MonoImage *meta, + MonoImage *meta, guint32 table_index, guint32 *offset, guint32 *rva, @@ -1056,7 +1059,7 @@ mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, Mon MonoMethodSignature* mono_method_get_signature_checked (MonoMethod *method, MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error); - + MONO_COMPONENT_API MonoMethod * mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, MonoGenericContext *context, MonoError *error); diff --git a/src/mono/mono/metadata/metadata-update.c b/src/mono/mono/metadata/metadata-update.c index 800ffb9f04727..ac31818c5e499 100644 --- a/src/mono/mono/metadata/metadata-update.c +++ b/src/mono/mono/metadata/metadata-update.c @@ -12,6 +12,7 @@ #include "mono/metadata/metadata-update.h" #include "mono/metadata/components.h" +#include "mono/metadata/class-internals.h" #include "mono/component/hot_reload.h" gboolean @@ -147,3 +148,37 @@ mono_metadata_table_num_rows_slow (MonoImage *base_image, int table_index) { return mono_component_hot_reload()->table_num_rows_slow (base_image, table_index); } + +void* +mono_metadata_update_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer) +{ + return mono_component_hot_reload()->metadata_linear_search (base_image, base_table, key, comparer); +} + +/* + * Returns the (1-based) table row index of the fielddef of the given field + * (which must have m_field_is_from_update set). + */ +uint32_t +mono_metadata_update_get_field_idx (MonoClassField *field) +{ + return mono_component_hot_reload()->get_field_idx (field); +} + +MonoClassField * +mono_metadata_update_get_field (MonoClass *klass, uint32_t fielddef_token) +{ + return mono_component_hot_reload()->get_field (klass, fielddef_token); +} + +gpointer +mono_metadata_update_get_static_field_addr (MonoClassField *field) +{ + return mono_component_hot_reload()->get_static_field_addr (field); +} + +MonoMethod * +mono_metadata_update_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error) +{ + return mono_component_hot_reload()->find_method_by_name (klass, name, param_count, flags, error); +} diff --git a/src/mono/mono/metadata/metadata-update.h b/src/mono/mono/metadata/metadata-update.h index 15d0d51e10f4a..ee999a4f0a10f 100644 --- a/src/mono/mono/metadata/metadata-update.h +++ b/src/mono/mono/metadata/metadata-update.h @@ -6,6 +6,7 @@ #define __MONO_METADATA_UPDATE_H__ #include "mono/utils/mono-forward.h" +#include "mono/utils/bsearch.h" #include "mono/metadata/loader-internals.h" #include "mono/metadata/metadata-internals.h" @@ -57,4 +58,19 @@ mono_metadata_update_table_bounds_check (MonoImage *base_image, int table_index, gboolean mono_metadata_update_delta_heap_lookup (MonoImage *base_image, MetadataHeapGetterFunc get_heap, uint32_t orig_index, MonoImage **image_out, uint32_t *index_out); +void* +mono_metadata_update_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer); + +MonoMethod* +mono_metadata_update_find_method_by_name (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error); + +uint32_t +mono_metadata_update_get_field_idx (MonoClassField *field); + +MonoClassField * +mono_metadata_update_get_field (MonoClass *klass, uint32_t fielddef_token); + +gpointer +mono_metadata_update_get_static_field_addr (MonoClassField *field); + #endif /*__MONO_METADATA_UPDATE_H__*/ diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 04a43f5e0076f..f249e816b76f5 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -4801,7 +4801,12 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index) if (meta->uncompressed_metadata) loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx); - /* FIXME: metadata-update */ + /* if it's not in the base image, look in the hot reload table */ + gboolean added = (loc.idx > table_info_get_rows (&meta->tables [MONO_TABLE_FIELD])); + if (added) { + uint32_t res = mono_component_hot_reload()->field_parent (meta, loc.idx); + return res; /* 0 if not found, otherwise 1-based */ + } if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, typedef_locator)) return 0; @@ -4974,18 +4979,22 @@ mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index) MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS]; locator_t loc; - if (!tdef->base) + if (!tdef->base && !meta->has_updates) return 0; loc.idx = mono_metadata_token_index (index); loc.col_idx = MONO_NESTED_CLASS_NESTED; loc.t = tdef; - /* FIXME: metadata-update */ - - if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator)) + gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; + if (!found && !meta->has_updates) return 0; + if (G_UNLIKELY (meta->has_updates)) { + if (!found && !mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator)) + return 0; + } + /* loc_result is 0..1, needs to be mapped to table index (that is +1) */ return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF; } @@ -5077,19 +5086,24 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index) MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE]; locator_t loc; - if (!tdef->base) + if (!tdef->base && !meta->has_updates) return 0; loc.idx = index; loc.col_idx = MONO_CUSTOM_ATTR_PARENT; loc.t = tdef; - /* FIXME: metadata-update */ /* FIXME: Index translation */ - if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator)) + gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; + if (!found && !meta->has_updates) return 0; + if (G_UNLIKELY (meta->has_updates)) { + if (!found && !mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator)) + return 0; + } + /* Find the first entry by searching backwards */ while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index)) loc.result --; diff --git a/src/mono/mono/metadata/method-builder-ilgen.c b/src/mono/mono/metadata/method-builder-ilgen.c index 68ddbaae60e80..5f48ac8b038aa 100644 --- a/src/mono/mono/metadata/method-builder-ilgen.c +++ b/src/mono/mono/metadata/method-builder-ilgen.c @@ -616,10 +616,10 @@ mono_mb_emit_exception_for_error (MonoMethodBuilder *mb, MonoError *error) void mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr) { - mono_mb_emit_ldloc (mb, local); + mono_mb_emit_ldloc (mb, local); mono_mb_emit_icon (mb, incr); mono_mb_emit_byte (mb, CEE_ADD); - mono_mb_emit_stloc (mb, local); + mono_mb_emit_stloc (mb, local); } void diff --git a/src/mono/mono/metadata/method-builder.c b/src/mono/mono/metadata/method-builder.c index b907d82add622..3f6452ec89a6b 100644 --- a/src/mono/mono/metadata/method-builder.c +++ b/src/mono/mono/metadata/method-builder.c @@ -1,7 +1,7 @@ /** * \file * Functions for creating IL methods at runtime. - * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -47,11 +47,11 @@ static MonoDisHelper marshal_dh = { "\n", "IL_%04x: ", "IL_%04x", - indenter, + indenter, NULL, NULL }; -#endif +#endif static MonoMethodBuilderCallbacks mb_cb; static gboolean cb_inited = FALSE; diff --git a/src/mono/mono/metadata/method-builder.h b/src/mono/mono/metadata/method-builder.h index fd3903c866445..673dcec32b858 100644 --- a/src/mono/mono/metadata/method-builder.h +++ b/src/mono/mono/metadata/method-builder.h @@ -1,7 +1,7 @@ /** * \file * Functions for creating IL methods at runtime. - * + * * Author: * Paolo Molaro (lupus@ximian.com) * diff --git a/src/mono/mono/metadata/monitor.c b/src/mono/mono/metadata/monitor.c index da5662677b866..042f73b866c86 100644 --- a/src/mono/mono/metadata/monitor.c +++ b/src/mono/mono/metadata/monitor.c @@ -315,7 +315,7 @@ mono_locks_dump (gboolean include_untaken) } /* LOCKING: this is called with monitor_mutex held */ -static void +static void mon_finalize (MonoThreadsSync *mon) { LOCK_DEBUG (g_message ("%s: Finalizing sync %p", __func__, mon)); @@ -411,7 +411,7 @@ mon_new (gsize id) new_->status = mon_status_init_entry_count (new_->status); new_->nest = 1; new_->data = NULL; - + #ifndef DISABLE_PERFCOUNTERS mono_atomic_inc_i32 (&mono_perfcounters->gc_sync_blocks); #endif @@ -566,7 +566,7 @@ mono_object_hash_internal (MonoObject* obj) /* Done by somebody else */ return hash; } - + mono_monitor_inflate (obj); lw.sync = obj->synchronisation; } else if (lock_word_is_flat (lw)) { @@ -666,7 +666,7 @@ mono_monitor_exit_inflated (MonoObject *obj) old_status = tmp_status; } LOCK_DEBUG (g_message ("%s: (%d) Object %p is now unlocked", __func__, mono_thread_info_get_small_id (), obj)); - + /* object is now unlocked, leave nest==1 so we don't * need to set it when the lock is reacquired */ @@ -758,7 +758,7 @@ static gint64 thread_contentions; /* for Monitor.LockContentionCount, otherwise /* If allow_interruption==TRUE, the method will be interrupted if abort or suspend * is requested. In this case it returns -1. - */ + */ static gint32 mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_interruption, guint32 id) { @@ -874,7 +874,7 @@ mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_int then = mono_msec_ticks (); } waitms = ms; - + #ifndef DISABLE_PERFCOUNTERS mono_atomic_inc_i32 (&mono_perfcounters->thread_queue_len); mono_atomic_inc_i32 (&mono_perfcounters->thread_queue_max); @@ -905,8 +905,8 @@ mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_int if (timedout || (interrupted && allow_interruption)) { /* we're done */ } else { - /* - * We have to obey a stop/suspend request even if + /* + * We have to obey a stop/suspend request even if * allow_interruption is FALSE to avoid hangs at shutdown. * FIXME Handle abort protected blocks */ @@ -1051,7 +1051,7 @@ void mono_monitor_exit_internal (MonoObject *obj) { LockWord lw; - + LOCK_DEBUG (g_message ("%s: (%d) Unlocking %p", __func__, mono_thread_info_get_small_id (), obj)); if (G_UNLIKELY (!obj)) { @@ -1242,7 +1242,7 @@ ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObjectHandle obj_hand } else if (lock_word_is_inflated (lw)) { return mon_status_get_owner (lock_word_get_inflated_lock (lw)->status) == mono_thread_info_get_small_id (); } - + return FALSE; } @@ -1279,7 +1279,7 @@ mono_monitor_pulse (MonoObject *obj, const char *func, gboolean all) MonoThreadsSync *mon; LOCK_DEBUG (g_message ("%s: (%d) Pulsing %p", func, id, obj)); - + lw.sync = obj->synchronisation; if (!mono_monitor_ensure_owned (lw, id)) @@ -1365,7 +1365,7 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in mono_thread_set_state (thread, ThreadState_WaitSleepJoin); mon->wait_list = g_slist_append (mon->wait_list, event); - + /* Save the nest count, and release the lock */ nest = mon->nest; mon->nest = 1; @@ -1414,7 +1414,7 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in * be signalled more than once, thereby starving another * thread. */ - + if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) { LOCK_DEBUG (g_message ("%s: (%d) Success", __func__, id)); success = TRUE; @@ -1426,7 +1426,7 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in mon->wait_list = g_slist_remove (mon->wait_list, event); } mono_w32event_close (event); - + return success; } diff --git a/src/mono/mono/metadata/mono-basic-block.c b/src/mono/mono/metadata/mono-basic-block.c index 6dd0a679fe541..4fef3f8b9a442 100644 --- a/src/mono/mono/metadata/mono-basic-block.c +++ b/src/mono/mono/metadata/mono-basic-block.c @@ -410,7 +410,7 @@ bb_formation_il_pass (const unsigned char *start, const unsigned char *end, Mono offset = cli_addr + 5 + (gint32)read32 (ip + 1); ip += 5; } - + branch = bb_split (bb, current, root, offset, TRUE, method, error); if (!branch) return; @@ -442,7 +442,7 @@ bb_formation_il_pass (const unsigned char *start, const unsigned char *end, Mono return; bb_link (current, next); - tmp = next; + tmp = next; for (j = 0; j < n; ++j) { if (ip >= end) { @@ -545,7 +545,7 @@ mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader * bb_formation_il_pass (start, end, bb, &root, method, error); if (!is_ok (error)) goto fail; - + bb_formation_eh_pass (header, bb, &root, method, error); if (!is_ok (error)) goto fail; @@ -567,14 +567,14 @@ mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader * * mono_opcode_value_and_size: * * Returns the size of the opcode starting at *@ip, or -1 on error. - * Value is the opcode number. + * Value is the opcode number. */ int mono_opcode_value_and_size (const unsigned char **ip, const unsigned char *end, MonoOpcodeEnum *value) { const unsigned char *start = *ip, *p; int i = *value = mono_opcode_value (ip, end); - int size = 0; + int size = 0; if (i < 0 || i >= MONO_CEE_LAST) return -1; p = *ip; diff --git a/src/mono/mono/metadata/mono-conc-hash.c b/src/mono/mono/metadata/mono-conc-hash.c index f0bdcc4002482..c79e7210ce20a 100644 --- a/src/mono/mono/metadata/mono-conc-hash.c +++ b/src/mono/mono/metadata/mono-conc-hash.c @@ -169,7 +169,7 @@ rehash_table (MonoConcGHashTable *hash_table, int multiplier) hash_table->overflow_count = (int)(new_table->table_size * LOAD_FACTOR); hash_table->element_count -= hash_table->tombstone_count; hash_table->tombstone_count = 0; - conc_table_lf_free (old_table); + conc_table_lf_free (old_table); } @@ -305,7 +305,7 @@ mono_conc_g_hash_table_foreach (MonoConcGHashTable *hash_table, GHFunc func, gpo if (table->keys [i] && !key_is_tombstone (hash_table, table->keys [i])) { func (table->keys [i], table->values [i], user_data); } - } + } } void @@ -359,7 +359,7 @@ mono_conc_g_hash_table_insert (MonoConcGHashTable *hash_table, gpointer key, gpo if (is_tombstone) --hash_table->tombstone_count; else - ++hash_table->element_count; + ++hash_table->element_count; return NULL; } @@ -382,7 +382,7 @@ mono_conc_g_hash_table_insert (MonoConcGHashTable *hash_table, gpointer key, gpo if (is_tombstone) --hash_table->tombstone_count; else - ++hash_table->element_count; + ++hash_table->element_count; return NULL; } diff --git a/src/mono/mono/metadata/mono-config-internals.h b/src/mono/mono/metadata/mono-config-internals.h index ce26f5dd52ca6..dabccc0e8a4f0 100644 --- a/src/mono/mono/metadata/mono-config-internals.h +++ b/src/mono/mono/metadata/mono-config-internals.h @@ -7,7 +7,7 @@ #include "mono/metadata/mono-config.h" -void +void mono_config_for_assembly_internal (MonoImage *assembly); #endif /* __MONO_METADATA_CONFIG_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/mono-config.c b/src/mono/mono/metadata/mono-config.c index 89c5be8ff5e7f..f38b8f5303dd5 100644 --- a/src/mono/mono/metadata/mono-config.c +++ b/src/mono/mono/metadata/mono-config.c @@ -63,7 +63,7 @@ #define CONFIG_WORDSIZE "32" #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_64) || defined(TARGET_POWERPC) #define CONFIG_WORDSIZE "64" -#ifdef __mono_ppc_ilp32__ +#ifdef __mono_ppc_ilp32__ # define CONFIG_CPU "ppc64ilp32" #else # define CONFIG_CPU "ppc64" diff --git a/src/mono/mono/metadata/mono-debug.c b/src/mono/mono/metadata/mono-debug.c index 03626981f441d..78b1e07a42183 100644 --- a/src/mono/mono/metadata/mono-debug.c +++ b/src/mono/mono/metadata/mono-debug.c @@ -847,7 +847,7 @@ mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset) if (ret) return ret; } - } + } MonoDebugSourceLocation *location; @@ -871,7 +871,7 @@ mono_debug_lookup_locals (MonoMethod *method) { MonoDebugMethodInfo *minfo; MonoDebugLocalsInfo *res; - + MonoImage* img = m_class_get_image (method->klass); if (img->has_updates) { int idx = mono_metadata_token_index (method->token); @@ -1144,7 +1144,7 @@ mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrA if (mono_ppdb_get_seq_points_enc (minfo, mdie->ppdb_file, mdie->idx, source_file, source_file_list, source_files, seq_points, n_seq_points)) return; } - } + } if (minfo->handle->ppdb) mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points); else diff --git a/src/mono/mono/metadata/mono-endian.c b/src/mono/mono/metadata/mono-endian.c index d7822c72ff630..170498377f605 100644 --- a/src/mono/mono/metadata/mono-endian.c +++ b/src/mono/mono/metadata/mono-endian.c @@ -29,7 +29,7 @@ typedef union { guint64 i; } mono_rint64; -guint16 +guint16 mono_read16 (const unsigned char *x) { mono_rint16 r; @@ -43,7 +43,7 @@ mono_read16 (const unsigned char *x) return r.i; } -guint32 +guint32 mono_read32 (const unsigned char *x) { mono_rint32 r; @@ -61,7 +61,7 @@ mono_read32 (const unsigned char *x) return r.i; } -guint64 +guint64 mono_read64 (const unsigned char *x) { mono_rint64 r; diff --git a/src/mono/mono/metadata/mono-hash-internals.h b/src/mono/mono/metadata/mono-hash-internals.h index 84b8894f9e00e..bf2f4ea9fd7be 100644 --- a/src/mono/mono/metadata/mono-hash-internals.h +++ b/src/mono/mono/metadata/mono-hash-internals.h @@ -12,7 +12,7 @@ MONO_COMPONENT_API MonoGHashTable * mono_g_hash_table_new_type_internal (GHashFunc hash_func, GEqualFunc key_equal_func, MonoGHashGCType type, MonoGCRootSource source, void *key, const char *msg); -MONO_COMPONENT_API void +MONO_COMPONENT_API void mono_g_hash_table_insert_internal (MonoGHashTable *h, gpointer k, gpointer v); #endif /* __MONO_G_HASH_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/mono-private-unstable.h b/src/mono/mono/metadata/mono-private-unstable.h index 4618c8fe08bc9..203ef008ad486 100644 --- a/src/mono/mono/metadata/mono-private-unstable.h +++ b/src/mono/mono/metadata/mono-private-unstable.h @@ -1,6 +1,6 @@ /** * \file - * + * * Private unstable APIs. * * WARNING: The declarations and behavior of functions in this header are NOT STABLE and can be modified or removed at diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index e32515ae8dcd1..a1fc8b47b702d 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -92,7 +92,7 @@ mono_dllmap_lookup_list (MonoDllMap *dll_map, const char *dll, const char* func, if (!dll_map) goto exit; - /* + /* * we use the first entry we find that matches, since entries from * the config file are prepended to the list and we document that the * later entries win. @@ -254,7 +254,7 @@ mono_global_dllmap_cleanup (void) * This function is used to programatically add \c DllImport remapping in either * a specific assembly, or as a global remapping. This is done by remapping * references in a \c DllImport attribute from the \p dll library name into the \p tdll - * name. If the \p dll name contains the prefix i:, the comparison of the + * name. If the \p dll name contains the prefix i:, the comparison of the * library name is done without case sensitivity. * * If you pass \p func, this is the name of the \c EntryPoint in a \c DllImport if specified @@ -526,7 +526,7 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags) module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name, lflags); // Check the assembly directory if the search flag is set and the image exists - if ((flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY) != 0 && image != NULL && + if ((flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY) != 0 && image != NULL && module == NULL && (image->filename != NULL)) { char *mdirname = g_path_get_dirname (image->filename); if (mdirname) @@ -1145,7 +1145,7 @@ pinvoke_probe_for_symbol (MonoDl *module, MonoMethodPInvoke *piinfo, const char #if HOST_WIN32 && HOST_X86 /* Try the stdcall mangled name */ - /* + /* * gcc under windows creates mangled names without the underscore, but MS.NET * doesn't support it, so we doesn't support it either. */ @@ -1385,7 +1385,7 @@ mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const char *file, *buffer, *err, *internal_path; if (!bundle_save_library_initialized) bundle_save_library_initialize (); - + file = g_build_filename (bundled_dylibrary_directory, destfname, (const char*)NULL); buffer = g_str_from_file_region (fd, offset, size); g_file_set_contents (file, buffer, size, NULL); @@ -1400,7 +1400,7 @@ mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const mono_loader_register_module (internal_path, lib); g_free (internal_path); bundle_library_paths = g_slist_append (bundle_library_paths, file); - + g_free (buffer); } diff --git a/src/mono/mono/metadata/null-gc-handles.c b/src/mono/mono/metadata/null-gc-handles.c index 6ba1c0fe7f99d..8d946fe890b1c 100644 --- a/src/mono/mono/metadata/null-gc-handles.c +++ b/src/mono/mono/metadata/null-gc-handles.c @@ -36,7 +36,7 @@ typedef struct { #define EMPTY_HANDLE_DATA(type) {NULL, NULL, 0, (type), 0, NULL} -/* weak and weak-track arrays will be allocated in malloc memory +/* weak and weak-track arrays will be allocated in malloc memory */ static HandleData gc_handles [] = { EMPTY_HANDLE_DATA (HANDLE_WEAK), @@ -236,12 +236,12 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) * This returns a handle that wraps the object, this is used to keep a * reference to a managed object from the unmanaged world and preventing the * object from being disposed. - * + * * If \p pinned is false the address of the object can not be obtained, if it is * true the address of the object can be obtained. This will also pin the * object so it will not be possible by a moving garbage collector to move the - * object. - * + * object. + * * \returns a handle that can be used to access the object from * unmanaged code. */ @@ -261,14 +261,14 @@ mono_gchandle_new_internal (MonoObject *obj, gboolean pinned) * Unlike the \c mono_gchandle_new_internal the object can be reclaimed by the * garbage collector. In this case the value of the GCHandle will be * set to zero. - * + * * If \p track_resurrection is TRUE the object will be tracked through * finalization and if the object is resurrected during the execution * of the finalizer, then the returned weakref will continue to hold * a reference to the object. If \p track_resurrection is FALSE, then * the weak reference's target will become NULL as soon as the object * is passed on to the finalizer. - * + * * \returns a handle that can be used to access the object from * unmanaged code. */ @@ -388,7 +388,7 @@ mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain) * * Frees the \p gchandle handle. If there are no outstanding * references, the garbage collector can reclaim the memory of the - * object wrapped. + * object wrapped. */ void mono_gchandle_free_internal (guint32 gchandle) diff --git a/src/mono/mono/metadata/null-gc.c b/src/mono/mono/metadata/null-gc.c index 343756d2c67da..039e3c2ad7056 100644 --- a/src/mono/mono/metadata/null-gc.c +++ b/src/mono/mono/metadata/null-gc.c @@ -635,7 +635,7 @@ mono_gc_ephemeron_array_add (MonoObject *obj) return TRUE; } -guint64 mono_gc_get_total_allocated_bytes (MonoBoolean precise) +guint64 mono_gc_get_total_allocated_bytes (MonoBoolean precise) { return 0; } diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 6c6d089ee2122..efa4b0624548d 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -93,7 +93,7 @@ mono_array_new_specific_handle (MonoVTable *vtable, uintptr_t n, MonoError *erro MonoArray* mono_array_new_specific_checked (MonoVTable *vtable, uintptr_t n, MonoError *error); -/* +/* * Macros which cache. * These should be used instead of the original versions. */ @@ -170,7 +170,7 @@ struct _MonoArray { /* bounds is NULL for szarrays */ MonoArrayBounds *bounds; /* total number of elements of the array */ - mono_array_size_t max_length; + mono_array_size_t max_length; /* we use mono_64bitaligned_t to ensure proper alignment on platforms that need it */ mono_64bitaligned_t vector [MONO_ZERO_LEN_ARRAY]; }; @@ -469,7 +469,7 @@ typedef struct _MonoQCallAssemblyHandle MonoQCallAssemblyHandle; typedef struct { MonoObject object; - MonoReflectionType *class_to_proxy; + MonoReflectionType *class_to_proxy; MonoObject *context; MonoObject *unwrapped_server; gint32 target_domain_id; @@ -523,7 +523,7 @@ TYPED_HANDLE_DECL (MonoComInteropProxy); typedef struct { MonoObject object; - MonoRealProxy *rp; + MonoRealProxy *rp; MonoRemoteClass *remote_class; MonoBoolean custom_type_info; } MonoTransparentProxy; @@ -534,9 +534,9 @@ TYPED_HANDLE_DECL (MonoTransparentProxy); typedef struct { MonoObject obj; MonoReflectionMethod *method; - MonoArray *args; - MonoArray *names; - MonoArray *arg_types; + MonoArray *args; + MonoArray *names; + MonoArray *arg_types; MonoObject *ctx; MonoObject *rval; MonoObject *exc; @@ -664,7 +664,7 @@ TYPED_HANDLE_DECL (MonoDelegate); typedef void (*InterpJitInfoFunc) (MonoJitInfo *ji, gpointer user_data); -/* +/* * Callbacks supplied by the runtime and called by the modules in metadata/ * This interface is easier to extend than adding a new function type + * a new 'install' function for every callback. @@ -780,9 +780,9 @@ mono_domain_get_tls_offset (void); /* * Handling System.Type objects: * - * Fields defined as System.Type in managed code should be defined as MonoObject* - * in unmanaged structures, and the monotype_cast () function should be used for - * casting them to MonoReflectionType* to avoid crashes/security issues when + * Fields defined as System.Type in managed code should be defined as MonoObject* + * in unmanaged structures, and the monotype_cast () function should be used for + * casting them to MonoReflectionType* to avoid crashes/security issues when * encountering instances of user defined subclasses of System.Type. */ @@ -830,8 +830,8 @@ struct _MonoDelegate { gpointer delegate_trampoline; /* Extra argument passed to the target method in llvmonly mode */ gpointer extra_arg; - /* - * If non-NULL, this points to a memory location which stores the address of + /* + * If non-NULL, this points to a memory location which stores the address of * the compiled code of the method, or NULL if it is not yet compiled. */ guint8 **method_code; @@ -1138,7 +1138,7 @@ typedef struct { MonoArray *modopt; } MonoReflectionFieldBuilder; -/* Safely access System.Reflection.Emit.FieldBuilder from native code */ +/* Safely access System.Reflection.Emit.FieldBuilder from native code */ TYPED_HANDLE_DECL (MonoReflectionFieldBuilder); typedef struct { @@ -1222,6 +1222,7 @@ struct _MonoReflectionTypeBuilder { MonoGenericContainer *generic_container; MonoArray *generic_params; MonoReflectionType *created; + gboolean is_byreflike_set; gint32 state; }; @@ -1344,7 +1345,7 @@ typedef struct { MonoArray *refs; GSList *referenced_by; MonoReflectionType *owner; -} MonoReflectionDynamicMethod; +} MonoReflectionDynamicMethod; /* Safely access System.Reflection.Emit.DynamicMethod from native code */ TYPED_HANDLE_DECL (MonoReflectionDynamicMethod); @@ -1666,7 +1667,7 @@ mono_class_set_ref_info (MonoClass *klass, MonoObjectHandle obj); void mono_class_free_ref_info (MonoClass *klass); -MonoObject * +MONO_COMPONENT_API MonoObject * mono_object_new_pinned (MonoClass *klass, MonoError *error); MonoObjectHandle @@ -1678,7 +1679,7 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error); ICALL_EXPORT MonoObject * ves_icall_object_new (MonoClass *klass); - + ICALL_EXPORT MonoObject * ves_icall_object_new_specific (MonoVTable *vtable); @@ -1886,7 +1887,7 @@ MonoObject* mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects *params, MonoError *error); -void* +void* mono_compile_method_checked (MonoMethod *method, MonoError *error); MonoObject* diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 284e15b1ade8e..9a39381533e5a 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -886,6 +887,7 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int } else { /* fall through */ } + case MONO_TYPE_TYPEDBYREF: case MONO_TYPE_VALUETYPE: { MonoClass *fclass = mono_class_from_mono_type_internal (field->type); if (m_class_has_references (fclass)) { @@ -2854,6 +2856,9 @@ mono_static_field_get_addr (MonoVTable *vt, MonoClassField *field) g_assert (field->type->attrs & FIELD_ATTRIBUTE_STATIC); if (field->offset == -1) { + if (G_UNLIKELY (m_field_is_from_update (field))) { + return mono_metadata_update_get_static_field_addr (field); + } /* Special static */ ERROR_DECL (error); gpointer addr = mono_special_static_field_get_offset (field, error); @@ -3237,9 +3242,13 @@ mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value) { MONO_REQ_GC_NEUTRAL_MODE; + HANDLE_FUNCTION_ENTER (); + ERROR_DECL (error); mono_field_static_get_value_checked (vt, field, value, MONO_HANDLE_NEW (MonoString, NULL), error); mono_error_cleanup (error); + + HANDLE_FUNCTION_RETURN (); } /** @@ -6791,9 +6800,9 @@ mono_string_is_interned_lookup (MonoStringHandle str, gboolean insert, MonoError #ifdef HOST_WASM /** * mono_string_instance_is_interned: - * Searches the interned string table for the provided string instance. + * Checks to see if the string instance has its interned flag set. * \param str String to probe - * \returns TRUE if the string is interned, FALSE otherwise. + * \returns TRUE if the string instance is interned, FALSE otherwise. */ int mono_string_instance_is_interned (MonoString *str) diff --git a/src/mono/mono/metadata/object.h b/src/mono/mono/metadata/object.h index fa9d84121bc1b..2186fa802c448 100644 --- a/src/mono/mono/metadata/object.h +++ b/src/mono/mono/metadata/object.h @@ -48,7 +48,7 @@ typedef void (*MonoMainThreadFunc) (void* user_data); } while (0) #define mono_array_addr(array,type,index) ((type*)mono_array_addr_with_size ((array), sizeof (type), (index))) -#define mono_array_get(array,type,index) ( *(type*)mono_array_addr ((array), type, (index)) ) +#define mono_array_get(array,type,index) ( *(type*)mono_array_addr ((array), type, (index)) ) #define mono_array_set(array,type,index,value) \ do { \ type *__p = (type *) mono_array_addr ((array), type, (index)); \ @@ -291,7 +291,7 @@ mono_runtime_exec_managed_code (MonoDomain *domain, void* main_args); MONO_API MONO_RT_EXTERNAL_ONLY int -mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], +mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], MonoObject **exc); MONO_API MONO_RT_EXTERNAL_ONLY int @@ -348,11 +348,11 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec /* GC handles support * * A handle can be created to refer to a managed object and either prevent it - * from being garbage collected or moved or to be able to know if it has been + * from being garbage collected or moved or to be able to know if it has been * collected or not (weak references). * mono_gchandle_new () is used to prevent an object from being garbage collected * until mono_gchandle_free() is called. Use a TRUE value for the pinned argument to - * prevent the object from being moved (this should be avoided as much as possible + * prevent the object from being moved (this should be avoided as much as possible * and this should be used only for shorts periods of time or performance will suffer). * To create a weakref use mono_gchandle_new_weakref (): track_resurrection should * usually be false (see the GC docs for more details). diff --git a/src/mono/mono/metadata/property-bag.c b/src/mono/mono/metadata/property-bag.c index 9dc0634ec0087..42c083f038115 100644 --- a/src/mono/mono/metadata/property-bag.c +++ b/src/mono/mono/metadata/property-bag.c @@ -21,7 +21,7 @@ void* mono_property_bag_get (MonoPropertyBag *bag, int tag) { MonoPropertyBagItem *item; - + for (item = bag->head; item && item->tag <= tag; item = item->next) { if (item->tag == tag) return item; diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 9c39731d698b2..47683f1e68ab9 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -1,7 +1,7 @@ /** * \file * System.Type icalls and related reflection queries. - * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -238,7 +238,7 @@ mono_assembly_get_object_handle (MonoAssembly *assembly, MonoError *error) /** * mono_module_get_object: */ -MonoReflectionModule* +MonoReflectionModule* mono_module_get_object (MonoDomain *domain, MonoImage *image) { MonoReflectionModuleHandle result; @@ -255,7 +255,7 @@ static MonoReflectionModuleHandle module_object_construct (MonoClass *unused_klass, MonoImage *image, gpointer user_data, MonoError *error) { char* basename; - + error_init (error); MonoReflectionModuleHandle res = MONO_HANDLE_CAST (MonoReflectionModule, mono_object_new_handle (mono_class_get_mono_module_class (), error)); goto_if_nok (error, fail); @@ -328,7 +328,7 @@ mono_module_file_get_object_handle (MonoImage *image, int table_index, MonoError const char *name; guint32 i, name_idx; const char *val; - + error_init (error); MonoReflectionModuleHandle res = MONO_HANDLE_CAST (MonoReflectionModule, mono_object_new_handle (mono_class_get_mono_module_class (), error)); @@ -448,7 +448,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) /*we must avoid using @type as it might have come * from a mono_metadata_type_dup and the caller * expects that is can be freed. - * Using the right type from + * Using the right type from */ type = m_type_is_byref (m_class_get_byval_arg (klass)) == m_type_is_byref (type) ? m_class_get_byval_arg (klass) : m_class_get_this_arg (klass); @@ -469,9 +469,9 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) /* * If the vtable of the given class was already created, we can use * the MonoType from there and avoid all locking and hash table lookups. - * + * * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects - * that the resulting object is different. + * that the resulting object is different. */ if (type == m_class_get_byval_arg (klass) && !image_is_dynamic (m_class_get_image (klass))) { MonoVTable *vtable = mono_class_try_get_vtable (klass); @@ -594,7 +594,7 @@ method_object_construct (MonoClass *refclass, MonoMethod *method, gpointer user_ error_init (error); g_assert (refclass != NULL); /* - * We use the same C representation for methods and constructors, but the type + * We use the same C representation for methods and constructors, but the type * name in C# is different. */ MonoClass *klass; @@ -1053,7 +1053,7 @@ param_objects_construct (MonoClass *refclass, MonoMethodSignature **addr_of_sig, int i; error_init (error); - + MonoReflectionMethodHandle member = mono_method_get_object_handle (method, refclass, error); goto_if_nok (error, leave); names = g_new (char *, sig->param_count); @@ -1107,7 +1107,7 @@ param_objects_construct (MonoClass *refclass, MonoMethodSignature **addr_of_sig, if (!is_ok (error)) return NULL_HANDLE_ARRAY; - + return res; } @@ -1444,7 +1444,7 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) if (!crow) { continue; } - + mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE); blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]); types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE]; @@ -1479,7 +1479,7 @@ mono_get_object_from_blob (MonoType *type, const char *blob, MonoStringHandleOut if (m_class_is_enumtype (klass)) basetype = mono_class_enum_basetype_internal (klass); } - + if (mono_get_constant_value_from_blob (basetype->type, blob, retval, string_handle, error)) MONO_HANDLE_ASSIGN_RAW (object_handle, object); else @@ -1685,7 +1685,7 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed, // *w++ = *p++; p++; } - + if (!info->name) { if (last_point) { info->name_space = start; @@ -1936,7 +1936,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) * \param name the string to parse * \param info the parsed name components * \param error set on error - * + * * Parse the given \p name and write the results to \p info, setting \p error * on error. The string \p name is modified in place and \p info points into * its memory and into allocated memory. @@ -1969,7 +1969,7 @@ _mono_reflection_get_type_from_info (MonoAssemblyLoadContext *alc, MonoTypeNameP if (info->assembly.name) { MonoAssembly *assembly = mono_assembly_loaded_internal (alc, &info->assembly); if (!assembly && image && image->assembly && mono_assembly_check_name_match (&info->assembly, &image->assembly->aname)) - /* + /* * This could happen in the AOT compiler case when the search hook is not * installed. */ @@ -2015,7 +2015,7 @@ mono_reflection_get_type_internal (MonoAssemblyLoadContext *alc, MonoImage *root int modval; gboolean bounded = FALSE; MonoType* type = NULL; - + error_init (error); if (!image) image = mono_defaults.corlib; @@ -2151,7 +2151,7 @@ mono_reflection_get_type_internal (MonoAssemblyLoadContext *alc, MonoImage *root * \param type_resolve whenever type resolve was already tried * * Build a MonoType from the type description in \p info. - * + * */ MonoType* mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) @@ -2253,7 +2253,7 @@ mono_reflection_get_type_internal_dynamic (MonoAssemblyLoadContext *alc, MonoIma leave: HANDLE_FUNCTION_RETURN_VAL (type); } - + MonoType* mono_reflection_get_type_with_rootimage (MonoAssemblyLoadContext *alc, MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean search_mscorlib, gboolean *type_resolve, MonoError *error) { @@ -2279,11 +2279,11 @@ mono_reflection_get_type_with_rootimage (MonoAssemblyLoadContext *alc, MonoImage goto return_null; if (type_resolve) { - if (*type_resolve) + if (*type_resolve) goto return_null; *type_resolve = TRUE; } - + /* Reconstruct the type name */ fullName = g_string_new (""); if (info->name_space && (info->name_space [0] != '\0')) @@ -2354,7 +2354,7 @@ mono_reflection_free_type_info (MonoTypeNameParse *info) * Retrieves a \c MonoType from its \p name. If the name is not fully qualified, * it defaults to get the type from \p image or, if \p image is NULL or loading * from it fails, uses corlib. - * + * */ MonoType* mono_reflection_type_from_name (char *name, MonoImage *image) @@ -2392,7 +2392,7 @@ mono_reflection_type_from_name_checked (char *name, MonoAssemblyLoadContext *alc error_init (error); /* Make a copy since parse_type modifies its argument */ tmp = g_strdup (name); - + /*g_print ("requested type %s\n", str);*/ ERROR_DECL (parse_error); if (!mono_reflection_parse_type_checked (tmp, &info, parse_error)) { @@ -2421,7 +2421,7 @@ mono_reflection_get_token (MonoObject *obj_raw) ERROR_DECL (error); result = mono_reflection_get_token_checked (obj, error); mono_error_assert_ok (error); - + MONO_EXIT_GC_UNSAFE; HANDLE_FUNCTION_RETURN_VAL (result); } @@ -2570,7 +2570,7 @@ mono_reflection_bind_generic_parameters (MonoReflectionTypeHandle reftype, int t MonoClass *geninst; error_init (error); - + mono_loader_lock (); MonoClass *klass = mono_handle_class (reftype); @@ -2803,7 +2803,7 @@ mono_declsec_flags_from_method (MonoMethod *method) * mono_declsec_flags_from_class: * \param klass The class for which we want the declarative security flags. * Get the security actions (in the form of flags) associated with the specified class. - * We cache the flags inside the \c MonoClass structure as this will get + * We cache the flags inside the \c MonoClass structure as this will get * called very often (at least for each method). * \returns the declarative security flags for the class. */ @@ -2900,7 +2900,7 @@ fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityAction } static MonoBoolean -mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, +mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, guint32 id_std, guint32 id_noncas, guint32 id_choice) { guint32 idx = mono_metadata_token_index (m_class_get_type_token (klass)); @@ -2910,7 +2910,7 @@ mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions } static MonoBoolean -mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, +mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, guint32 id_std, guint32 id_noncas, guint32 id_choice) { guint32 idx = mono_method_get_index (method); @@ -2928,7 +2928,7 @@ mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActi MonoBoolean mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands) { - guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | + guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | MONO_DECLSEC_FLAG_DEMAND_CHOICE; MonoBoolean result = FALSE; guint32 flags; @@ -2949,7 +2949,7 @@ mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands) mono_class_init_internal (method->klass); memset (demands, 0, sizeof (MonoDeclSecurityActions)); - result = mono_declsec_get_method_demands_params (method, demands, + result = mono_declsec_get_method_demands_params (method, demands, SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE); } @@ -2960,7 +2960,7 @@ mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands) mono_class_init_internal (method->klass); memset (demands, 0, sizeof (MonoDeclSecurityActions)); } - result |= mono_declsec_get_class_demands_params (method->klass, demands, + result |= mono_declsec_get_class_demands_params (method->klass, demands, SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE); } @@ -3000,7 +3000,7 @@ mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { mono_class_init_internal (method->klass); - result = mono_declsec_get_method_demands_params (method, cmethod, + result = mono_declsec_get_method_demands_params (method, cmethod, SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE); } @@ -3009,7 +3009,7 @@ mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) { mono_class_init_internal (method->klass); - result |= mono_declsec_get_class_demands_params (method->klass, klass, + result |= mono_declsec_get_class_demands_params (method->klass, klass, SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE); } @@ -3040,7 +3040,7 @@ mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions mono_class_init_internal (klass); memset (demands, 0, sizeof (MonoDeclSecurityActions)); - result |= mono_declsec_get_class_demands_params (klass, demands, + result |= mono_declsec_get_class_demands_params (klass, demands, SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE); } @@ -3070,7 +3070,7 @@ mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActi mono_class_init_internal (method->klass); memset (demands, 0, sizeof (MonoDeclSecurityActions)); - return mono_declsec_get_method_demands_params (method, demands, + return mono_declsec_get_method_demands_params (method, demands, SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE); } return FALSE; @@ -3164,7 +3164,7 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, Mono g_assert (method); } - /* + /* * The result of mono_type_get_object_checked () might be a System.MonoType but we * need a TypeBuilder so use mono_class_get_ref_info (klass). */ diff --git a/src/mono/mono/metadata/reflection.h b/src/mono/mono/metadata/reflection.h index 83bcfccd657bf..bab5586a8d7f5 100644 --- a/src/mono/mono/metadata/reflection.h +++ b/src/mono/mono/metadata/reflection.h @@ -27,7 +27,7 @@ typedef struct { #define MONO_SIZEOF_CUSTOM_ATTR_INFO (offsetof (MonoCustomAttrInfo, attrs)) -/* +/* * Information which isn't in the MonoMethod structure is stored here for * dynamic methods. */ diff --git a/src/mono/mono/metadata/row-indexes.h b/src/mono/mono/metadata/row-indexes.h index b0f5dc072d681..64534db11373e 100644 --- a/src/mono/mono/metadata/row-indexes.h +++ b/src/mono/mono/metadata/row-indexes.h @@ -306,7 +306,7 @@ enum { MONO_GENERICPARAM_FLAGS, MONO_GENERICPARAM_OWNER, MONO_GENERICPARAM_NAME, - + MONO_GENERICPARAM_SIZE }; diff --git a/src/mono/mono/metadata/runtime.c b/src/mono/mono/metadata/runtime.c index a71933874505e..81e74c4be8d66 100644 --- a/src/mono/mono/metadata/runtime.c +++ b/src/mono/mono/metadata/runtime.c @@ -66,7 +66,7 @@ mono_runtime_fire_process_exit_event (void) MONO_STATIC_POINTER_INIT_END (MonoMethod, procexit_method) g_assert (procexit_method); - + mono_runtime_try_invoke (procexit_method, NULL, NULL, &exc, error); #endif } diff --git a/src/mono/mono/metadata/seq-points-data.c b/src/mono/mono/metadata/seq-points-data.c index 308435993793c..fa80737f1e2b3 100644 --- a/src/mono/mono/metadata/seq-points-data.c +++ b/src/mono/mono/metadata/seq-points-data.c @@ -405,7 +405,7 @@ mono_seq_point_data_read (SeqPointData *data, char *path) fclose (f); return FALSE; } - + fseek(f, 0, SEEK_SET); buffer_orig = buffer = (guint8 *)g_malloc (fsize + 1); diff --git a/src/mono/mono/metadata/seq-points-data.h b/src/mono/mono/metadata/seq-points-data.h index 4b9c1d0d479f8..575e0f815fdc9 100644 --- a/src/mono/mono/metadata/seq-points-data.h +++ b/src/mono/mono/metadata/seq-points-data.h @@ -3,7 +3,7 @@ * Copyright 2015 Xamarin Inc * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ - + #ifndef __MONO_SEQ_POINTS_DATA_H__ #define __MONO_SEQ_POINTS_DATA_H__ @@ -21,7 +21,7 @@ #define SEQ_POINT_AOT_EXT ".msym" /* Native offset used to mark seq points in dead code */ -#define SEQ_POINT_NATIVE_OFFSET_DEAD_CODE -1 +#define SEQ_POINT_NATIVE_OFFSET_DEAD_CODE -1 typedef struct { int il_offset, native_offset, flags; diff --git a/src/mono/mono/metadata/sgen-bridge.h b/src/mono/mono/metadata/sgen-bridge.h index 3f11c11bcb09f..0b91359064d97 100644 --- a/src/mono/mono/metadata/sgen-bridge.h +++ b/src/mono/mono/metadata/sgen-bridge.h @@ -1,7 +1,7 @@ /** * \file * Copyright 2011 Novell, Inc. - * + * * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ @@ -57,7 +57,7 @@ MONO_BEGIN_DECLS enum { SGEN_BRIDGE_VERSION = 5 }; - + typedef enum { /* Instances of this class should be scanned when computing the transitive dependency among bridges. E.g. List*/ GC_BRIDGE_TRANSPARENT_CLASS, diff --git a/src/mono/mono/metadata/sgen-client-mono.h b/src/mono/mono/metadata/sgen-client-mono.h index f69e05904f6df..bb54b33d0a248 100644 --- a/src/mono/mono/metadata/sgen-client-mono.h +++ b/src/mono/mono/metadata/sgen-client-mono.h @@ -697,7 +697,7 @@ sgen_client_binary_protocol_ephemeron_ref (gpointer list, gpointer key, gpointer /* Enter must be visible before anything is done in the critical region. */ #define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0) -/* Exit must make sure all critical regions stores are visible before it signal the end of the region. +/* Exit must make sure all critical regions stores are visible before it signal the end of the region. * We don't need to emit a full barrier since we */ #define EXIT_CRITICAL_REGION do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0) diff --git a/src/mono/mono/metadata/sgen-mono-ilgen.c b/src/mono/mono/metadata/sgen-mono-ilgen.c index aa5e034dbc6f9..734e2a4f9f5da 100644 --- a/src/mono/mono/metadata/sgen-mono-ilgen.c +++ b/src/mono/mono/metadata/sgen-mono-ilgen.c @@ -295,7 +295,7 @@ emit_managed_allocator_ilgen (MonoMethodBuilder *mb, gboolean slowpath, gboolean * * offsetof (MonoString, chars) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1) * len <= (SIZE_MAX - (SGEN_ALLOC_ALIGN - 1) - offsetof (MonoString, chars)) / 2 - 1 - * + * * On 64-bit platforms SIZE_MAX is so big that the 32-bit string length can * never reach the maximum size. */ @@ -372,7 +372,7 @@ emit_managed_allocator_ilgen (MonoMethodBuilder *mb, gboolean slowpath, gboolean mono_mb_emit_no_nullcheck (mb); mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, p_var); - + /* new_next = (char*)p + size; */ new_next_var = mono_mb_add_local (mb, int_type); mono_mb_emit_ldloc (mb, p_var); diff --git a/src/mono/mono/metadata/sgen-old-bridge.c b/src/mono/mono/metadata/sgen-old-bridge.c index b9ef527dd42fe..c3650a769343d 100644 --- a/src/mono/mono/metadata/sgen-old-bridge.c +++ b/src/mono/mono/metadata/sgen-old-bridge.c @@ -313,15 +313,15 @@ dyn_array_int_merge (DynIntArray *dst, DynIntArray *src) for (i = j = 0; i < dyn_array_int_size (dst) || j < dyn_array_int_size (src); ) { if (i < dyn_array_int_size (dst) && j < dyn_array_int_size (src)) { - int a = dyn_array_int_get (dst, i); - int b = dyn_array_int_get (src, j); + int a = dyn_array_int_get (dst, i); + int b = dyn_array_int_get (src, j); if (a < b) { dyn_array_int_add (&merge_array, a); ++i; } else if (a == b) { dyn_array_int_add (&merge_array, a); ++i; - ++j; + ++j; } else { dyn_array_int_add (&merge_array, b); ++j; diff --git a/src/mono/mono/metadata/sgen-tarjan-bridge.c b/src/mono/mono/metadata/sgen-tarjan-bridge.c index c5a7f876502d0..f956277b0efb2 100644 --- a/src/mono/mono/metadata/sgen-tarjan-bridge.c +++ b/src/mono/mono/metadata/sgen-tarjan-bridge.c @@ -978,7 +978,7 @@ step_timer (gint64 *timer) { gint64 curtime, diff; - SGEN_TV_GETTIME (curtime); + SGEN_TV_GETTIME (curtime); diff = SGEN_TV_ELAPSED (*timer, curtime); *timer = curtime; return diff; diff --git a/src/mono/mono/metadata/sgen-toggleref.h b/src/mono/mono/metadata/sgen-toggleref.h index a2d5ce2aa7902..77b622bed79a8 100644 --- a/src/mono/mono/metadata/sgen-toggleref.h +++ b/src/mono/mono/metadata/sgen-toggleref.h @@ -6,7 +6,7 @@ * * Author: * Rodrigo Kumpera (kumpera@gmail.com) - * + * * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ diff --git a/src/mono/mono/metadata/sre-encode.c b/src/mono/mono/metadata/sre-encode.c index 450b6f37d72d3..4bcbbf7683c4b 100644 --- a/src/mono/mono/metadata/sre-encode.c +++ b/src/mono/mono/metadata/sre-encode.c @@ -2,8 +2,8 @@ * \file * Routines for encoding SRE builders into a * MonoDynamicImage and generating tokens. - * - * + * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -161,7 +161,7 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) g_assert_not_reached (); return; } - + if (m_type_is_byref (type)) sigbuffer_add_value (buf, MONO_TYPE_BYREF); @@ -343,13 +343,13 @@ mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, Mono break; case MONO_TYPE_VALUETYPE: { MonoClass *klass = val->vtable->klass; - + if (m_class_is_enumtype (klass)) { *ret_type = mono_class_enum_basetype_internal (klass)->type; goto handle_enum; } else if (mono_is_corlib_image (m_class_get_image (klass)) && strcmp (m_class_get_name_space (klass), "System") == 0 && strcmp (m_class_get_name (klass), "DateTime") == 0) { len = 8; - } else + } else g_error ("we can't encode valuetypes, we should have never reached this line"); break; } @@ -438,7 +438,7 @@ mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType * /* * If it's in the same module and not a generic type parameter: */ - if ((m_class_get_image (klass) == &assembly->image) && (type->type != MONO_TYPE_VAR) && + if ((m_class_get_image (klass) == &assembly->image) && (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) { token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS); /* This function is called multiple times from sre and sre-save, so same object is okay */ diff --git a/src/mono/mono/metadata/sre-internals.h b/src/mono/mono/metadata/sre-internals.h index b602748833cf6..356e0c43fb764 100644 --- a/src/mono/mono/metadata/sre-internals.h +++ b/src/mono/mono/metadata/sre-internals.h @@ -100,7 +100,7 @@ mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, gboolean mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error); - + guint32 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image); diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index 912c4a9e94578..62254b3fa2c3e 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -2,8 +2,8 @@ * \file * Routines for creating an image at runtime * and related System.Reflection.Emit icalls - * - * + * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -139,7 +139,7 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) MonoAssembly *ta; klass = mono_class_from_mono_type_internal (type); - if (!klass) + if (!klass) return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION); ta = klass->image->assembly; if (assembly_is_dynamic (ta) || (ta == ass)) { @@ -381,7 +381,7 @@ method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflect #ifndef DISABLE_REFLECTION_EMIT /* - * LOCKING: Acquires the loader lock. + * LOCKING: Acquires the loader lock. */ static void mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs) @@ -440,7 +440,7 @@ mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoIma return token; } - + if (assembly_is_dynamic (image->assembly)) /* FIXME: */ memset (cols, 0, sizeof (cols)); @@ -624,7 +624,7 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono rmb->mhandle = mb->mhandle; rmb->nrefs = 0; rmb->refs = NULL; -} +} #else /* DISABLE_REFLECTION_EMIT */ gboolean mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) { @@ -678,14 +678,14 @@ mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, guint32 token; MonoMethodSignature *sig; - + create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image; if (create_typespec) { token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1))); if (token) return token; - } + } token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method)); if (token && !create_typespec) @@ -723,7 +723,7 @@ mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 origina { MonoDynamicTable *table; guint32 token; - + table = &assembly->tables [MONO_TABLE_MEMBERREF]; token = MONO_TOKEN_MEMBER_REF | table->next_idx; table->next_idx ++; @@ -801,7 +801,7 @@ mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method) { MonoMethodInflated *imethod; guint32 token; - + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method)); if (token) return token; @@ -825,7 +825,7 @@ mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m) return mono_image_get_memberref_token (assembly, m_class_get_byval_arg (m->klass)); } -static guint32 +static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error) { guint32 idx; @@ -911,7 +911,7 @@ mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMetho am = NULL; for (GList *tmp = assembly->array_methods; tmp; tmp = tmp->next) { am = (ArrayMethod *)tmp->data; - if (strcmp (name, am->name) == 0 && + if (strcmp (name, am->name) == 0 && mono_metadata_type_equal (am->parent, mtype) && mono_metadata_signature_equal (am->sig, sig)) { g_free (name); @@ -1040,15 +1040,15 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj * mono_image_create_token: * @assembly: a dynamic assembly * @obj: - * @register_token: Whenever to register the token in the assembly->tokens hash. + * @register_token: Whenever to register the token in the assembly->tokens hash. * * Get a token to insert in the IL code stream for the given MemberInfo. - * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, - * the table_idx-es were recomputed, so registering the token would overwrite an existing + * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, + * the table_idx-es were recomputed, so registering the token would overwrite an existing * entry. */ guint32 -mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj, +mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj, gboolean create_open_instance, gboolean register_token, MonoError *error) { @@ -1215,14 +1215,14 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb, M MonoDynamicAssembly *assembly; MonoDynamicImage *image; MonoAssemblyLoadContext *alc = mono_alc_get_default (); - + if (assemblyb->dynamic_assembly) return; assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1); MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly)); - + assembly->assembly.ref_count = 1; assembly->assembly.dynamic = TRUE; assemblyb->assembly.assembly = (MonoAssembly*)assembly; @@ -1271,9 +1271,9 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb, M mono_alc_add_assembly (alc, (MonoAssembly*)assembly); register_assembly (&assemblyb->assembly, &assembly->assembly); - + MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly)); - + mono_assembly_invoke_load_hook_internal (alc, (MonoAssembly*)assembly); } @@ -1287,7 +1287,7 @@ image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *e if (!image) { /* * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but - * we don't know which module it belongs to, since that is only + * we don't know which module it belongs to, since that is only * determined at assembly save time. */ /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */ @@ -1993,7 +1993,7 @@ encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuf { const char *argval = (const char*)void_argval; MonoTypeEnum simple_type; - + error_init (error); if ((p-buffer) + 10 >= *buflen) { char *newbuf; @@ -2163,7 +2163,7 @@ MONO_DISABLE_WARNING(4309) // truncation of constant MONO_RESTORE_WARNING break; } - + klass = mono_object_class (arg); if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) { @@ -2537,7 +2537,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb guint32 table_idx; table_idx = MONO_HANDLE_GETVAL (ref_tb, table_idx); /* - * The size calculation here warrants some explaining. + * The size calculation here warrants some explaining. * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF, * meaning we need to alloc enough space to morth a def into a gtd. */ @@ -2554,7 +2554,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb goto_if_nok (error, leave); klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx; mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs)); - + MONO_PROFILER_RAISE (class_loading, (klass)); klass->element_class = klass; @@ -2649,7 +2649,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/ MONO_PROFILER_RAISE (class_loaded, (klass)); - + leave: mono_loader_unlock (); HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); @@ -2790,7 +2790,7 @@ mono_reflection_marshal_as_attribute_from_marshal_spec (MonoClass *klass, MonoMarshalSpec *spec, MonoError *error) { error_init (error); - + MonoAssemblyLoadContext *alc = mono_alc_get_ambient (); MonoReflectionMarshalAsAttributeHandle minfo = MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, mono_object_new_handle (mono_class_get_marshal_as_attribute_class (), error)); goto_if_nok (error, fail); @@ -2909,7 +2909,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, mono_error_assert_ok (error); method_aux->dll = string_to_utf8_image_raw (image, rmb->dll, error); mono_error_assert_ok (error); - + ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags; if (image_is_dynamic (klass->image)) @@ -2938,7 +2938,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, code = mono_array_addr_internal (rmb->code, guint8, 0); code_size = mono_array_length_internal (rmb->code); /* we probably need to run a verifier on the code... */ - max_stack = 8; + max_stack = 8; } else { code = NULL; @@ -2956,7 +2956,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, header->num_locals = num_locals; for (i = 0; i < num_locals; ++i) { - MonoReflectionLocalBuilder *lb = + MonoReflectionLocalBuilder *lb = mono_array_get_internal (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i); header->locals [i] = image_g_new0 (image, MonoType, 1); @@ -3095,14 +3095,14 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, } /* Parameter marshalling */ - if (rmb->pinfo) + if (rmb->pinfo) for (i = 0; i < mono_array_length_internal (rmb->pinfo); ++i) { MonoReflectionParamBuilder *pb; if ((pb = mono_array_get_internal (rmb->pinfo, MonoReflectionParamBuilder*, i))) { if (pb->marshal_info) { if (specs == NULL) specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1); - specs [pb->position] = + specs [pb->position] = mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error); goto_if_nok (error, fail); } @@ -3126,7 +3126,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, fail: m = NULL; goto leave; -} +} static MonoMethod* ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error) @@ -3374,7 +3374,7 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error) return FALSE; klass->methods [j++] = meth; } - + if (tb->interfaces) { klass->interface_count = mono_array_length_internal (tb->interfaces); klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count); @@ -3402,7 +3402,7 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error) if (!(im->flags & METHOD_ATTRIBUTE_STATIC)) im->slot = slot_num++; } - + klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/ mono_class_setup_interface_offsets (klass); mono_class_setup_interface_id (klass); @@ -3410,12 +3410,12 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error) /* * The generic vtable is needed even if image->run is not set since some - * runtime code like ves_icall_Type_GetMethodsByName depends on + * runtime code like ves_icall_Type_GetMethodsByName depends on * method->slot being defined. */ - /* - * tb->methods could not be freed since it is used for determining + /* + * tb->methods could not be freed since it is used for determining * overrides during dynamic vtable construction. */ @@ -3470,7 +3470,7 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides onum = 0; if (tb->methods) { for (i = 0; i < tb->num_methods; ++i) { - MonoReflectionMethodBuilder *mb = + MonoReflectionMethodBuilder *mb = mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i); if (mb->override_methods) onum += mono_array_length_internal (mb->override_methods); @@ -3482,7 +3482,7 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides onum = 0; for (i = 0; i < tb->num_methods; ++i) { - MonoReflectionMethodBuilder *mb = + MonoReflectionMethodBuilder *mb = mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i); if (mb->override_methods) { for (j = 0; j < mono_array_length_internal (mb->override_methods); ++j) { @@ -3556,6 +3556,11 @@ typebuilder_setup_one_field (MonoDynamicImage *dynamic_image, MonoClass *klass, } } + if (m_type_is_byref (field->type) && !m_class_is_byreflike (klass)) { + mono_error_set_type_load_name (error, NULL, NULL, "Field '%s' is a byref in a non-byref-like type", field->name); + goto leave; + } + if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) { char *base = mono_array_addr_internal (rva_data, char, 0); size_t size = mono_array_length_internal (rva_data); @@ -3622,7 +3627,7 @@ typebuilder_setup_fields (MonoClass *klass, MonoError *error) packing_size = tb->packing_size; instance_size += tb->class_size; } - + klass->fields = image_g_new0 (image, MonoClassField, fcount); def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount); mono_class_set_field_def_values (klass, def_values); @@ -3738,7 +3743,7 @@ typebuilder_setup_events (MonoClass *klass, MonoError *error) int j; events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length_internal (eb->other_methods) + 1); for (j = 0; j < mono_array_length_internal (eb->other_methods); ++j) { - MonoReflectionMethodBuilder *mb = + MonoReflectionMethodBuilder *mb = mono_array_get_internal (eb->other_methods, MonoReflectionMethodBuilder*, j); events [i].other [j] = mb->mhandle; @@ -3857,6 +3862,12 @@ ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_ mono_class_setup_supertypes (klass); mono_class_setup_mono_type (klass); + /* Check if the type is marked as byreflike. + * The IsByRefLike attribute only applies to value types and enums. This matches CoreCLR behavior. + */ + if (klass->enumtype || klass->valuetype) + klass->is_byreflike = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_tb), is_byreflike_set); + /* enums are done right away */ if (!klass->enumtype) if (!ensure_runtime_vtable (klass, error)) @@ -3910,9 +3921,9 @@ ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_ } } - /* + /* * If we are a generic TypeBuilder, there might be instantiations in the type cache - * which have type System.Reflection.MonoGenericClass, but after the type is created, + * which have type System.Reflection.MonoGenericClass, but after the type is created, * we want to return normal System.MonoType objects, so clear these out from the cache. * * Together with this we must ensure the contents of all instances to match the created type. @@ -3957,7 +3968,7 @@ typedef struct { /* * The runtime automatically clean up those after finalization. -*/ +*/ static MonoReferenceQueue *dynamic_method_queue; static void @@ -4013,7 +4024,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono /* * Resolve references. */ - /* + /* * Every second entry in the refs array is reserved for storing handle_class, * which is needed by the ldtoken implementation in the JIT. */ @@ -4030,7 +4041,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono /* * The referenced DynamicMethod should already be created by the managed * code, except in the case of circular references. In that case, we store - * method in the refs array, and fix it up later when the referenced + * method in the refs array, and fix it up later when the referenced * DynamicMethod is created. */ if (method->mhandle) { @@ -4060,7 +4071,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono rmb.refs [i] = ref; rmb.refs [i + 1] = handle_class; - } + } if (mb->owner) { MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error); @@ -4090,7 +4101,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data; MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle; gpointer *data; - + g_assert (method->mhandle); data = (gpointer*)wrapper->method_data; diff --git a/src/mono/mono/metadata/sysmath.c b/src/mono/mono/metadata/sysmath.c index e8fef9f8e08e9..ec25a20fc0025 100644 --- a/src/mono/mono/metadata/sysmath.c +++ b/src/mono/mono/metadata/sysmath.c @@ -1,6 +1,6 @@ /** * \file - * these are based on bob smith's csharp routines + * these are based on bob smith's csharp routines * * Author: * Mono Project (http://www.mono-project.com) @@ -55,49 +55,49 @@ ves_icall_System_Math_ModF (gdouble x, gdouble *d) return modf (x, d); } -gdouble +gdouble ves_icall_System_Math_Sin (gdouble x) { return sin (x); } -gdouble +gdouble ves_icall_System_Math_Cos (gdouble x) { return cos (x); } -gdouble +gdouble ves_icall_System_Math_Cbrt (gdouble x) { return cbrt (x); } -gdouble +gdouble ves_icall_System_Math_Tan (gdouble x) { return tan (x); } -gdouble +gdouble ves_icall_System_Math_Sinh (gdouble x) { return sinh (x); } -gdouble +gdouble ves_icall_System_Math_Cosh (gdouble x) { return cosh (x); } -gdouble +gdouble ves_icall_System_Math_Tanh (gdouble x) { return tanh (x); } -gdouble +gdouble ves_icall_System_Math_Acos (gdouble x) { return acos (x); @@ -109,78 +109,66 @@ ves_icall_System_Math_Acosh (gdouble x) return acosh (x); } -gdouble +gdouble ves_icall_System_Math_Asin (gdouble x) { return asin (x); } -gdouble +gdouble ves_icall_System_Math_Asinh (gdouble x) { return asinh (x); } -gdouble +gdouble ves_icall_System_Math_Atan (gdouble x) { return atan (x); } -gdouble +gdouble ves_icall_System_Math_Atan2 (gdouble y, gdouble x) { return atan2 (y, x); } -gdouble +gdouble ves_icall_System_Math_Atanh (gdouble x) { return atanh (x); } -gdouble +gdouble ves_icall_System_Math_Exp (gdouble x) { return exp (x); } -gdouble +gdouble ves_icall_System_Math_Log (gdouble x) { return log (x); } -gdouble +gdouble ves_icall_System_Math_Log10 (gdouble x) { return log10 (x); } -gdouble +gdouble ves_icall_System_Math_Pow (gdouble x, gdouble y) { return pow (x, y); } -gdouble +gdouble ves_icall_System_Math_Sqrt (gdouble x) { return sqrt (x); } -gdouble -ves_icall_System_Math_Abs_double (gdouble v) -{ - return fabs (v); -} - -float -ves_icall_System_Math_Abs_single (float v) -{ - return fabsf (v); -} - gdouble ves_icall_System_Math_Ceiling (gdouble v) { diff --git a/src/mono/mono/metadata/tabledefs.h b/src/mono/mono/metadata/tabledefs.h index 6cfc4c8ffe756..52521435fc3b5 100644 --- a/src/mono/mono/metadata/tabledefs.h +++ b/src/mono/mono/metadata/tabledefs.h @@ -10,12 +10,12 @@ * * From the ECMA documentation */ - + #ifndef _MONO_METADATA_TABLEDEFS_H_ #define _MONO_METADATA_TABLEDEFS_H_ /* - * 22.1.1 Values for AssemblyHashAlgorithm + * 22.1.1 Values for AssemblyHashAlgorithm */ enum { @@ -42,7 +42,7 @@ enum { FILE_CONTAINS_NO_METADATA = 1 }; -/* keep in synch with System.Security.Permissions.SecurityAction enum +/* keep in synch with System.Security.Permissions.SecurityAction enum (except for the special non-CAS cases) */ enum { SECURITY_ACTION_DEMAND = 2, diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index 862a3437f82ce..4f9d15fcd8a5e 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -680,6 +680,9 @@ mono_thread_internal_set_priority (MonoInternalThread *internal, MonoThreadPrior // When this API becomes available on an arbitrary thread, we can use it, // not available on current Zircon // +#elif HOST_WASI + // Thread scheduling isn't yet implemented in the WASI build + return; #else /* !HOST_WIN32 and not HOST_FUCHSIA */ pthread_t tid; int policy; diff --git a/src/mono/mono/metadata/tokentype.h b/src/mono/mono/metadata/tokentype.h index a1c58944d7404..c7ae1178aff74 100644 --- a/src/mono/mono/metadata/tokentype.h +++ b/src/mono/mono/metadata/tokentype.h @@ -9,13 +9,13 @@ * These tokens match the table ID except for the last * three (string, name and base type which are special) */ - + typedef enum { MONO_TOKEN_MODULE = 0x00000000, MONO_TOKEN_TYPE_REF = 0x01000000, MONO_TOKEN_TYPE_DEF = 0x02000000, MONO_TOKEN_FIELD_DEF = 0x04000000, - MONO_TOKEN_METHOD_DEF = 0x06000000, + MONO_TOKEN_METHOD_DEF = 0x06000000, MONO_TOKEN_PARAM_DEF = 0x08000000, MONO_TOKEN_INTERFACE_IMPL = 0x09000000, MONO_TOKEN_MEMBER_REF = 0x0a000000, diff --git a/src/mono/mono/metadata/verify.h b/src/mono/mono/metadata/verify.h index 9ec9f2e07d2ac..6efb0fd3373b1 100644 --- a/src/mono/mono/metadata/verify.h +++ b/src/mono/mono/metadata/verify.h @@ -23,7 +23,7 @@ typedef enum { MONO_VERIFY_NOT_VERIFIABLE = 8, /*OR it with other flags*/ - + /* Abort the verification if the code is not verifiable. * The standard behavior is to abort if the code is not valid. * */ diff --git a/src/mono/mono/metadata/w32file-unix.c b/src/mono/mono/metadata/w32file-unix.c index 50da28bf8468b..ee1e2fe89d557 100644 --- a/src/mono/mono/metadata/w32file-unix.c +++ b/src/mono/mono/metadata/w32file-unix.c @@ -298,7 +298,7 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir, } else { dirname = g_strdup (dir); } - + if (_wapi_access (dirname, F_OK) == 0) { mono_w32error_set_last (ERROR_FILE_NOT_FOUND); } else { @@ -316,18 +316,18 @@ file_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * { gint ret; MonoThreadInfo *info = mono_thread_info_current (); - + if(byteswritten!=NULL) { *byteswritten=0; } - + if(!(filehandle->fileaccess & GENERIC_WRITE) && !(filehandle->fileaccess & GENERIC_ALL)) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - + do { MONO_ENTER_GC_SAFE; ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); @@ -340,7 +340,7 @@ file_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * ret = 0; } else { _wapi_set_last_error_from_errno (); - + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); @@ -357,18 +357,18 @@ console_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint3 { gint ret; MonoThreadInfo *info = mono_thread_info_current (); - + if(byteswritten!=NULL) { *byteswritten=0; } - + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - + do { MONO_ENTER_GC_SAFE; ret = write(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); @@ -381,7 +381,7 @@ console_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint3 ret = 0; } else { _wapi_set_last_error_from_errno (); - + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); @@ -390,7 +390,7 @@ console_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint3 if(byteswritten!=NULL) { *byteswritten=ret; } - + return(TRUE); } @@ -399,18 +399,18 @@ pipe_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * { gint ret; MonoThreadInfo *info = mono_thread_info_current (); - + if(byteswritten!=NULL) { *byteswritten=0; } - + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd); do { @@ -425,7 +425,7 @@ pipe_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * ret = 0; } else { _wapi_set_last_error_from_errno (); - + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: write of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); @@ -434,14 +434,14 @@ pipe_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * if(byteswritten!=NULL) { *byteswritten=ret; } - + return(TRUE); } static gint convert_flags(guint32 fileaccess, guint32 createmode) { gint flags=0; - + switch(fileaccess) { case GENERIC_READ: flags=O_RDONLY; @@ -478,7 +478,7 @@ static gint convert_flags(guint32 fileaccess, guint32 createmode) createmode); break; } - + return(flags); } @@ -490,7 +490,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, guint32 file_existing_share, file_existing_access; file_already_shared = file_share_get (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info); - + if (file_already_shared) { /* The reference to this share info was incremented * when we looked it up, so be careful to put it back @@ -502,7 +502,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, file_share_release (*share_info); *share_info = NULL; - + return(FALSE); } @@ -515,7 +515,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, file_share_release (*share_info); *share_info = NULL; - + return(FALSE); } } else { @@ -560,12 +560,12 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode if (attrs & FILE_ATTRIBUTE_TEMPORARY) perms = 0600; - + if (attrs & FILE_ATTRIBUTE_ENCRYPTED){ mono_w32error_set_last (ERROR_ENCRYPTION_FAILED); return INVALID_HANDLE_VALUE; } - + if (name == NULL) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: name is NULL", __func__); @@ -581,12 +581,12 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode mono_w32error_set_last (ERROR_INVALID_NAME); return(INVALID_HANDLE_VALUE); } - + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: Opening %s with share 0x%" PRIx32 " and access 0x%" PRIx32, __func__, filename, sharemode, fileaccess); - + fd = _wapi_open (filename, flags, perms); - + /* If we were trying to open a directory with write permissions * (e.g. O_WRONLY or O_RDWR), this call will fail with * EISDIR. However, this is a bit bogus because calls to @@ -600,7 +600,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode /* Try again but don't try to make it writable */ fd = _wapi_open (filename, flags & ~(O_RDWR|O_WRONLY), perms); } - + if (fd == -1) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: Error opening file %s: %s", __func__, filename, g_strerror(errno)); _wapi_set_last_path_error_from_errno (NULL, filename); @@ -647,7 +647,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode MONO_ENTER_GC_SAFE; close (((MonoFDHandle*) filehandle)->fd); MONO_EXIT_GC_SAFE; - + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return (INVALID_HANDLE_VALUE); } @@ -659,7 +659,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode MONO_ENTER_GC_SAFE; close (((MonoFDHandle*) filehandle)->fd); MONO_EXIT_GC_SAFE; - + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return(INVALID_HANDLE_VALUE); } diff --git a/src/mono/mono/metadata/w32handle.h b/src/mono/mono/metadata/w32handle.h index 6ec82b812e077..3ab448759ec0d 100644 --- a/src/mono/mono/metadata/w32handle.h +++ b/src/mono/mono/metadata/w32handle.h @@ -47,7 +47,7 @@ typedef enum { MONO_W32HANDLE_WAIT_RET_NOT_OWNED_BY_CALLER = -5 } MonoW32HandleWaitRet; -typedef struct +typedef struct { void (*close)(gpointer data); diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 175aa7759aad4..6ed23b463151d 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -46,7 +46,7 @@ if(HOST_WIN32) endif() # ICU -if(HAVE_SYS_ICU) +if(HAVE_SYS_ICU AND NOT HOST_WASI) if(STATIC_ICU) set(pal_icushim_sources_base pal_icushim_static.c) diff --git a/src/mono/mono/mini/abcremoval.c b/src/mono/mono/mini/abcremoval.c index ec87d201c06ee..6568a7003c540 100644 --- a/src/mono/mono/mini/abcremoval.c +++ b/src/mono/mono/mini/abcremoval.c @@ -148,7 +148,7 @@ print_evaluation_context_status (MonoRelationsEvaluationStatus status) { printf ("EVALUATION_NOT_STARTED"); } else { gboolean print_or = FALSE; - + printf ("("); if (status & MONO_RELATIONS_EVALUATION_IN_PROGRESS) { if (print_or) printf ("|"); @@ -257,7 +257,7 @@ get_relation_from_ins (MonoVariableRelationsEvaluationArea *area, MonoInst *ins, { MonoIntegerValueKind value_kind; MonoSummarizedValue *value = &result->related_value; - + if (ins->type == STACK_I8) { value_kind = MONO_INTEGER_VALUE_SIZE_8; } else if (ins->type == STACK_I4) { @@ -401,7 +401,7 @@ get_relation_from_ins (MonoVariableRelationsEvaluationArea *area, MonoInst *ins, * 462 i8const * 472 call */ - + break; } return value_kind; @@ -462,10 +462,10 @@ get_relations_from_previous_bb (MonoVariableRelationsEvaluationArea *area, MonoB relations->relation1.variable = -1; INITIALIZE_VALUE_RELATION (&(relations->relation2.relation)); relations->relation2.relation.relation_is_static_definition = FALSE; - relations->relation2.relation.next = NULL; + relations->relation2.relation.next = NULL; relations->relation2.insertion_point = NULL; relations->relation2.variable = -1; - + if (bb->in_count == 1) { /* Should write the code to "sum" conditions... */ in_bb = bb->in_bb [0]; @@ -527,7 +527,7 @@ static void apply_change_to_evaluation_area (MonoVariableRelationsEvaluationArea *area, MonoAdditionalVariableRelation *change) { MonoSummarizedValueRelation *base_relation; - + if (change->relation.relation != MONO_ANY_RELATION) { base_relation = &(area->relations [change->variable]); while ((base_relation->next != NULL) && (base_relation->next->relation_is_static_definition)) { @@ -698,24 +698,24 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are { MonoRelationsEvaluationContext * const context = &(area->contexts [variable]); MonoRelationsEvaluationStatus * const status = &(area->statuses [variable]); - + // First of all, we check the evaluation status // (what must be done is *very* different in each case) switch (*status) { case MONO_RELATIONS_EVALUATION_NOT_STARTED: { MonoSummarizedValueRelation *relation = &(area->relations [variable]); - + if (TRACE_ABC_REMOVAL) { printf ("Evaluating variable %d (target variable %d); ", variable, target_variable); print_summarized_value_relation (relation); printf ("\n"); } - + // We properly inizialize the context *status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; context->father = father_context; MONO_MAKE_RELATIONS_EVALUATION_RANGES_WEAK (context->ranges); - + // If we have found the target variable, we can set the range // related to it in the context to "equal" (which is [0,0]) if (variable == target_variable) { @@ -725,18 +725,18 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are context->ranges.variable.lower = 0; context->ranges.variable.upper = 0; } - + // Examine all relations for this variable (scan the list) // The contribute of each relation will be intersected (logical and) while (relation != NULL) { context->current_relation = relation; - + if (TRACE_ABC_REMOVAL) { printf ("Processing (%d): ", variable); print_summarized_value_relation (relation); printf ("\n"); } - + // We decie what to do according the the type of the related value switch (relation->related_value.type) { case MONO_ANY_SUMMARIZED_VALUE: @@ -749,13 +749,13 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are case MONO_VARIABLE_SUMMARIZED_VALUE: // Generally, evaluate related variable and intersect ranges. // However, some check is necessary... - + // If the relation is "ANY", nothing to do (no added information) if (relation->relation != MONO_ANY_RELATION) { int related_variable = relation->related_value.value.variable.variable; MonoRelationsEvaluationContext *related_context = &(area->contexts [related_variable]); MonoRelationsEvaluationStatus related_status = area->statuses [related_variable]; - + // The second condition in the "or" avoids messing with "back edges" in the graph traversal // (they are simply ignored instead of triggering the handling of recursion) if ( (related_status == MONO_RELATIONS_EVALUATION_NOT_STARTED) || ! @@ -763,14 +763,14 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are (related_context->current_relation->related_value.value.variable.variable == variable))) { // Evaluate the related variable evaluate_relation_with_target_variable (area, related_variable, target_variable, context); - + // Check if we are part of a recursive loop if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { printf ("Recursivity detected for variable %d (target variable %d), status ", variable, target_variable); print_evaluation_context_status (*status); } - + // If we are, check if the evaluation of the related variable is complete if (related_status == MONO_RELATIONS_EVALUATION_COMPLETED) { // If it is complete, we are part of a recursive definition. @@ -811,13 +811,13 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are int phi; gboolean is_ascending = FALSE; gboolean is_descending = FALSE; - + MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE (phi_ranges); phi_ranges.zero.nullness = relation->related_value.value.phi.number_of_alternatives > 0 ? MONO_VALUE_NOT_NULL : MONO_VALUE_MAYBE_NULL; for (phi = 0; phi < relation->related_value.value.phi.number_of_alternatives; phi++) { int phi_alternative = relation->related_value.value.phi.phi_alternatives [phi]; evaluate_relation_with_target_variable (area, phi_alternative, target_variable, context); - + // This means we are part of a recursive loop if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { @@ -836,7 +836,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are is_descending = TRUE; } phi_ranges.zero.nullness = MONO_VALUE_MAYBE_NULL; - + // Clear "recursivity" bits in the status (recursion has been handled) *status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; } else { @@ -844,7 +844,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are union_nullness (&phi_ranges.zero, area->contexts [phi_alternative].ranges.zero.nullness); } } - + // Apply the effects of all recursive loops if (is_ascending) { phi_ranges.zero.upper = INT_MAX; @@ -854,7 +854,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are phi_ranges.zero.lower = INT_MIN; phi_ranges.variable.lower = INT_MIN; } - + // Intersect final result MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION (context->ranges, phi_ranges); intersect_nullness (&context->ranges.zero, phi_ranges.zero.nullness, MONO_EQ_RELATION); @@ -863,11 +863,11 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are default: g_assert_not_reached(); } - + // Pass to next relation relation = relation->next; } - + // Check if any recursivity bits are still in the status, and in any case clear them if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { @@ -897,21 +897,21 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are gboolean evaluation_can_be_recursive = TRUE; gboolean evaluation_is_definition = TRUE; int path_value = 0; - + if (TRACE_ABC_REMOVAL) { printf ("Evaluation of variable %d (target variable %d) already in progress\n", variable, target_variable); print_evaluation_context (context, *status); print_summarized_value_relation (context->current_relation); printf ("\n"); } - + // We must check if the loop can be a recursive definition (we scan the whole loop) while (current_context != last_context) { if (current_context == NULL) { printf ("Broken recursive ring in ABC removal\n"); g_assert_not_reached (); } - + if (current_context->current_relation->relation_is_static_definition) { if (current_context->current_relation->related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) { /* No need to check path_value for over/under-flow, since delta should be safe */ @@ -923,10 +923,10 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are evaluation_is_definition = FALSE; evaluation_can_be_recursive = FALSE; } - + current_context = current_context->father; } - + // If this is a recursive definition, we properly flag the status in all the involved contexts if (evaluation_is_definition) { MonoRelationsEvaluationStatus recursive_status; @@ -941,13 +941,13 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are } else { recursive_status = MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE; } - + if (TRACE_ABC_REMOVAL) { printf ("Recursivity accepted ("); print_evaluation_context_status (recursive_status); printf (")\n"); } - + current_context = father_context; while (current_context != last_context) { int index = current_context - area->contexts; @@ -974,7 +974,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are } break; } - + } /* @@ -1032,9 +1032,9 @@ remove_abc_from_inst (MonoInst *ins, MonoVariableRelationsEvaluationArea *area) int index_variable = ins->sreg2; MonoRelationsEvaluationContext *array_context = &(area->contexts [array_variable]); MonoRelationsEvaluationContext *index_context = &(area->contexts [index_variable]); - + clean_contexts (area, area->cfg->next_vreg); - + evaluate_relation_with_target_variable (area, index_variable, array_variable, NULL); evaluate_relation_with_target_variable (area, array_variable, array_variable, NULL); @@ -1066,7 +1066,7 @@ eval_non_null (MonoVariableRelationsEvaluationArea *area, int reg) clean_contexts (area, area->cfg->next_vreg); evaluate_relation_with_target_variable (area, reg, reg, NULL); - + return context->ranges.zero.nullness == MONO_VALUE_NOT_NULL; } @@ -1107,7 +1107,7 @@ process_block (MonoCompile *cfg, MonoBasicBlock *bb, MonoVariableRelationsEvalua MonoAdditionalVariableRelationsForBB additional_relations; GSList *dominated_bb, *l; GSList *check_relations = NULL; - + if (TRACE_ABC_REMOVAL) { printf ("\nABCREM BLOCK/2 %d [dfn %d]...\n", bb->block_num, bb->dfn); } @@ -1141,7 +1141,7 @@ process_block (MonoCompile *cfg, MonoBasicBlock *bb, MonoVariableRelationsEvalua if (ins->opcode == OP_BOUNDS_CHECK) { /* Handle OP_LDELEMA2D, too */ array_var = ins->sreg1; index_var = ins->sreg2; - + remove_abc_from_inst (ins, area); /* We can derive additional relations from the bounds check */ @@ -1229,15 +1229,15 @@ process_block (MonoCompile *cfg, MonoBasicBlock *bb, MonoVariableRelationsEvalua } */ } - } - + } + for (dominated_bb = bb->dominated; dominated_bb != NULL; dominated_bb = dominated_bb->next) { process_block (cfg, (MonoBasicBlock*) (dominated_bb->data), area); } for (l = check_relations; l; l = l->next) remove_change_from_evaluation_area ((MonoAdditionalVariableRelation *)l->data); - + remove_change_from_evaluation_area (&(additional_relations.relation1)); remove_change_from_evaluation_area (&(additional_relations.relation2)); } @@ -1295,7 +1295,7 @@ type_to_value_kind (MonoType *type) * - Allocate memory for the evaluation contexts in the evaluation area * - Recursively process all the BBs in the dominator tree (it is enough * to invoke the processing on the entry BB) - * + * * cfg: the method code */ void @@ -1304,7 +1304,7 @@ mono_perform_abc_removal (MonoCompile *cfg) MonoVariableRelationsEvaluationArea area; MonoBasicBlock *bb; int i; - + verbose_level = cfg->verbose_level; area.cfg = cfg; @@ -1338,7 +1338,7 @@ mono_perform_abc_removal (MonoCompile *cfg) for (ins = bb->code; ins; ins = ins->next) { const char *spec = INS_INFO (ins->opcode); gint32 idx, *reg; - + if (spec [MONO_INST_DEST] == ' ' || MONO_IS_STORE_MEMBASE (ins)) continue; @@ -1371,7 +1371,7 @@ mono_perform_abc_removal (MonoCompile *cfg) MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range); apply_value_kind_to_range (&range, area.variable_value_kind [ins->dreg]); apply_value_kind_to_range (&range, effective_value_kind); - + if (range.upper < INT_MAX) { type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation)); type_relation->relation = MONO_LE_RELATION; @@ -1414,17 +1414,17 @@ mono_perform_abc_removal (MonoCompile *cfg) if (area.relations [i].related_value.value.variable.nullness & MONO_VALUE_IS_VARIABLE) { symmetric_nullness = area.relations [i].related_value.value.variable.nullness; } - + area.relations [related_index].relation = MONO_EQ_RELATION; area.relations [related_index].relation_is_static_definition = TRUE; area.relations [related_index].related_value.type = MONO_VARIABLE_SUMMARIZED_VALUE; area.relations [related_index].related_value.value.variable.variable = i; area.relations [related_index].related_value.value.variable.delta = - area.relations [i].related_value.value.variable.delta; area.relations [related_index].related_value.value.variable.nullness = symmetric_nullness; - + area.relations [related_index].next = area.relations [related_variable].next; area.relations [related_variable].next = &(area.relations [related_index]); - + if (TRACE_ABC_REMOVAL) { printf ("Added symmetric summarized value for variable variable %d (to %d): ", i, related_variable); print_summarized_value (&(area.relations [related_index].related_value)); diff --git a/src/mono/mono/mini/abcremoval.h b/src/mono/mono/mini/abcremoval.h index 8bc91ad4d7053..585a9072fbca3 100644 --- a/src/mono/mono/mini/abcremoval.h +++ b/src/mono/mono/mini/abcremoval.h @@ -159,7 +159,7 @@ typedef struct MonoSummarizedValueRelation { * The bits are handled separately because the same evaluation context could * belong to more than one loop, so that each loop would set its bits. * After the backtracking, the bits are examined and a decision is taken. - * + * */ typedef enum { MONO_RELATIONS_EVALUATION_NOT_STARTED = 0, @@ -333,7 +333,7 @@ typedef struct MonoVariableRelationsEvaluationArea { * coming to dominate the running time of abcremoval. By * storing the statuses together, we can memset the entire * region. - */ + */ MonoRelationsEvaluationStatus *statuses; MonoRelationsEvaluationContext *contexts; diff --git a/src/mono/mono/mini/alias-analysis.c b/src/mono/mono/mini/alias-analysis.c index 522e62d850915..206c16274331d 100644 --- a/src/mono/mono/mini/alias-analysis.c +++ b/src/mono/mono/mini/alias-analysis.c @@ -53,8 +53,8 @@ lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr) } if (replaced_op != load->opcode) { - if (cfg->verbose_level > 2) - printf ("Incompatible load type: expected %s but got %s\n", + if (cfg->verbose_level > 2) + printf ("Incompatible load type: expected %s but got %s\n", mono_inst_name (replaced_op), mono_inst_name (load->opcode)); return FALSE; @@ -84,8 +84,8 @@ lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr) if (replaced_op != store->opcode) { - if (cfg->verbose_level > 2) - printf ("Incompatible store_reg type: expected %s but got %s\n", + if (cfg->verbose_level > 2) + printf ("Incompatible store_reg type: expected %s but got %s\n", mono_inst_name (replaced_op), mono_inst_name (store->opcode)); return FALSE; @@ -131,7 +131,7 @@ lower_store_imm (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr) #if TARGET_SIZEOF_VOID_P == 8 case OP_STORE_MEMBASE_IMM: -#endif +#endif case OP_STOREI8_MEMBASE_IMM: if (!is_long_stack_size (var->type)) { if (cfg->verbose_level > 2) printf ("Incompatible variable of size != 8\n"); diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 4a3ca8efe039c..7bc376cd3bf56 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3671,6 +3671,8 @@ encode_signature (MonoAotCompile *acfg, MonoMethodSignature *sig, guint8 *buf, g flags |= 0x20; if (sig->explicit_this) flags |= 0x40; + if (sig->pinvoke) + flags |= 0x80; flags |= (sig->call_convention & 0x0F); *p = flags; @@ -3772,6 +3774,9 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 encode_value (info->d.icall.jit_icall_id, p, &p); } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) { encode_method_ref (acfg, info->d.managed_to_native.method, p, &p); + } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT) { + encode_klass_ref (acfg, info->d.native_func.klass, p, &p); + encode_signature (acfg, info->d.native_func.sig, p, &p); } else { g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE); encode_method_ref (acfg, info->d.managed_to_native.method, p, &p); diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index c4b0b821a25dc..4bfbd29519977 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -184,12 +184,12 @@ static GHashTable *aot_modules; #define mono_aot_unlock() mono_os_mutex_unlock (&aot_mutex) static mono_mutex_t aot_mutex; -/* +/* * Maps assembly names to the mono_aot_module__info symbols in the * AOT modules registered by mono_aot_register_module (). */ static GHashTable *static_aot_modules; -/* +/* * Same as above, but tracks module that must be loaded before others are * This allows us to have a "container" module which contains resources for * other modules. Since it doesn't provide methods for a managed assembly, @@ -346,7 +346,7 @@ decode_value (guint8 *ptr, guint8 **rptr) { guint8 b = *ptr; gint32 len; - + if ((b & 0x80) == 0){ len = b; ++ptr; @@ -385,7 +385,7 @@ mono_aot_get_offset (guint32 *table, int index) guint8 *data_start, *p; guint32 *index32 = NULL; guint16 *index16 = NULL; - + /* noffsets = table [0]; */ group_size = table [1]; ngroups = table [2]; @@ -571,7 +571,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError if (is_not_anonymous) { gboolean is_method = decode_value (p, &p); - + if (is_method) { MonoMethod *method_def; g_assert (type == MONO_TYPE_MVAR); @@ -840,13 +840,14 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target guint32 flags; int i, gen_param_count = 0, param_count, call_conv; guint8 *p = buf; - gboolean hasthis, explicit_this, has_gen_params; + gboolean hasthis, explicit_this, has_gen_params, pinvoke; flags = *p; p ++; has_gen_params = (flags & 0x10) != 0; hasthis = (flags & 0x20) != 0; explicit_this = (flags & 0x40) != 0; + pinvoke = (flags & 0x80) != 0; call_conv = flags & 0x0F; if (has_gen_params) @@ -859,6 +860,7 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target sig->sentinelpos = -1; sig->hasthis = hasthis; sig->explicit_this = explicit_this; + sig->pinvoke = pinvoke; sig->call_convention = call_conv; sig->generic_param_count = gen_param_count; sig->ret = decode_type (module, p, &p, error); @@ -899,7 +901,7 @@ sig_matches_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guin MonoMethodSignature *sig; gboolean res; guint8 *p = buf; - + sig = decode_signature_with_target (module, mono_method_signature_internal (target), p, &p); res = sig && mono_metadata_signature_equal (mono_method_signature_internal (target), sig); g_free (sig); @@ -997,7 +999,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod ref->method = mono_marshal_get_stelemref (); } else if (subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF) { int kind; - + kind = decode_value (p, &p); ref->method = mono_marshal_get_virtual_stelemref_wrapper ((MonoStelemrefKind)kind); @@ -1127,6 +1129,14 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod if (subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) { MonoJitICallInfo *info = mono_find_jit_icall_info ((MonoJitICallId)decode_value (p, &p)); ref->method = mono_icall_get_wrapper_method (info); + } else if (subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT) { + MonoClass *klass = decode_klass_ref (module, p, &p, error); + if (!klass) + return FALSE; + MonoMethodSignature *sig = decode_signature (module, p, &p); + if (!sig) + return FALSE; + ref->method = mono_marshal_get_native_func_wrapper_indirect (klass, sig, TRUE); } else { m = decode_resolve_method_ref (module, p, &p, error); if (!m) @@ -1311,8 +1321,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod MonoGenericContext ctx; guint32 token_index; - /* - * These methods do not have a token which resolves them, so we + /* + * These methods do not have a token which resolves them, so we * resolve them immediately. */ klass = decode_klass_ref (module, p, &p, error); @@ -1339,11 +1349,11 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod if (FALSE && mono_class_is_ginst (klass)) { ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst; ctx.method_inst = NULL; - + ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, error); if (!ref->method) return FALSE; - } + } memset (&ctx, 0, sizeof (ctx)); @@ -1449,7 +1459,7 @@ find_symbol (MonoDl *module, gpointer *globals, const char *name, gpointer *valu int global_index; guint16 *table, *entry; guint16 table_size; - guint32 hash; + guint32 hash; char *symbol = (char*)name; #ifdef TARGET_MACH @@ -1906,7 +1916,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer return; if (assembly->image->aot_module) - /* + /* * Already loaded. This can happen because the assembly loading code might invoke * the assembly load hooks multiple times for the same assembly. */ @@ -2112,7 +2122,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer aname->culture = g_strdup (table); table += strlen (table) + 1; memcpy (aname->public_key_token, table, strlen (table) + 1); - table += strlen (table) + 1; + table += strlen (table) + 1; table = (char *)ALIGN_PTR_TO (table, 8); aname->flags = *(guint32*)table; @@ -2310,7 +2320,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer * mono_aot_register_module: * * This should be called by embedding code to register normal AOT modules statically linked - * into the executable. + * into the executable. * * \param aot_info the value of the 'mono_aot_module__info' global symbol from the AOT module. */ @@ -2451,7 +2461,7 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin *endbuf = buf; return TRUE; -} +} gpointer mono_aot_get_method_from_vt_slot (MonoVTable *vtable, int slot, MonoError *error) @@ -2524,7 +2534,7 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res) * using a cache stored in the AOT file. * Stores the resulting class in *KLASS if found, stores NULL otherwise. * - * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was + * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was * found. */ gboolean @@ -2624,7 +2634,7 @@ mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const ch } amodule_unlock (amodule); - + return TRUE; } @@ -2842,7 +2852,7 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoJitInfo *jinfo, /* Clear thumb flag */ code_start = (guint8*)(((gsize)code_start) & ~1); - fde = amodule->mono_eh_frame + table [(pos * 2) + 1]; + fde = amodule->mono_eh_frame + table [(pos * 2) + 1]; /* This won't overflow because there is +1 entry in the table */ fde_len = table [(pos * 2) + 2 + 1] - table [(pos * 2) + 1]; @@ -3272,7 +3282,7 @@ decode_exception_debug_info (MonoAotModule *amodule, int map_size = decode_value (p, &p); /* The GC map requires 4 bytes of alignment */ while ((guint64)(gsize)p % 4) - p ++; + p ++; jinfo->gc_info = p; p += map_size; } @@ -3282,7 +3292,7 @@ decode_exception_debug_info (MonoAotModule *amodule, if (!ji_to_amodule) ji_to_amodule = g_hash_table_new (NULL, NULL); g_hash_table_insert (ji_to_amodule, jinfo, amodule); - mono_aot_unlock (); + mono_aot_unlock (); } return jinfo; @@ -3644,7 +3654,7 @@ mono_aot_find_jit_info (MonoImage *image, gpointer addr) if ((guint8*)addr >= (guint8*)jinfo->code_start + jinfo->code_size) /* addr is in the padding between methods, see the adjustment of code_size in decode_exception_debug_info () */ return NULL; - + return jinfo; } @@ -3757,7 +3767,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin case MONO_PATCH_INFO_R4: case MONO_PATCH_INFO_R4_GOT: { guint32 val; - + ji->data.target = mono_mem_manager_alloc0 (mem_manager, sizeof (float)); val = decode_value (p, &p); *(float*)ji->data.target = *(float*)&val; @@ -3849,7 +3859,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin entry->data = (MonoJumpInfo *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo)); entry->data->type = (MonoJumpInfoType)((val >> 9) & 0xff); mono_error_cleanup (error); /* FIXME don't swallow the error */ - + res = decode_patch (aot_module, mp, entry->data, p, &p); if (!res) goto cleanup; @@ -3877,7 +3887,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin case MONO_PATCH_INFO_GSHAREDVT_METHOD: { MonoGSharedVtMethodInfo *info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc0 (mp, sizeof (MonoGSharedVtMethodInfo)); int i; - + info->method = decode_resolve_method_ref (aot_module, p, &p, error); mono_error_assert_ok (error); /* FIXME don't swallow the error */ @@ -4035,7 +4045,7 @@ register_jump_target_got_slot (MonoMethod *method, gpointer *got_slot) MonoMethod *shared_method = mini_method_to_shared (method); method = shared_method ? shared_method : method; - jit_mm = jit_mm_for_method (method); + jit_mm = jit_mm_for_method (method); jit_mm_lock (jit_mm); if (!jit_mm->jump_target_got_slot_hash) jit_mm->jump_target_got_slot_hash = g_hash_table_new (NULL, NULL); @@ -4243,7 +4253,7 @@ load_method (MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint } /** find_aot_method_in_amodule - * + * * \param code_amodule The AOT module containing the code pointer * \param method The method to find the code index for * \param hash_full The hash for the method @@ -4257,7 +4267,7 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui guint32 index; static guint32 n_extra_decodes; - // The AOT module containing the MonoMethod + // The AOT module containing the MonoMethod // The reference to the metadata amodule will differ among multiple dedup methods // which mangle to the same name but live in different assemblies. This leads to // the caching breaking. The solution seems to be to cache using the "metadata" amodule. @@ -4414,7 +4424,7 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule) int i; guint32 hash = mono_aot_method_hash (method); - /* Try the place we expect to have moved the method only + /* Try the place we expect to have moved the method only * We don't probe, as that causes hard-to-debug issues when we fail * to find the method */ if (container_amodule && mono_aot_can_dedup (method)) { @@ -4429,7 +4439,7 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule) if (index != 0xffffff) return index; - /* + /* * Try all other modules. * This is needed because generic instances klass->image points to the image * containing the generic definition, but the native code is generated to the @@ -4453,7 +4463,7 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule) break; } } - + g_ptr_array_free (modules, TRUE); return index; @@ -4687,7 +4697,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) if (method->is_inflated && !method->wrapper_type && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE) && !dedupable) { MonoMethod *orig_method = method; - /* + /* * For generic methods, we store the fully shared instance in place of the * original method. */ @@ -4754,7 +4764,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) if (!m) g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */ - /* + /* * Get the code for the instantiation which should be emitted into * the mscorlib aot image by the AOT compiler. */ @@ -4914,7 +4924,7 @@ mono_aot_is_got_entry (guint8 *code, guint8 *addr) mono_aot_lock (); g_hash_table_foreach (aot_modules, check_is_got_entry, &user_data); mono_aot_unlock (); - + return user_data.res; } @@ -4947,11 +4957,11 @@ find_aot_module (guint8 *code) user_data.addr = code; user_data.module = NULL; - + mono_aot_lock (); g_hash_table_foreach (aot_modules, find_aot_module_cb, &user_data); mono_aot_unlock (); - + return user_data.module; } @@ -5022,7 +5032,7 @@ mono_aot_plt_resolve (gpointer aot_module, host_mgreg_t *regs, guint8 *code, Mon using_gsharedvt = TRUE; #endif - /* + /* * Avoid calling resolve_patch_target in the full-aot case if possible, since * it would create a trampoline, and we don't need that. * We could do this only if the method does not need the special handling @@ -5163,7 +5173,7 @@ mono_aot_get_plt_entry (host_mgreg_t *regs, guint8 *code) while (target != NULL) { if ((target >= (guint8*)(amodule->plt)) && (target < (guint8*)(amodule->plt_end))) return target; - + // Add 4 since mono_arch_get_call_target assumes we're passing // the instruction after the actual branch instruction. target = mono_arch_get_call_target (target + 4); @@ -5223,7 +5233,7 @@ mono_create_ftnptr_malloc (guint8 *code) /* * load_function_full: * - * Load the function named NAME from the aot image. + * Load the function named NAME from the aot image. */ static gpointer load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **out_tinfo) @@ -5696,7 +5706,7 @@ get_numerous_trampoline (MonoAotTrampoline tramp_type, int n_got_slots, MonoAotM #define MONOTOUCH_TRAMPOLINES_ERROR "" #endif if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type]) { - g_error ("Ran out of trampolines of type %d in '%s' (limit %d)%s\n", + g_error ("Ran out of trampolines of type %d in '%s' (limit %d)%s\n", tramp_type, image ? image->name : MONO_ASSEMBLY_CORLIB_NAME, amodule->info.num_trampolines [tramp_type], MONOTOUCH_TRAMPOLINES_ERROR); } index = amodule->trampoline_index [tramp_type] ++; @@ -5789,7 +5799,7 @@ mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr) code = (guint8 *)get_numerous_trampoline (MONO_AOT_TRAMP_STATIC_RGCTX, 2, &amodule, &got_offset, NULL); amodule->got [got_offset] = ctx; - amodule->got [got_offset + 1] = addr; + amodule->got [got_offset + 1] = addr; } /* The caller expects an ftnptr */ @@ -6041,7 +6051,7 @@ mono_aot_get_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, buf = (void **)m_class_alloc0 (vtable->klass, (real_count + 1) * 2 * sizeof (gpointer)); index = 0; for (i = 0; i < count; ++i) { - MonoIMTCheckItem *item = imt_entries [i]; + MonoIMTCheckItem *item = imt_entries [i]; if (!item->is_equals) continue; @@ -6060,7 +6070,7 @@ mono_aot_get_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, } buf [(index * 2)] = NULL; buf [(index * 2) + 1] = fail_tramp; - + if (USE_PAGE_TRAMPOLINES) { code = get_new_imt_trampoline_from_page (buf); } else { @@ -6085,7 +6095,7 @@ mono_aot_get_gsharedvt_arg_trampoline (gpointer arg, gpointer addr) code = (guint8 *)get_numerous_trampoline (MONO_AOT_TRAMP_GSHAREDVT_ARG, 2, &amodule, &got_offset, NULL); amodule->got [got_offset] = arg; - amodule->got [got_offset + 1] = addr; + amodule->got [got_offset + 1] = addr; } /* The caller expects an ftnptr */ @@ -6130,7 +6140,7 @@ mono_aot_set_make_unreadable (gboolean unreadable) if (make_unreadable && !inited) { mono_counters_register ("AOT: pagefaults", MONO_COUNTER_JIT | MONO_COUNTER_INT, &n_pagefaults); - } + } } typedef struct { @@ -6179,7 +6189,7 @@ mono_aot_is_pagefault (void *ptr) if (!make_unreadable) return FALSE; - /* + /* * Not signal safe, but SIGSEGV's are synchronous, and * this is only turned on by a MONO_DEBUG option. */ @@ -6368,7 +6378,7 @@ mono_aot_get_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, { g_assert_not_reached (); return NULL; -} +} gpointer mono_aot_get_gsharedvt_arg_trampoline (gpointer arg, gpointer addr) diff --git a/src/mono/mono/mini/aot-runtime.h b/src/mono/mono/mini/aot-runtime.h index dff55a92563fa..4cb34374fe08b 100644 --- a/src/mono/mono/mini/aot-runtime.h +++ b/src/mono/mono/mini/aot-runtime.h @@ -11,7 +11,7 @@ #include "mini.h" /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 182 +#define MONO_AOT_FILE_VERSION 183 #define MONO_AOT_TRAMP_PAGE_SIZE 16384 diff --git a/src/mono/mono/mini/arch-stubs.c b/src/mono/mono/mini/arch-stubs.c index 853f92d5a52c0..bd09fb0066ae8 100644 --- a/src/mono/mono/mini/arch-stubs.c +++ b/src/mono/mono/mini/arch-stubs.c @@ -134,7 +134,7 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) return NULL; } -gpointer +gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { g_assert_not_reached (); diff --git a/src/mono/mono/mini/branch-opts.c b/src/mono/mono/mini/branch-opts.c index df8954784aefe..bdf889f57953e 100644 --- a/src/mono/mono/mini/branch-opts.c +++ b/src/mono/mono/mini/branch-opts.c @@ -19,7 +19,7 @@ /* * Returns true if @bb is a basic block which falls through the next block. - * TODO verify if it helps to check if the bb last ins is a branch to its successor. + * TODO verify if it helps to check if the bb last ins is a branch to its successor. */ static gboolean mono_bb_is_fall_through (MonoCompile *cfg, MonoBasicBlock *bb) @@ -30,7 +30,7 @@ mono_bb_is_fall_through (MonoCompile *cfg, MonoBasicBlock *bb) /* * Used by the arch code to replace the exception handling - * with a direct branch. This is safe to do if the + * with a direct branch. This is safe to do if the * exception object isn't used, no rethrow statement and * no filter statement (verify). * @@ -57,9 +57,9 @@ mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, con if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE && clause->data.catch_class && mono_class_is_assignable_from_internal (clause->data.catch_class, exclass)) { MonoBasicBlock *tbb; - /* get the basic block for the handler and + /* get the basic block for the handler and * check if the exception object is used. - * Flag is set during method_to_ir due to + * Flag is set during method_to_ir due to * pop-op is optmized away in codegen (burg). */ tbb = cfg->cil_offset_to_bb [clause->handler_offset]; @@ -69,7 +69,7 @@ mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, con /* Check if this catch clause is ok to optimize by * looking for the BB_EXCEPTION_UNSAFE in every BB that - * belongs to the same region. + * belongs to the same region. * * UNSAFE flag is set during method_to_ir (OP_RETHROW) */ @@ -93,11 +93,11 @@ mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, con jump->inst_i1 = (MonoInst *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst)); jump->inst_true_bb = targetbb; - if (cfg->verbose_level > 2) + if (cfg->verbose_level > 2) g_print ("found exception to optimize - returning branch to BB%d (%s) (instead of throw) for method %s:%s\n", targetbb->block_num, m_class_get_name (clause->data.catch_class), m_class_get_name (cfg->method->klass), cfg->method->name); return jump; - } + } return NULL; } else { @@ -168,7 +168,7 @@ br_to_br_un (int opcode) * mono_replace_ins: * * Replace INS with its decomposition which is stored in a series of bblocks starting - * at FIRST_BB and ending at LAST_BB. On enter, PREV points to the predecessor of INS. + * at FIRST_BB and ending at LAST_BB. On enter, PREV points to the predecessor of INS. * On return, it will be set to the last ins of the decomposition. */ void @@ -183,7 +183,7 @@ mono_replace_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst } if (first_bb == last_bb) { - /* + /* * Only one replacement bb, merge the code into * the current bb. */ @@ -295,7 +295,7 @@ mono_if_conversion (MonoCompile *cfg) // FIXME: Make this work with extended bblocks - /* + /* * This pass requires somewhat optimized IR code so it should be run after * local cprop/deadce. Also, it should be run before dominator computation, since * it changes control flow. @@ -349,7 +349,7 @@ mono_if_conversion (MonoCompile *cfg) true_bb = branch->inst_true_bb; false_bb = branch->inst_false_bb; - /* + /* * Check that bb1 and bb2 are 'simple' and both assign to the same * variable. */ @@ -364,7 +364,7 @@ mono_if_conversion (MonoCompile *cfg) for (tmp = ins1->next; tmp; tmp = tmp->next) if (!((tmp->opcode == OP_NOP) || (tmp->opcode == OP_IL_SEQ_POINT) || (tmp->opcode == OP_BR))) simple = FALSE; - + for (tmp = ins2->next; tmp; tmp = tmp->next) if (!((tmp->opcode == OP_NOP) || (tmp->opcode == OP_IL_SEQ_POINT) || (tmp->opcode == OP_BR))) simple = FALSE; @@ -549,7 +549,7 @@ mono_if_conversion (MonoCompile *cfg) continue; if (!(cfg->opt & MONO_OPT_DEADCE)) - /* + /* * It is possible that dreg is never set before, so we can't use * it as an sreg of the cmov instruction (#582322). */ @@ -618,10 +618,10 @@ mono_if_conversion (MonoCompile *cfg) (bb->region == bb->out_bb [0]->region)) { mono_merge_basic_blocks (cfg, bb, bb->out_bb [0]); - /* - * bbn might have fallen through to the next bb without a branch, + /* + * bbn might have fallen through to the next bb without a branch, * have to add one now (#474718). - * FIXME: Maybe need to do this more generally in + * FIXME: Maybe need to do this more generally in * merge_basic_blocks () ? */ if (!(bb->last_ins && MONO_IS_BRANCH_OP (bb->last_ins)) && bb->out_count) { @@ -717,7 +717,7 @@ mono_if_conversion (MonoCompile *cfg) mono_unlink_bblock (cfg, bb, branch1->inst_true_bb); mono_unlink_bblock (cfg, bb, branch1->inst_false_bb); branch1->inst_target_bb = next_bb; - mono_link_bblock (cfg, bb, next_bb); + mono_link_bblock (cfg, bb, next_bb); /* Rewrite the second branch */ branch2->opcode = br_to_br_un (branch2->opcode); @@ -774,7 +774,7 @@ mono_if_conversion (MonoCompile *cfg) } void -mono_nullify_basic_block (MonoBasicBlock *bb) +mono_nullify_basic_block (MonoBasicBlock *bb) { bb->in_count = 0; bb->out_count = 0; @@ -785,7 +785,7 @@ mono_nullify_basic_block (MonoBasicBlock *bb) bb->cil_code = NULL; } -static void +static void replace_out_block (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) { int i; @@ -805,7 +805,7 @@ replace_out_block (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *re } } -static void +static void replace_in_block (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) { int i; @@ -829,7 +829,7 @@ static void replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) { MonoInst *ins; - + for (ins = bb->code; ins != NULL; ins = ins->next) { switch (ins->opcode) { case OP_BR: @@ -885,7 +885,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p bb->not_useless = TRUE; return FALSE; } - + MONO_BB_FOR_EACH_INS (bb, inst) { switch (inst->opcode) { case OP_NOP: @@ -899,7 +899,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p return FALSE; } } - + if (target_bb == NULL) { if ((bb->out_count == 1) && (bb->out_bb [0] == bb->next_bb)) { target_bb = bb->next_bb; @@ -908,25 +908,25 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p return FALSE; } } - + /* Do not touch BBs following a switch (they are the "default" branch) */ if ((previous_bb->last_ins != NULL) && (previous_bb->last_ins->opcode == OP_SWITCH)) { return FALSE; } - + /* Do not touch BBs following the entry BB and jumping to something that is not */ /* thiry "next" bb (the entry BB cannot contain the branch) */ if ((previous_bb == cfg->bb_entry) && (bb->next_bb != target_bb)) { return FALSE; } - /* - * Do not touch BBs following a try block as the code in + /* + * Do not touch BBs following a try block as the code in * mini_method_compile needs them to compute the length of the try block. */ if (MONO_BBLOCK_IS_IN_REGION (previous_bb, MONO_REGION_TRY)) return FALSE; - + /* Check that there is a target BB, and that bb is not an empty loop (Bug 75061) */ if ((target_bb != NULL) && (target_bb != bb)) { int i; @@ -934,7 +934,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p if (cfg->verbose_level > 1) { printf ("remove_block_if_useless, removed BB%d\n", bb->block_num); } - + /* unlink_bblock () modifies the bb->in_bb array so can't use a for loop here */ while (bb->in_count) { MonoBasicBlock *in_bb = bb->in_bb [0]; @@ -942,7 +942,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p mono_link_bblock (cfg, in_bb, target_bb); replace_out_block_in_code (in_bb, bb, target_bb); } - + mono_unlink_bblock (cfg, bb, target_bb); if (previous_bb != cfg->bb_entry && mono_bb_is_fall_through (cfg, previous_bb)) { for (i = 0; i < previous_bb->out_count; i++) { @@ -956,10 +956,10 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p } } } - + previous_bb->next_bb = bb->next_bb; mono_nullify_basic_block (bb); - + return TRUE; } else { return FALSE; @@ -967,7 +967,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p } void -mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *bbn) +mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *bbn) { MonoInst *inst; MonoBasicBlock *prev_bb; @@ -1048,7 +1048,7 @@ mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *b } mono_nullify_basic_block (bbn); - /* + /* * If bbn fell through to its next bblock, have to add a branch, since bb * will not fall though to the same bblock (#513931). */ @@ -1087,7 +1087,7 @@ move_basic_block_to_end (MonoCompile *cfg, MonoBasicBlock *bb) MONO_ADD_INS (bb, ins); mono_link_bblock (cfg, bb, next); ins->inst_target_bb = next; - } + } } /* @@ -1096,7 +1096,7 @@ move_basic_block_to_end (MonoCompile *cfg, MonoBasicBlock *bb) * Remove BB from the control flow graph */ void -mono_remove_bblock (MonoCompile *cfg, MonoBasicBlock *bb) +mono_remove_bblock (MonoCompile *cfg, MonoBasicBlock *bb) { MonoBasicBlock *tmp_bb; @@ -1112,7 +1112,7 @@ mono_remove_critical_edges (MonoCompile *cfg) { MonoBasicBlock *bb; MonoBasicBlock *previous_bb; - + if (cfg->verbose_level > 3) { for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { int i; @@ -1132,15 +1132,15 @@ mono_remove_critical_edges (MonoCompile *cfg) printf ("\n"); } } - + for (previous_bb = cfg->bb_entry, bb = previous_bb->next_bb; bb != NULL; previous_bb = previous_bb->next_bb, bb = bb->next_bb) { if (bb->in_count > 1) { int in_bb_index; for (in_bb_index = 0; in_bb_index < bb->in_count; in_bb_index++) { MonoBasicBlock *in_bb = bb->in_bb [in_bb_index]; - /* + /* * Have to remove non-critical edges whose source ends with a BR_REG - * ins too, since inserting a computation before the BR_REG could + * ins too, since inserting a computation before the BR_REG could * overwrite the sreg1 of the ins. */ if ((in_bb->out_count > 1) || (in_bb->out_count == 1 && in_bb->last_ins && in_bb->last_ins->opcode == OP_BR_REG)) { @@ -1148,7 +1148,7 @@ mono_remove_critical_edges (MonoCompile *cfg) new_bb->block_num = cfg->num_bblocks++; // new_bb->real_offset = bb->real_offset; new_bb->region = bb->region; - + /* Do not alter the CFG while altering the BB list */ if (mono_bb_is_fall_through (cfg, previous_bb)) { if (previous_bb != cfg->bb_entry) { @@ -1172,7 +1172,7 @@ mono_remove_critical_edges (MonoCompile *cfg) new_bb_after_entry->block_num = cfg->num_bblocks++; // new_bb_after_entry->real_offset = bb->real_offset; new_bb_after_entry->region = bb->region; - + MONO_INST_NEW (cfg, jump, OP_BR); MONO_ADD_INS (new_bb_after_entry, jump); jump->cil_code = bb->cil_code; @@ -1181,7 +1181,7 @@ mono_remove_critical_edges (MonoCompile *cfg) mono_unlink_bblock (cfg, previous_bb, bb); mono_link_bblock (cfg, new_bb_after_entry, bb); mono_link_bblock (cfg, previous_bb, new_bb_after_entry); - + previous_bb->next_bb = new_bb_after_entry; previous_bb = new_bb_after_entry; @@ -1190,12 +1190,12 @@ mono_remove_critical_edges (MonoCompile *cfg) } } } - + /* Insert new_bb in the BB list */ previous_bb->next_bb = new_bb; new_bb->next_bb = bb; previous_bb = new_bb; - + /* Setup in_bb and out_bb */ new_bb->in_bb = (MonoBasicBlock **)mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*)); new_bb->in_bb [0] = in_bb; @@ -1203,12 +1203,12 @@ mono_remove_critical_edges (MonoCompile *cfg) new_bb->out_bb = (MonoBasicBlock **)mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*)); new_bb->out_bb [0] = bb; new_bb->out_count = 1; - + /* Relink in_bb and bb to (from) new_bb */ replace_out_block (in_bb, bb, new_bb); replace_out_block_in_code (in_bb, bb, new_bb); replace_in_block (bb, in_bb, new_bb); - + if (cfg->verbose_level > 2) { printf ("remove_critical_edges, removed critical edge from BB%d to BB%d (added BB%d)\n", in_bb->block_num, bb->block_num, new_bb->block_num); } @@ -1216,7 +1216,7 @@ mono_remove_critical_edges (MonoCompile *cfg) } } } - + if (cfg->verbose_level > 3) { for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { int i; @@ -1260,7 +1260,7 @@ mono_optimize_branches (MonoCompile *cfg) niterations = cfg->num_bblocks * 2; else niterations = 1000; - + do { MonoBasicBlock *previous_bb; changed = FALSE; @@ -1291,7 +1291,7 @@ mono_optimize_branches (MonoCompile *cfg) for (i = 0; i < bbn->out_count; i++) replace_in_block (bbn->out_bb [i], bbn, NULL); - mono_nullify_basic_block (bbn); + mono_nullify_basic_block (bbn); changed = TRUE; } @@ -1341,7 +1341,7 @@ mono_optimize_branches (MonoCompile *cfg) for (i = 0; i < bbn->out_count; i++) replace_in_block (bbn->out_bb [i], bbn, NULL); - mono_nullify_basic_block (bbn); + mono_nullify_basic_block (bbn); changed = TRUE; continue; } @@ -1355,7 +1355,7 @@ mono_optimize_branches (MonoCompile *cfg) if (bb->region == bbn->region && bbn_first_inst && bbn_first_inst->opcode == OP_BR && bbn_first_inst->inst_target_bb != bbn && bbn_first_inst->inst_target_bb->region == bb->region) { - + if (cfg->verbose_level > 2) g_print ("branch to branch triggered %d -> %d -> %d\n", bb->block_num, bbn->block_num, bbn_first_inst->inst_target_bb->block_num); @@ -1387,7 +1387,7 @@ mono_optimize_branches (MonoCompile *cfg) untaken_branch_target = bb->last_ins->inst_true_bb; } if (taken_branch_target) { - /* if mono_eval_cond_branch () is ever taken to handle + /* if mono_eval_cond_branch () is ever taken to handle * non-constant values to compare, issue a pop here. */ bb->last_ins->opcode = OP_BR; @@ -1401,12 +1401,12 @@ mono_optimize_branches (MonoCompile *cfg) bbn_first_inst = mono_bb_first_inst (bbn, filter); if (bb->region == bbn->region && bbn_first_inst && bbn_first_inst->opcode == OP_BR && bbn_first_inst->inst_target_bb->region == bb->region) { - if (cfg->verbose_level > 2) - g_print ("cbranch1 to branch triggered %d -> (%d) %d (0x%02x)\n", - bb->block_num, bbn->block_num, bbn_first_inst->inst_target_bb->block_num, + if (cfg->verbose_level > 2) + g_print ("cbranch1 to branch triggered %d -> (%d) %d (0x%02x)\n", + bb->block_num, bbn->block_num, bbn_first_inst->inst_target_bb->block_num, bbn_first_inst->opcode); - /* + /* * Unlink, then relink bblocks to avoid various * tricky situations when the two targets of the branch * are equal, or will become equal after the change. @@ -1428,8 +1428,8 @@ mono_optimize_branches (MonoCompile *cfg) if (bbn && bb->region == bbn->region && bbn_first_inst && bbn_first_inst->opcode == OP_BR && bbn_first_inst->inst_target_bb->region == bb->region) { if (cfg->verbose_level > 2) - g_print ("cbranch2 to branch triggered %d -> (%d) %d (0x%02x)\n", - bb->block_num, bbn->block_num, bbn_first_inst->inst_target_bb->block_num, + g_print ("cbranch2 to branch triggered %d -> (%d) %d (0x%02x)\n", + bb->block_num, bbn->block_num, bbn_first_inst->inst_target_bb->block_num, bbn_first_inst->opcode); mono_unlink_bblock (cfg, bb, bb->last_ins->inst_true_bb); @@ -1449,7 +1449,7 @@ mono_optimize_branches (MonoCompile *cfg) * If bb is an extended bb, it could contain an inside branch to bbn. * FIXME: Enable the optimization if that is not true. * If bblocks_linked () is true, then merging bb and bbn - * would require addition of an extra branch at the end of bbn + * would require addition of an extra branch at the end of bbn * slowing down loops. */ if (bbn && bb->region == bbn->region && bbn->in_count == 1 && cfg->enable_extended_bblocks && bbn != cfg->bb_exit && !bb->extended && !bbn->out_of_line && !mono_bblocks_linked (bbn, bb)) { @@ -1472,7 +1472,7 @@ mono_optimize_branches (MonoCompile *cfg) move_basic_block_to_end (cfg, bb->last_ins->inst_true_bb); if (cfg->verbose_level > 2) - g_print ("cbranch to throw block triggered %d.\n", + g_print ("cbranch to throw block triggered %d.\n", bb->block_num); } } diff --git a/src/mono/mono/mini/calls.c b/src/mono/mono/mini/calls.c index dc3007b36bfb7..e6eed77d6884c 100644 --- a/src/mono/mono/mini/calls.c +++ b/src/mono/mono/mini/calls.c @@ -105,7 +105,7 @@ ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -139,7 +139,7 @@ ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt) } MonoCallInst * -mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, +mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, gboolean calli, gboolean virtual_, gboolean tailcall, gboolean rgctx, gboolean unbox_trampoline, MonoMethod *target) { @@ -193,7 +193,7 @@ mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst *temp = mono_compile_create_var (cfg, sig_ret, OP_LOCAL); MonoInst *loada; - temp->backend.is_pinvoke = sig->pinvoke; + temp->backend.is_pinvoke = sig->pinvoke && !sig->marshalling_disabled; /* * We use a new opcode OP_OUTARG_VTRETADDR instead of LDADDR for emitting the @@ -218,8 +218,8 @@ mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK if (COMPILE_SOFT_FLOAT (cfg)) { - /* - * If the call has a float argument, we would need to do an r8->r4 conversion using + /* + * If the call has a float argument, we would need to do an r8->r4 conversion using * an icall, but that cannot be done during the call sequence since it would clobber * the call registers + the stack. So we do it before emitting the call. */ @@ -260,7 +260,7 @@ mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, cfg->param_area = MAX (cfg->param_area, call->stack_usage); cfg->flags |= MONO_CFG_HAS_CALLS; - + return call; } @@ -289,7 +289,7 @@ set_rgctx_arg (MonoCompile *cfg, MonoCallInst *call, int rgctx_reg, MonoInst *rg #ifdef ENABLE_LLVM call->rgctx_arg_reg = rgctx_reg; #endif -} +} /* Either METHOD or IMT_ARG needs to be set */ static void @@ -524,7 +524,7 @@ mini_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign FIXME: a dummy use is not the best way to do it as the local register allocator will put it on a caller save register and spill it around the call. - Ideally, we would either put it on a callee save register or only do the store part. + Ideally, we would either put it on a callee save register or only do the store part. */ EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [0]); @@ -533,7 +533,7 @@ mini_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign if ((!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || (MONO_METHOD_IS_FINAL (method)))) { - /* + /* * the method is not virtual, we just need to ensure this is not null * and then we can call the method directly. */ @@ -635,13 +635,13 @@ mono_emit_jit_icall_id (MonoCompile *cfg, MonoJitICallId jit_icall_id, MonoInst * Emit a call to the runtime function described by PATCH_TYPE and DATA. */ MonoInst* -mini_emit_abs_call (MonoCompile *cfg, MonoJumpInfoType patch_type, gconstpointer data, +mini_emit_abs_call (MonoCompile *cfg, MonoJumpInfoType patch_type, gconstpointer data, MonoMethodSignature *sig, MonoInst **args) { MonoJumpInfo *ji = mono_patch_info_new (cfg->mempool, 0, patch_type, data); MonoInst *ins; - /* + /* * We pass ji as the call address, the PATCH_INFO_ABS resolving code will * handle it. * FIXME: Is the abs_patches hashtable avoidable? diff --git a/src/mono/mono/mini/cfold.c b/src/mono/mono/mini/cfold.c index 89c4f7b9563ac..fea708e4ef6d7 100644 --- a/src/mono/mono/mini/cfold.c +++ b/src/mono/mono/mini/cfold.c @@ -110,7 +110,7 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns FOLD_FBINOP (OP_FMUL, *); } dest->opcode = OP_R8CONST; - MONO_INST_NULLIFY_SREGS (dest); + MONO_INST_NULLIFY_SREGS (dest); } break; case OP_RADD: @@ -122,7 +122,7 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns FOLD_RBINOP (OP_RMUL, *); } dest->opcode = OP_R4CONST; - MONO_INST_NULLIFY_SREGS (dest); + MONO_INST_NULLIFY_SREGS (dest); } break; case OP_IMUL: @@ -144,7 +144,7 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns MONO_INST_NULLIFY_SREGS (dest); } } else if (arg1->opcode == OP_ICONST) { - /* + /* * This is commutative so swap the arguments, allowing the _imm variant * to be used later. */ @@ -380,8 +380,8 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns } if (overwrite) { - /* - * Can't nullify OP_COMPARE here since the decompose long branch + /* + * Can't nullify OP_COMPARE here since the decompose long branch * opcodes depend on it being executed. Also, the branch might not * be eliminated after all if loop opts is disabled, for example. */ @@ -443,17 +443,17 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns } /* - * TODO: + * TODO: * conv.* opcodes. * *ovf* opcodes? It's slow and hard to do in C. - * switch can be replaced by a simple jump + * switch can be replaced by a simple jump */ default: return NULL; } - + return dest; -} +} #endif /* DISABLE_JIT */ diff --git a/src/mono/mono/mini/debug-mini.c b/src/mono/mono/mini/debug-mini.c index 2fdb64d2c12b2..a665dd012738d 100644 --- a/src/mono/mono/mini/debug-mini.c +++ b/src/mono/mono/mini/debug-mini.c @@ -76,7 +76,7 @@ mono_debug_open_method (MonoCompile *cfg) header = cfg->header; g_assert (header); - + info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1); info->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry)); jit->num_locals = header->num_locals; @@ -118,7 +118,7 @@ write_variable (MonoInst *inst, MonoDebugVarInfo *var) * * Register symbol information for the method with valgrind */ -static void +static void mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit) { #ifdef VALGRIND_ADD_LINE_INFO @@ -143,7 +143,7 @@ mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit) addresses = g_new0 (guint32, header->code_size + 1); lines = g_new0 (guint32, header->code_size + 1); - /* + /* * Very simple code to convert the addr->offset mappings that mono has * into [addr-addr] ->line number mappings. */ @@ -183,7 +183,7 @@ mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit) else address = addresses [i]; } - + address = 0; line_number = 0; i = 0; @@ -193,7 +193,7 @@ mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit) else { if (line_number > 0) { //g_assert (addresses [i] - 1 >= address); - + if (addresses [i] - 1 >= address) { VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number); //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number); @@ -294,7 +294,7 @@ mono_debug_free_method (MonoCompile *cfg) if (info->line_numbers) g_array_free (info->line_numbers, TRUE); g_free (info); - cfg->debug_info = NULL; + cfg->debug_info = NULL; } } @@ -359,7 +359,7 @@ encode_value (gint32 value, guint8 *buf, guint8 **endbuf) //printf ("ENCODE: %d 0x%x.\n", value, value); - /* + /* * Same encoding as the one used in the metadata, extended to handle values * greater than 0x1fffffff. */ @@ -393,7 +393,7 @@ decode_value (guint8 *ptr, guint8 **rptr) { guint8 b = *ptr; gint32 len; - + if ((b & 0x80) == 0){ len = b; ++ptr; @@ -597,7 +597,7 @@ deserialize_debug_info (MonoMethod *method, guint8 *code_start, guint8 *buf, gui } void -mono_debug_add_aot_method (MonoMethod *method, guint8 *code_start, +mono_debug_add_aot_method (MonoMethod *method, guint8 *code_start, guint8 *debug_info, guint32 debug_info_len) { MonoDebugMethodJitInfo *jit; @@ -654,7 +654,7 @@ print_var_info (MonoDebugVarInfo *info, int idx, const char *name, const char *t * * Prints to stdout the information about the local variables in * a method (if \p only_arguments is false) or about the arguments. - * The information includes the storage info (where the variable + * The information includes the storage info (where the variable * lives, in a register or in memory). * The method is found by looking up what method has been emitted at * the instruction address \p ip. diff --git a/src/mono/mono/mini/debugger-agent-external.c b/src/mono/mono/mini/debugger-agent-external.c index 2fc584c5ad949..67298c2363b7e 100644 --- a/src/mono/mono/mini/debugger-agent-external.c +++ b/src/mono/mono/mini/debugger-agent-external.c @@ -49,7 +49,7 @@ mono_debugger_agent_parse_options (char *options) } DebuggerTransport * -mono_debugger_agent_get_transports (int *ntrans) +mono_debugger_agent_get_transports (int *ntrans) { *ntrans = ntransports; return transports; diff --git a/src/mono/mono/mini/decompose.c b/src/mono/mono/mini/decompose.c index efc8bfd6f06bc..8e6db0073f589 100644 --- a/src/mono/mono/mini/decompose.c +++ b/src/mono/mono/mini/decompose.c @@ -129,7 +129,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) break; } #endif - + case OP_ICONV_TO_OVF_I8: case OP_ICONV_TO_OVF_I: ins->opcode = OP_SEXT_I4; @@ -310,7 +310,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) mono_arch_decompose_opts (cfg, ins); /* - * The code below assumes that we are called immediately after emitting + * The code below assumes that we are called immediately after emitting * ins. This means we can emit code using the normal code generation * macros. */ @@ -600,7 +600,7 @@ mono_decompose_long_opts (MonoCompile *cfg) */ /** - * Create a dummy bblock and emit code into it so we can use the normal + * Create a dummy bblock and emit code into it so we can use the normal * code generation macros. */ cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); @@ -980,7 +980,7 @@ mono_decompose_long_opts (MonoCompile *cfg) break; case OP_LCEQ: { int d1, d2; - + /* Branchless version based on gcc code */ d1 = alloc_ireg (cfg); d2 = alloc_ireg (cfg); @@ -998,7 +998,7 @@ mono_decompose_long_opts (MonoCompile *cfg) case OP_LCGT: case OP_LCGT_UN: { MonoBasicBlock *set_to_0, *set_to_1; - + NEW_BBLOCK (cfg, set_to_0); NEW_BBLOCK (cfg, set_to_1); @@ -1013,7 +1013,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); NULLIFY_INS (next); - break; + break; } default: g_assert_not_reached (); @@ -1067,7 +1067,7 @@ mono_decompose_long_opts (MonoCompile *cfg) break; case OP_LCEQ: { int d1, d2; - + /* Branchless version based on gcc code */ d1 = alloc_ireg (cfg); d2 = alloc_ireg (cfg); @@ -1085,7 +1085,7 @@ mono_decompose_long_opts (MonoCompile *cfg) case OP_LCGT: case OP_LCGT_UN: { MonoBasicBlock *set_to_0, *set_to_1; - + NEW_BBLOCK (cfg, set_to_0); NEW_BBLOCK (cfg, set_to_1); @@ -1100,7 +1100,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); NULLIFY_INS (next); - break; + break; } default: g_assert_not_reached (); @@ -1161,23 +1161,23 @@ mono_decompose_vtype_opts (MonoCompile *cfg) * everywhere. * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed, * enabling optimizations to work on vtypes too. - * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it + * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it * can be executed anytime. It should be executed as late as possible so vtype * opcodes can be optimized by the other passes. * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation. - * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the + * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the * var to 1. - * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass + * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass * when OP_VMOVE opcodes are decomposed. */ - /* + /* * Vregs have no associated type information, so we store the type of the vregs * in ins->klass. */ /** - * Create a dummy bblock and emit code into it so we can use the normal + * Create a dummy bblock and emit code into it so we can use the normal * code generation macros. */ cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); @@ -1238,11 +1238,11 @@ mono_decompose_vtype_opts (MonoCompile *cfg) EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, m_class_get_byval_arg (ins->klass)); mini_emit_initobj (cfg, dest, NULL, ins->klass); - + if (cfg->compute_gc_maps) { MonoInst *tmp; - /* + /* * Tell the GC map code that the vtype is considered live after * the initialization. */ @@ -1491,12 +1491,12 @@ mono_decompose_array_access_opts (MonoCompile *cfg) MonoBasicBlock *bb, *first_bb; /* - * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it + * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it * can be executed anytime. It should be run before decompose_long */ /** - * Create a dummy bblock and emit code into it so we can use the normal + * Create a dummy bblock and emit code into it so we can use the normal * code generation macros. */ cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); @@ -1628,7 +1628,7 @@ mono_decompose_soft_float (MonoCompile *cfg) */ /** - * Create a dummy bblock and emit code into it so we can use the normal + * Create a dummy bblock and emit code into it so we can use the normal * code generation macros. */ cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); @@ -1717,7 +1717,7 @@ mono_decompose_soft_float (MonoCompile *cfg) conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs); conv->dreg = ins->dreg; break; - } + } case OP_FCALL: case OP_FCALL_REG: case OP_FCALL_MEMBASE: { @@ -1809,7 +1809,7 @@ mono_decompose_soft_float (MonoCompile *cfg) cmp->sreg1 = call->dreg; cmp->inst_imm = 0; MONO_ADD_INS (cfg->cbb, cmp); - + MONO_INST_NEW (cfg, br, OP_IBNE_UN); br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2); br->inst_true_bb = ins->next->inst_true_bb; diff --git a/src/mono/mono/mini/dominators.c b/src/mono/mono/mini/dominators.c index 01093eb9d11e3..3e8197c6a64db 100644 --- a/src/mono/mono/mini/dominators.c +++ b/src/mono/mono/mini/dominators.c @@ -28,7 +28,7 @@ /* * Compute dominators and immediate dominators using the algorithm in the - * paper "A Simple, Fast Dominance Algorithm" by Keith D. Cooper, + * paper "A Simple, Fast Dominance Algorithm" by Keith D. Cooper, * Timothy J. Harvey, and Ken Kennedy: * http://citeseer.ist.psu.edu/cooper01simple.html */ @@ -169,7 +169,7 @@ check_dominance_frontier (MonoBasicBlock *x, MonoBasicBlock *t) if (!(t->flags & BB_VISITED)) { int found = FALSE; check_dominance_frontier (x, t->out_bb [i]); - + for (j = 0; j < t->out_bb [i]->in_count; j++) { if (t->out_bb [i]->in_bb [j] == t) found = TRUE; @@ -183,7 +183,7 @@ check_dominance_frontier (MonoBasicBlock *x, MonoBasicBlock *t) g_assert_not_reached (); } } -} +} #endif @@ -203,7 +203,7 @@ compute_dominance_frontier (MonoCompile *cfg) bitsize = mono_bitset_alloc_size (cfg->num_bblocks, 0); mem = (char *)mono_mempool_alloc0 (cfg->mempool, bitsize * cfg->num_bblocks); - + for (i = 0; i < cfg->num_bblocks; ++i) { MonoBasicBlock *bb = cfg->bblocks [i]; bb->dfrontier = mono_bitset_mem_new (mem, cfg->num_bblocks, 0); @@ -230,7 +230,7 @@ compute_dominance_frontier (MonoCompile *cfg) #if 0 for (i = 0; i < cfg->num_bblocks; ++i) { MonoBasicBlock *bb = cfg->bblocks [i]; - + printf ("DFRONT %s BB%d: ", mono_method_full_name (cfg->method, TRUE), bb->block_num); mono_blockset_print (cfg, bb->dfrontier, NULL, -1); } @@ -240,14 +240,14 @@ compute_dominance_frontier (MonoCompile *cfg) /* this is a check for the dominator frontier */ for (i = 0; i < m->num_bblocks; ++i) { MonoBasicBlock *x = m->bblocks [i]; - + mono_bitset_foreach_bit ((x->dfrontier), j, (m->num_bblocks)) { MonoBasicBlock *w = m->bblocks [j]; int k; /* x must not strictly dominates w */ if (mono_bitset_test_fast (w->dominators, x->dfn) && w != x) g_assert_not_reached (); - + for (k = 0; k < m->num_bblocks; ++k) m->bblocks [k]->flags &= ~BB_VISITED; @@ -260,7 +260,7 @@ compute_dominance_frontier (MonoCompile *cfg) } static void -df_set (MonoCompile *m, MonoBitSet* dest, MonoBitSet *set) +df_set (MonoCompile *m, MonoBitSet* dest, MonoBitSet *set) { int i; @@ -285,11 +285,11 @@ mono_compile_iterated_dfrontier (MonoCompile *m, MonoBitSet *set) df_set (m, result, result); count2 = mono_bitset_count (result); } while (count2 > count1); - + return result; } -void +void mono_compile_dominator_info (MonoCompile *cfg, int dom_flags) { if ((dom_flags & MONO_COMP_DOM) && !(cfg->comp_done & MONO_COMP_DOM)) @@ -301,7 +301,7 @@ mono_compile_dominator_info (MonoCompile *cfg, int dom_flags) /* * code to detect loops and loop nesting level */ -void +void mono_compute_natural_loops (MonoCompile *cfg) { int i, j, k; @@ -340,8 +340,8 @@ mono_compute_natural_loops (MonoCompile *cfg) mono_bitset_set_fast (in_loop_blocks, b->dfn); } } - todo = g_slist_prepend (NULL, n); - + todo = g_slist_prepend (NULL, n); + while (todo) { MonoBasicBlock *cb = (MonoBasicBlock *)todo->data; todo = g_slist_delete_link (todo, todo); @@ -424,27 +424,27 @@ static void clear_idominators (MonoCompile *cfg) { guint i; - + for (i = 0; i < cfg->num_bblocks; ++i) { if (cfg->bblocks[i]->dominated) { cfg->bblocks[i]->dominated = NULL; } } - cfg->comp_done &= ~MONO_COMP_IDOM; + cfg->comp_done &= ~MONO_COMP_IDOM; } static void clear_loops (MonoCompile *cfg) { guint i; - + for (i = 0; i < cfg->num_bblocks; ++i) { cfg->bblocks[i]->nesting = 0; cfg->bblocks[i]->loop_blocks = NULL; } - cfg->comp_done &= ~MONO_COMP_LOOPS; + cfg->comp_done &= ~MONO_COMP_LOOPS; } void diff --git a/src/mono/mono/mini/exceptions-arm.c b/src/mono/mono/mini/exceptions-arm.c index 146cf26e1e366..afa4a5f976c14 100644 --- a/src/mono/mono/mini/exceptions-arm.c +++ b/src/mono/mono/mini/exceptions-arm.c @@ -61,7 +61,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) start = code = mono_global_codeman_reserve (128); - /* + /* * Move things to their proper place so we can restore all the registers with * one instruction. */ @@ -99,7 +99,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) * arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We - * also use this function to call finally handlers (we pass NULL as + * also use this function to call finally handlers (we pass NULL as * @exc object in this case). */ gpointer @@ -214,13 +214,13 @@ mono_arm_resume_unwind (guint32 dummy1, host_mgreg_t pc, host_mgreg_t sp, host_m /** * get_throw_trampoline: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following * signature: void (*func) (MonoException *exc); or * void (*func) (guint32 ex_token, guint8* ip); * */ -static gpointer +static gpointer get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips) { guint8 *start; @@ -335,16 +335,16 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm /** * arch_get_throw_exception: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); * For example to raise an arithmetic exception you can use: * - * x86_push_imm (code, mono_get_exception_arithmetic ()); - * x86_call_code (code, arch_get_throw_exception ()); + * x86_push_imm (code, mono_get_exception_arithmetic ()); + * x86_call_code (code, arch_get_throw_exception ()); * */ -gpointer +gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline (132, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE); @@ -353,9 +353,9 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_rethrow_exception: * - * Returns a function pointer which can be used to rethrow - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * Returns a function pointer which can be used to rethrow + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); * */ gpointer @@ -364,7 +364,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot, FALSE); } -gpointer +gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE); @@ -372,19 +372,19 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_throw_corlib_exception: - * \returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (guint32 ex_token, guint32 offset); - * Here, \c offset is the offset which needs to be substracted from the caller IP - * to get the IP of the throw. Passing the offset has the advantage that it + * \returns a function pointer which can be used to raise + * corlib exceptions. The returned function has the following + * signature: void (*func) (guint32 ex_token, guint32 offset); + * Here, \c offset is the offset which needs to be substracted from the caller IP + * to get the IP of the throw. Passing the offset has the advantage that it * needs no relocations in the caller. * On ARM, the ip is passed instead of an offset. */ -gpointer +gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE); -} +} GSList* mono_arm_get_exception_trampolines (gboolean aot) @@ -398,7 +398,7 @@ mono_arm_get_exception_trampolines (gboolean aot) get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot, FALSE); info->jit_icall_info = &mono_get_jit_icall_info ()->mono_llvm_throw_corlib_exception_trampoline; tramps = g_slist_prepend (tramps, info); - + get_throw_trampoline (168, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot, FALSE); info->jit_icall_info = &mono_get_jit_icall_info ()->mono_llvm_throw_corlib_exception_abs_trampoline; tramps = g_slist_prepend (tramps, info); @@ -426,7 +426,7 @@ mono_arch_exceptions_init (void) { gpointer tramp; GSList *tramps, *l; - + if (mono_aot_only) { // FIXME Macroize. @@ -451,7 +451,7 @@ mono_arch_exceptions_init (void) } } -/* +/* * mono_arch_unwind_frame: * * See exceptions-amd64.c for docs; @@ -525,7 +525,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, g_assert ((((guint64)(*lmf)->previous_lmf) & 2) == 0); frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; - + if ((ji = mini_jit_info_table_find ((gpointer)(gsize)(*lmf)->ip))) { frame->ji = ji; } else { @@ -635,7 +635,7 @@ mono_arch_handle_exception (void *ctx, gpointer obj) result = mono_handle_exception (&mctx, obj); /* restore the context so that returning from the signal handler will invoke - * the catch clause + * the catch clause */ mono_monoctx_to_sigctx (&mctx, ctx); return result; diff --git a/src/mono/mono/mini/exceptions-arm64.c b/src/mono/mono/mini/exceptions-arm64.c index 30f0612f4fe88..adf650de2d02e 100644 --- a/src/mono/mono/mini/exceptions-arm64.c +++ b/src/mono/mono/mini/exceptions-arm64.c @@ -59,7 +59,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) /* ip0 = sp */ arm_ldrx (code, ARMREG_IP0, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_SP * 8)); /* Restore sp, ctx is no longer valid */ - arm_movspx (code, ARMREG_SP, ARMREG_IP0); + arm_movspx (code, ARMREG_SP, ARMREG_IP0); /* Branch to pc */ code = mono_arm_emit_brx (code, ARMREG_IP1); /* Not reached */ @@ -166,7 +166,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) return MINI_ADDR_TO_FTNPTR (start); } -static gpointer +static gpointer get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips) { guint8 *start, *code; @@ -206,7 +206,7 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm arm_ldrx (code, ARMREG_IP0, ARMREG_FP, 0); arm_strx (code, ARMREG_IP0, ARMREG_FP, gregs_offset + (ARMREG_FP * 8)); arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, frame_size); - arm_strx (code, ARMREG_IP0, ARMREG_FP, gregs_offset + (ARMREG_SP * 8)); + arm_strx (code, ARMREG_IP0, ARMREG_FP, gregs_offset + (ARMREG_SP * 8)); /* Save fregs */ for (i = 0; i < num_fregs; ++i) arm_strfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8)); @@ -270,7 +270,7 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm return MINI_ADDR_TO_FTNPTR (start); } -gpointer +gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE); @@ -288,7 +288,7 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE); } -gpointer +gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE); @@ -423,14 +423,14 @@ mono_arm_resume_unwind (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_regs, g mono_resume_unwind (&ctx); } -/* +/* * mono_arch_unwind_frame: * * See exceptions-amd64.c for docs; */ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) diff --git a/src/mono/mono/mini/exceptions-mips.c b/src/mono/mono/mini/exceptions-mips.c index eea3b637eee1d..9e26eef50080f 100644 --- a/src/mono/mono/mini/exceptions-mips.c +++ b/src/mono/mono/mini/exceptions-mips.c @@ -88,7 +88,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) * mono_arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We - * also use this function to call finally handlers (we pass NULL as + * also use this function to call finally handlers (we pass NULL as * @exc object in this case). * * This function is invoked as @@ -222,13 +222,13 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean /** * arch_get_throw_exception_generic: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following * signature: void (*func) (MonoException *exc); or * void (*func) (char *exc_name); * */ -static gpointer +static gpointer mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow, gboolean preserve_ips) { guint8 *code; @@ -298,9 +298,9 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboo /** * mono_arch_get_rethrow_exception: - * \returns a function pointer which can be used to rethrow - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * \returns a function pointer which can be used to rethrow + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); */ gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) @@ -323,8 +323,8 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) * mono_arch_get_rethrow_preserve_exception: * \returns a function pointer which can be used to rethrow * exceptions while avoiding modification of saved trace_ips. - * The returned function has the following - * signature: void (*func) (MonoException *exc); + * The returned function has the following + * signature: void (*func) (MonoException *exc); */ gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) @@ -346,13 +346,13 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /** * arch_get_throw_exception: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); * For example to raise an arithmetic exception you can use: * - * x86_push_imm (code, mono_get_exception_arithmetic ()); - * x86_call_code (code, arch_get_throw_exception ()); + * x86_push_imm (code, mono_get_exception_arithmetic ()); + * x86_call_code (code, arch_get_throw_exception ()); * */ gpointer @@ -372,13 +372,13 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) return start; } -gpointer +gpointer mono_arch_get_throw_exception_by_name (void) { guint8 *start, *code; int size = 64; - /* Not used on MIPS */ + /* Not used on MIPS */ start = code = mono_global_codeman_reserve (size); mips_break (code, 0xfd); mono_arch_flush_icache (start, code - start); @@ -388,9 +388,9 @@ mono_arch_get_throw_exception_by_name (void) /** * mono_arch_get_throw_corlib_exception: - * \returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (guint32 ex_token, guint32 offset); + * \returns a function pointer which can be used to raise + * corlib exceptions. The returned function has the following + * signature: void (*func) (guint32 ex_token, guint32 offset); * On MIPS, the offset argument is missing. */ gpointer @@ -419,9 +419,9 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) * Returns TRUE on success, FALSE otherwise. */ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, - MonoContext *new_ctx, MonoLMF **lmf, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, + MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) { @@ -448,7 +448,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, for (i = 0; i < MONO_MAX_IREGS; ++i) regs [i] = new_ctx->sc_regs [i]; - gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, + gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, ip, NULL, regs, MONO_MAX_IREGS, save_locations, MONO_MAX_IREGS, &cfa); @@ -562,7 +562,7 @@ mono_arch_handle_exception (void *ctx, gpointer obj) result = mono_handle_exception (&mctx, obj); /* restore the context so that returning from the signal handler will invoke - * the catch clause + * the catch clause */ mono_monoctx_to_sigctx (&mctx, ctx); return result; diff --git a/src/mono/mono/mini/exceptions-ppc.c b/src/mono/mono/mini/exceptions-ppc.c index d1584191ff6af..829da843d282a 100644 --- a/src/mono/mono/mini/exceptions-ppc.c +++ b/src/mono/mono/mini/exceptions-ppc.c @@ -36,62 +36,62 @@ /* struct sigcontext { - int sc_onstack; // sigstack state to restore - int sc_mask; // signal mask to restore - int sc_ir; // pc - int sc_psw; // processor status word - int sc_sp; // stack pointer if sc_regs == NULL - void *sc_regs; // (kernel private) saved state + int sc_onstack; // sigstack state to restore + int sc_mask; // signal mask to restore + int sc_ir; // pc + int sc_psw; // processor status word + int sc_sp; // stack pointer if sc_regs == NULL + void *sc_regs; // (kernel private) saved state }; struct ucontext { int uc_onstack; - sigset_t uc_sigmask; // signal mask used by this context - stack_t uc_stack; // stack used by this context - struct ucontext *uc_link; // pointer to resuming context - size_t uc_mcsize; // size of the machine context passed in - mcontext_t uc_mcontext; // machine specific context + sigset_t uc_sigmask; // signal mask used by this context + stack_t uc_stack; // stack used by this context + struct ucontext *uc_link; // pointer to resuming context + size_t uc_mcsize; // size of the machine context passed in + mcontext_t uc_mcontext; // machine specific context }; typedef struct ppc_exception_state { - unsigned long dar; // Fault registers for coredump + unsigned long dar; // Fault registers for coredump unsigned long dsisr; - unsigned long exception;// number of powerpc exception taken - unsigned long pad0; // align to 16 bytes + unsigned long exception;// number of powerpc exception taken + unsigned long pad0; // align to 16 bytes - unsigned long pad1[4]; // space in PCB "just in case" + unsigned long pad1[4]; // space in PCB "just in case" } ppc_exception_state_t; typedef struct ppc_vector_state { unsigned long save_vr[32][4]; unsigned long save_vscr[4]; unsigned int save_pad5[4]; - unsigned int save_vrvalid; // VRs that have been saved + unsigned int save_vrvalid; // VRs that have been saved unsigned int save_pad6[7]; } ppc_vector_state_t; typedef struct ppc_float_state { double fpregs[32]; - unsigned int fpscr_pad; // fpscr is 64 bits, 32 bits of rubbish - unsigned int fpscr; // floating point status register + unsigned int fpscr_pad; // fpscr is 64 bits, 32 bits of rubbish + unsigned int fpscr; // floating point status register } ppc_float_state_t; typedef struct ppc_thread_state { - unsigned int srr0; // Instruction address register (PC) - unsigned int srr1; // Machine state register (supervisor) + unsigned int srr0; // Instruction address register (PC) + unsigned int srr1; // Machine state register (supervisor) unsigned int r0; unsigned int r1; unsigned int r2; - ... + ... unsigned int r31; - unsigned int cr; // Condition register - unsigned int xer; // User's integer exception register - unsigned int lr; // Link register - unsigned int ctr; // Count register - unsigned int mq; // MQ register (601 only) + unsigned int cr; // Condition register + unsigned int xer; // User's integer exception register + unsigned int lr; // Link register + unsigned int ctr; // Count register + unsigned int mq; // MQ register (601 only) - unsigned int vrsave; // Vector Save Register + unsigned int vrsave; // Vector Save Register } ppc_thread_state_t; struct mcontext { @@ -115,19 +115,19 @@ struct pt_regs { unsigned long gpr[32]; unsigned long nip; unsigned long msr; - unsigned long orig_gpr3; // Used for restarting system calls + unsigned long orig_gpr3; // Used for restarting system calls unsigned long ctr; unsigned long link; unsigned long xer; unsigned long ccr; - unsigned long mq; // 601 only (not used at present) - // Used on APUS to hold IPL value. - unsigned long trap; // Reason for being here + unsigned long mq; // 601 only (not used at present) + // Used on APUS to hold IPL value. + unsigned long trap; // Reason for being here // N.B. for critical exceptions on 4xx, the dar and dsisr - // fields are overloaded to hold srr0 and srr1. - unsigned long dar; // Fault registers - unsigned long dsisr; // on 4xx/Book-E used for ESR - unsigned long result; // Result of a system call + // fields are overloaded to hold srr0 and srr1. + unsigned long dar; // Fault registers + unsigned long dsisr; // on 4xx/Book-E used for ESR + unsigned long result; // Result of a system call }; struct mcontext { elf_gregset_t mc_gregs; @@ -141,22 +141,22 @@ struct ucontext { struct ucontext *uc_link; stack_t uc_stack; int uc_pad[7]; - struct mcontext *uc_regs; // points to uc_mcontext field + struct mcontext *uc_regs; // points to uc_mcontext field sigset_t uc_sigmask; - // glibc has 1024-bit signal masks, ours are 64-bit + // glibc has 1024-bit signal masks, ours are 64-bit int uc_maskext[30]; int uc_pad2[3]; struct mcontext uc_mcontext; }; -#define ELF_NGREG 48 // includes nip, msr, lr, etc. -#define ELF_NFPREG 33 // includes fpscr +#define ELF_NGREG 48 // includes nip, msr, lr, etc. +#define ELF_NFPREG 33 // includes fpscr -// General registers +// General registers typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -// Floating point registers +// Floating point registers typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; @@ -256,7 +256,7 @@ emit_save_saved_regs (guint8 *code, int pos) * mono_arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We - * also use this function to call finally handlers (we pass NULL as + * also use this function to call finally handlers (we pass NULL as * @exc object in this case). */ gpointer @@ -357,8 +357,8 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, /** * arch_get_throw_exception_generic: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following * signature: void (*func) (MonoException *exc); or * void (*func) (guint32 ex_token, gpointer ip) * @@ -461,8 +461,8 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli * mono_arch_get_rethrow_preserve_exception: * \returns a function pointer which can be used to rethrow * exceptions and completely preserve trace_ips. - * The returned function has the following - * signature: void (*func) (MonoException *exc); + * The returned function has the following + * signature: void (*func) (MonoException *exc); */ gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) @@ -476,9 +476,9 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_rethrow_exception: - * \returns a function pointer which can be used to rethrow - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * \returns a function pointer which can be used to rethrow + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); */ gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) @@ -493,13 +493,13 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) /** * arch_get_throw_exception: * - * Returns a function pointer which can be used to raise - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * Returns a function pointer which can be used to raise + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); * For example to raise an arithmetic exception you can use: * - * x86_push_imm (code, mono_get_exception_arithmetic ()); - * x86_call_code (code, arch_get_throw_exception ()); + * x86_push_imm (code, mono_get_exception_arithmetic ()); + * x86_call_code (code, arch_get_throw_exception ()); * */ gpointer @@ -514,9 +514,9 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_throw_corlib_exception: - * \returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (guint32 ex_token, guint32 offset); + * \returns a function pointer which can be used to raise + * corlib exceptions. The returned function has the following + * signature: void (*func) (guint32 ex_token, guint32 offset); * On PPC, we pass the ip instead of the offset */ gpointer @@ -535,8 +535,8 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) * See exceptions-amd64.c for docs. */ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) @@ -581,7 +581,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i) regs [i] = ctx->regs [i]; - gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start, + gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start, (guint8*)ji->code_start + ji->code_size, (guint8*)ip, NULL, regs, ppc_lr + 1, save_locations, MONO_MAX_IREGS, &cfa); @@ -599,7 +599,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, return TRUE; } else if (*lmf) { - + if ((ji = mini_jit_info_table_find ((gpointer)(*lmf)->eip))) { } else { if (!(*lmf)->method) @@ -796,7 +796,7 @@ mono_arch_handle_exception (void *ctx, gpointer obj) result = mono_handle_exception (&mctx, obj); /* restore the context so that returning from the signal handler will invoke - * the catch clause + * the catch clause */ mono_monoctx_to_sigctx (&mctx, ctx); return result; diff --git a/src/mono/mono/mini/exceptions-s390x.c b/src/mono/mono/mini/exceptions-s390x.c index c1e0e420c6873..c13ede7e922fd 100644 --- a/src/mono/mono/mini/exceptions-s390x.c +++ b/src/mono/mono/mini/exceptions-s390x.c @@ -70,9 +70,9 @@ /* P r o t o t y p e s */ /*------------------------------------------------------------------*/ -static void throw_exception (MonoObject *, unsigned long, unsigned long, +static void throw_exception (MonoObject *, unsigned long, unsigned long, host_mgreg_t *, gdouble *, gint32 *, guint, gboolean, gboolean); -static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **, +static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **, int, gboolean, gboolean, gboolean); static void handle_signal_exception (gpointer); @@ -169,7 +169,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) /*------------------------------------------------------*/ /* Load all registers with values from the context */ /*------------------------------------------------------*/ - s390_lmg (code, s390_r3, s390_r12, s390_r13, + s390_lmg (code, s390_r3, s390_r12, s390_r13, G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[3])); pos = G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs[0]); for (i = 0; i < 16; ++i) { @@ -222,7 +222,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (code, s390_r14); - g_assert ((code - start) < SZ_THROW); + g_assert ((code - start) < SZ_THROW); mono_arch_flush_icache(start, code - start); MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); @@ -246,7 +246,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) /*------------------------------------------------------------------*/ static void -throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, +throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, host_mgreg_t *int_regs, gdouble *fp_regs, gint32 *acc_regs, guint fpc, gboolean rethrow, gboolean preserve_ips) { @@ -271,7 +271,7 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, MONO_CONTEXT_SET_BP (&ctx, sp); MONO_CONTEXT_SET_IP (&ctx, ip); - + if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow && !mono_ex->caught_in_unmanaged) { @@ -303,8 +303,8 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, /* */ /*------------------------------------------------------------------*/ -static gpointer -mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, +static gpointer +mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot, gboolean preserve_ips) { guint8 *code, *start; @@ -387,9 +387,9 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) - *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" - : (rethrow ? "rethrow_exception" - : (preserve_ips ? "rethrow_preserve_exception" + *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" + : (rethrow ? "rethrow_exception" + : (preserve_ips ? "rethrow_preserve_exception" : "throw_exception")), start, code - start, ji, unwind_ops); @@ -433,7 +433,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) /* */ /*------------------------------------------------------------------*/ -gpointer +gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) { g_assert (!aot); @@ -456,7 +456,7 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /* */ /*------------------------------------------------------------------*/ -gpointer +gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { g_assert (!aot); @@ -487,7 +487,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) *info = NULL; return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot, FALSE)); -} +} /*========================= End of Function ========================*/ @@ -500,8 +500,8 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) /*------------------------------------------------------------------*/ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) @@ -548,7 +548,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MONO_CONTEXT_SET_IP(new_ctx, regs[14] - 2); MONO_CONTEXT_SET_BP(new_ctx, regs[15]); MONO_CONTEXT_SET_SP(new_ctx, regs[15]); - + return TRUE; } else if (*lmf) { @@ -556,7 +556,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, if (!ji) { if (!(*lmf)->method) return FALSE; - + frame->method = (*lmf)->method; } @@ -782,7 +782,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) /*========================= End of Function ========================*/ /** - * + * * @brief Setup CTX so execution resumes at FUNC * * @param[in] Context to be resumed @@ -829,19 +829,19 @@ mono_arch_is_int_overflow (void *uc, void *info) /*----------------------------------------------------------*/ switch (code[0]) { case 0x1d : /* Divide Register */ - regNo = code[1] & 0x0f; + regNo = code[1] & 0x0f; if (ctx->uc_mcontext.gregs[regNo] == 0) arithExc = FALSE; break; case 0x5d : /* Divide */ - regNo = (code[2] & 0xf0 >> 8); + regNo = (code[2] & 0xf0 >> 8); idxNo = (code[1] & 0x0f); offset = *((guint16 *) code+2) & 0x0fff; operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset); if (idxNo != 0) operand += ctx->uc_mcontext.gregs[idxNo]; if (*operand == 0) - arithExc = FALSE; + arithExc = FALSE; break; case 0xb9 : /* DL[GR] or DS[GR] */ if ((code[1] == 0x97) || (code[1] == 0x87) || @@ -854,15 +854,15 @@ mono_arch_is_int_overflow (void *uc, void *info) case 0xe3 : /* DL[G] | DS[G] */ if ((code[5] == 0x97) || (code[5] == 0x87) || (code[5] == 0x0d) || (code[5] == 0x1d)) { - regNo = (code[2] & 0xf0 >> 8); + regNo = (code[2] & 0xf0 >> 8); idxNo = (code[1] & 0x0f); - offset = (code[2] & 0x0f << 8) + + offset = (code[2] & 0x0f << 8) + code[3] + (code[4] << 12); operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset); if (idxNo != 0) operand += ctx->uc_mcontext.gregs[idxNo]; if (*operand == 0) - arithExc = FALSE; + arithExc = FALSE; } break; default: diff --git a/src/mono/mono/mini/exceptions-sparc.c b/src/mono/mono/mini/exceptions-sparc.c index bd41fdbe55ebb..01dc27d1acf60 100644 --- a/src/mono/mono/mini/exceptions-sparc.c +++ b/src/mono/mono/mini/exceptions-sparc.c @@ -76,7 +76,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) * mono_arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We - * also use this function to call finally handlers (we pass NULL as + * also use this function to call finally handlers (we pass NULL as * @exc object in this case). * * call_filter (MonoContext *ctx, gpointer ip) @@ -127,7 +127,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) sparc_mov_reg_reg (code, sparc_fp, sparc_o7); - /* + /* * Modify the second frame so it is identical to the one used in the * method containing the filter. */ @@ -173,7 +173,7 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gb MonoContext ctx; static void (*restore_context) (MonoContext *); gpointer *window; - + if (!restore_context) restore_context = mono_get_restore_context (); @@ -198,7 +198,7 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gb g_assert_not_reached (); } -static gpointer +static gpointer get_throw_exception (gboolean rethrow, gboolean preserve_ips) { guint32 *start, *code; @@ -228,8 +228,8 @@ get_throw_exception (gboolean rethrow, gboolean preserve_ips) /** * mono_arch_get_throw_exception: * \returns a function pointer which can be used to raise exceptions. - * The returned function has the following - * signature: void (*func) (MonoException *exc); + * The returned function has the following + * signature: void (*func) (MonoException *exc); */ gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) @@ -293,11 +293,11 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_throw_corlib_exception: - * \returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (guint32 ex_token, guint32 offset); - * Here, offset is the offset which needs to be substracted from the caller IP - * to get the IP of the throw. Passing the offset has the advantage that it + * \returns a function pointer which can be used to raise + * corlib exceptions. The returned function has the following + * signature: void (*func) (guint32 ex_token, guint32 offset); + * Here, offset is the offset which needs to be substracted from the caller IP + * to get the IP of the throw. Passing the offset has the advantage that it * needs no relocations in the caller. */ gpointer @@ -356,16 +356,16 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) /* mono_arch_unwind_frame: * - * This function is used to gather information from @ctx. It return the + * This function is used to gather information from @ctx. It return the * MonoJitInfo of the corresponding function, unwinds one stack frame and - * stores the resulting context into @new_ctx. It also stores a string + * stores the resulting context into @new_ctx. It also stores a string * describing the stack location into @trace (if not NULL), and modifies - * the @lmf if necessary. @native_offset return the IP offset from the + * the @lmf if necessary. @native_offset return the IP offset from the * start of the function or -1 if that info is not available. */ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) @@ -490,7 +490,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj) mctx.fp = window [sparc_fp - 16]; mono_handle_exception (&mctx, obj); - + /* We can't use restore_context to return from a signal handler */ ctx->uc_mcontext.gregs [REG_PC] = mctx.ip; ctx->uc_mcontext.gregs [REG_nPC] = mctx.ip + 4; diff --git a/src/mono/mono/mini/exceptions-wasm.c b/src/mono/mono/mini/exceptions-wasm.c index 05a1cbad2f3eb..14545de35369b 100644 --- a/src/mono/mono/mini/exceptions-wasm.c +++ b/src/mono/mono/mini/exceptions-wasm.c @@ -38,7 +38,7 @@ wasm_throw_corlib_exception (void) } gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, @@ -96,7 +96,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) *info = mono_tramp_info_create ("restore_context", (guint8*)wasm_restore_context, 1, NULL, NULL); return (gpointer)wasm_restore_context; } -gpointer +gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { if (info) diff --git a/src/mono/mono/mini/exceptions-x86.c b/src/mono/mono/mini/exceptions-x86.c index 1c451717415c6..db6a76e5e06ed 100644 --- a/src/mono/mono/mini/exceptions-x86.c +++ b/src/mono/mono/mini/exceptions-x86.c @@ -130,19 +130,19 @@ mono_win32_get_handle_stackoverflow (void) * * Stack walking part of this method is from mono_handle_exception * - * The idea is simple; + * The idea is simple; * - walk the stack to free some space (64k) * - set esp to new stack location * - call mono_arch_handle_exception with stack overflow exception * - set esp to SEH handlers stack * - done */ -static void +static void win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, CONTEXT *sctx) { MonoJitInfo rji; MonoJitTlsData *jit_tls = mono_tls_get_jit_tls (); - MonoLMF *lmf = jit_tls->lmf; + MonoLMF *lmf = jit_tls->lmf; MonoContext initial_ctx; MonoContext ctx; guint32 free_stack = 0; @@ -295,7 +295,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) const int size = 128; start = code = mono_global_codeman_reserve (size); - + /* load ctx */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4); @@ -371,7 +371,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) * mono_arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We - * also use this function to call finally handlers (we pass NULL as + * also use this function to call finally handlers (we pass NULL as * @exc object in this case). */ gpointer @@ -495,7 +495,7 @@ mono_x86_throw_exception (host_mgreg_t *regs, MonoObject *exc, } void -mono_x86_throw_corlib_exception (host_mgreg_t *regs, guint32 ex_token_index, +mono_x86_throw_corlib_exception (host_mgreg_t *regs, guint32 ex_token_index, host_mgreg_t eip, gint32 pc_offset) { guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index; @@ -512,7 +512,7 @@ mono_x86_throw_corlib_exception (host_mgreg_t *regs, guint32 ex_token_index, } static void -mono_x86_resume_unwind (host_mgreg_t *regs, MonoObject *exc, +mono_x86_resume_unwind (host_mgreg_t *regs, MonoObject *exc, host_mgreg_t eip, gboolean rethrow) { MonoContext ctx; @@ -535,7 +535,7 @@ mono_x86_resume_unwind (host_mgreg_t *regs, MonoObject *exc, * * Generate a call to mono_x86_throw_exception/ * mono_x86_throw_corlib_exception. - * If LLVM is true, generate code which assumes the caller is LLVM generated code, + * If LLVM is true, generate code which assumes the caller is LLVM generated code, * which doesn't push the arguments. */ static guint8* @@ -551,7 +551,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea stack_size = 128; - /* + /* * On apple, the stack is misaligned by the pushing of the return address. */ if (!llvm && corlib) @@ -644,7 +644,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea } else if (corlib) { x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 8, 4); if (llvm_abs) { - /* + /* * The caller is LLVM code which passes the absolute address not a pc offset, * so compensate by passing 0 as 'ip' and passing the negated abs address as * the pc offset. @@ -691,28 +691,28 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea /** * mono_arch_get_throw_exception: - * \returns a function pointer which can be used to raise - * exceptions. The returned function has the following - * signature: void (*func) (MonoException *exc); + * \returns a function pointer which can be used to raise + * exceptions. The returned function has the following + * signature: void (*func) (MonoException *exc); * For example to raise an arithmetic exception you can use: * - * x86_push_imm (code, mono_get_exception_arithmetic ()); - * x86_call_code (code, arch_get_throw_exception ()); + * x86_push_imm (code, mono_get_exception_arithmetic ()); + * x86_call_code (code, arch_get_throw_exception ()); * */ -gpointer +gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline ("throw_exception", FALSE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE); } -gpointer +gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline ("rethrow_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE); } -gpointer +gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline ("rethrow_preserve_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, TRUE); @@ -720,14 +720,14 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) /** * mono_arch_get_throw_corlib_exception: - * \returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (guint32 ex_token, guint32 offset); - * Here, offset is the offset which needs to be substracted from the caller IP - * to get the IP of the throw. Passing the offset has the advantage that it + * \returns a function pointer which can be used to raise + * corlib exceptions. The returned function has the following + * signature: void (*func) (guint32 ex_token, guint32 offset); + * Here, offset is the offset which needs to be substracted from the caller IP + * to get the IP of the throw. Passing the offset has the advantage that it * needs no relocations in the caller. */ -gpointer +gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { return get_throw_trampoline ("throw_corlib_exception", FALSE, FALSE, TRUE, FALSE, FALSE, info, aot, FALSE); @@ -739,8 +739,8 @@ mono_arch_exceptions_init (void) guint8 *tramp; MonoTrampInfo *tinfo; -/* - * If we're running WoW64, we need to set the usermode exception policy +/* + * If we're running WoW64, we need to set the usermode exception policy * for SEHs to behave. This requires hotfix http://support.microsoft.com/kb/976038 * or (eventually) Windows 7 SP1. */ @@ -799,8 +799,8 @@ mono_arch_exceptions_init (void) * See exceptions-amd64.c for docs. */ gboolean -mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, +mono_arch_unwind_frame (MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) @@ -1074,7 +1074,7 @@ restore_soft_guard_pages (void) return NULL; } -/* +/* * this function modifies mctx so that when it is restored, it * won't execcute starting at mctx.eip, but in a function that * will restore the protection on the soft-guard pages and return back to diff --git a/src/mono/mono/mini/graph.c b/src/mono/mono/mini/graph.c index 4d6902d34a83a..f078f9c0e9502 100644 --- a/src/mono/mono/mini/graph.c +++ b/src/mono/mono/mini/graph.c @@ -52,7 +52,7 @@ dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h) level = h->nesting; fprintf (fp, "subgraph cluster_%d {\n", h->block_num); fprintf (fp, "label=\"loop_%d\"\n", h->block_num); - } + } for (i = 1; i < cfg->num_bblocks; ++i) { bb = cfg->bblocks [i]; @@ -61,14 +61,14 @@ dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h) if (bb->nesting == level) { fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num); } - + if (bb->nesting == (level + 1) && bb->loop_blocks) { fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num); dtree_emit_one_loop_level (cfg, fp, bb); } } } - + if (h) { fprintf (fp, "}\n"); } @@ -84,7 +84,7 @@ cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h) level = h->nesting; fprintf (fp, "subgraph cluster_%d {\n", h->block_num); fprintf (fp, "label=\"loop_%d\"\n", h->block_num); - } + } for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) { if (bb->region != -1) { @@ -107,18 +107,18 @@ cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h) if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) { if (bb->nesting == level) { - for (j = 0; j < bb->in_count; j++) + for (j = 0; j < bb->in_count; j++) fprintf (fp, "BB%d -> BB%d;\n", bb->in_bb [j]->block_num, bb->block_num); } - + if (bb->nesting == (level + 1) && bb->loop_blocks) { - for (j = 0; j < bb->in_count; j++) + for (j = 0; j < bb->in_count; j++) fprintf (fp, "BB%d -> BB%d;\n", bb->in_bb [j]->block_num, bb->block_num); cfg_emit_one_loop_level (cfg, fp, bb); } } } - + if (h) { fprintf (fp, "}\n"); } @@ -160,7 +160,7 @@ static void mono_draw_code_cfg (MonoCompile *cfg, FILE *fp) { MonoBasicBlock *bb; - + fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name)); fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n"); fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE)); @@ -181,13 +181,13 @@ mono_draw_code_cfg (MonoCompile *cfg, FILE *fp) color = ""; fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num); - + MONO_BB_FOR_EACH_INS (bb, inst) { //mono_print_label (fp, inst); - fprintf (fp, "\\n"); + fprintf (fp, "\\n"); } - fprintf (fp, "}\"];\n"); + fprintf (fp, "}\"];\n"); } cfg_emit_one_loop_level (cfg, fp, NULL); diff --git a/src/mono/mono/mini/helpers.c b/src/mono/mono/mini/helpers.c index 47525d02fec1a..0d83439c775f8 100644 --- a/src/mono/mono/mini/helpers.c +++ b/src/mono/mono/mini/helpers.c @@ -88,20 +88,20 @@ mono_inst_name (int op) { } void -mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom) +mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom) { #ifndef DISABLE_LOGGING int i; if (name) g_print ("%s:", name); - + mono_bitset_foreach_bit (set, i, cfg->num_bblocks) { if (idom == i) g_print (" [BB%d]", cfg->bblocks [i]->block_num); else g_print (" BB%d", cfg->bblocks [i]->block_num); - + } g_print ("\n"); #endif @@ -129,11 +129,11 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) int unused G_GNUC_UNUSED; #ifdef HOST_WIN32 - as_file = g_strdup_printf ("%s/test.s", tmp); + as_file = g_strdup_printf ("%s/test.s", tmp); if (!(ofd = fopen (as_file, "w"))) g_assert_not_reached (); -#else +#else i = g_file_open_tmp (NULL, &as_file, NULL); ofd = fdopen (i, "w"); g_assert (ofd); @@ -247,14 +247,14 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) #ifdef HOST_WIN32 o_file = g_strdup_printf ("%s/test.o", tmp); -#else +#else i = g_file_open_tmp (NULL, &o_file, NULL); close (i); #endif #ifdef HAVE_SYSTEM char *cmd = g_strdup_printf (ARCH_PREFIX AS_CMD " %s -o %s", as_file, o_file); - unused = system (cmd); + unused = system (cmd); g_free (cmd); char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS"); if (!objdump_args) @@ -263,8 +263,8 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) fflush (stdout); #if (defined(__arm__) || defined(__aarch64__)) && !defined(TARGET_OSX) - /* - * The arm assembler inserts ELF directives instructing objdump to display + /* + * The arm assembler inserts ELF directives instructing objdump to display * everything as data. */ cmd = g_strdup_printf (ARCH_PREFIX "strip -s %s", o_file); diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index a06a92420c884..164a7080a7fc6 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -101,8 +101,8 @@ typedef enum { #define INTERP_IMETHOD_IS_TAGGED_UNBOX(im) ((mono_u)(im) & 1) #define INTERP_IMETHOD_UNTAG_UNBOX(im) ((InterpMethod*)((mono_u)(im) & ~1)) -/* - * Structure representing a method transformed for the interpreter +/* + * Structure representing a method transformed for the interpreter */ typedef struct InterpMethod InterpMethod; struct InterpMethod { @@ -227,11 +227,6 @@ typedef struct { guchar *stack_pointer; /* Used for allocation of localloc regions */ FrameDataAllocator data_stack; - /* Used when a thread self-suspends at a safepoint in the interpreter, points to the - * currently executing frame. (If a thread self-suspends somewhere else in the runtime, this - * is NULL - the LMF will point to the InterpFrame before the thread exited the interpreter) - */ - InterpFrame *safepoint_frame; } ThreadContext; typedef struct { diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index e5aef94c5c6ee..fa00bca3b67d3 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -248,7 +248,7 @@ static gboolean interp_init_done = FALSE; static void interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args); -static MonoException* do_transform_method (InterpFrame *frame, ThreadContext *context); +static MonoException* do_transform_method (InterpMethod *imethod, InterpFrame *method, ThreadContext *context); static InterpMethod* lookup_method_pointer (gpointer addr); @@ -419,8 +419,6 @@ interp_free_context (gpointer ctx) set_context (NULL); } - context->safepoint_frame = NULL; - mono_vfree (context->stack_start, INTERP_STACK_SIZE, MONO_MEM_ACCOUNT_INTERP_STACK); /* Prevent interp_mark_stack from trying to scan the data_stack, before freeing it */ context->stack_start = NULL; @@ -429,19 +427,6 @@ interp_free_context (gpointer ctx) g_free (context); } -static void -context_set_safepoint_frame (ThreadContext *context, InterpFrame *frame) -{ - g_assert (!context->has_resume_state); - context->safepoint_frame = frame; -} - -static void -context_clear_safepoint_frame (ThreadContext *context) -{ - context->safepoint_frame = NULL; -} - void mono_interp_error_cleanup (MonoError* error) { @@ -1052,6 +1037,8 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con */ frame->state.ip = ip + 1; + interp_push_lmf (&ext, frame); + if (mono_object_isinst_checked ((MonoObject *) ex, mono_defaults.exception_class, error)) { MonoException *mono_ex = ex; if (!rethrow) { @@ -1071,7 +1058,6 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con * Since ctx.ip is 0, this will start unwinding from the LMF frame * pushed above, which points to our frames. */ - interp_push_lmf (&ext, frame); mono_handle_exception (&ctx, (MonoObject*)ex); @@ -1086,6 +1072,62 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con g_assert (context->has_resume_state); } +static MONO_NEVER_INLINE MonoException * +interp_error_convert_to_exception (InterpFrame *frame, MonoError *error, const guint16 *ip) +{ + MonoLMFExt ext; + MonoException *ex; + + /* + * When calling runtime functions we pass the ip of the instruction triggering the runtime call. + * Offset the subtraction from interp_frame_get_ip, so we don't end up in prev instruction. + */ + frame->state.ip = ip + 1; + + interp_push_lmf (&ext, frame); + ex = mono_error_convert_to_exception (error); + interp_pop_lmf (&ext); + return ex; +} + +#define INTERP_BUILD_EXCEPTION_TYPE_FUNC_NAME(prefix_name, type_name) \ +prefix_name ## _ ## type_name + +#define INTERP_GET_EXCEPTION(exception_type) \ +static MONO_NEVER_INLINE MonoException * \ +INTERP_BUILD_EXCEPTION_TYPE_FUNC_NAME(interp_get_exception, exception_type) (InterpFrame *frame, const guint16 *ip)\ +{ \ + MonoLMFExt ext; \ + MonoException *ex; \ + frame->state.ip = ip + 1; \ + interp_push_lmf (&ext, frame); \ + ex = INTERP_BUILD_EXCEPTION_TYPE_FUNC_NAME(mono_get_exception,exception_type) (); \ + interp_pop_lmf (&ext); \ + return ex; \ +} + +#define INTERP_GET_EXCEPTION_CHAR_ARG(exception_type) \ +static MONO_NEVER_INLINE MonoException * \ +INTERP_BUILD_EXCEPTION_TYPE_FUNC_NAME(interp_get_exception, exception_type) (const char *arg, InterpFrame *frame, const guint16 *ip)\ +{ \ + MonoLMFExt ext; \ + MonoException *ex; \ + frame->state.ip = ip + 1; \ + interp_push_lmf (&ext, frame); \ + ex = INTERP_BUILD_EXCEPTION_TYPE_FUNC_NAME(mono_get_exception,exception_type) (arg); \ + interp_pop_lmf (&ext); \ + return ex; \ +} + +INTERP_GET_EXCEPTION(null_reference) +INTERP_GET_EXCEPTION(divide_by_zero) +INTERP_GET_EXCEPTION(overflow) +INTERP_GET_EXCEPTION(invalid_cast) +INTERP_GET_EXCEPTION(index_out_of_range) +INTERP_GET_EXCEPTION(array_type_mismatch) +INTERP_GET_EXCEPTION(arithmetic) +INTERP_GET_EXCEPTION_CHAR_ARG(argument_out_of_range) + // We conservatively pin exception object here to avoid tweaking the // numerous call sites of this macro, even though, in a few cases, // this is not needed. @@ -1102,7 +1144,7 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con #define NULL_CHECK(o) do { \ if (G_UNLIKELY (!(o))) \ - THROW_EX (mono_get_exception_null_reference (), ip); \ + THROW_EX (interp_get_exception_null_reference (frame, ip), ip); \ } while (0) #define EXCEPTION_CHECKPOINT \ @@ -1115,19 +1157,27 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con } while (0) // Reduce duplicate code in interp_exec_method -static void -do_safepoint (InterpFrame *frame, ThreadContext *context) +static MONO_NEVER_INLINE void +do_safepoint (InterpFrame *frame, ThreadContext *context, const guint16 *ip) { - context_set_safepoint_frame (context, frame); + MonoLMFExt ext; + + /* + * When calling runtime functions we pass the ip of the instruction triggering the runtime call. + * Offset the subtraction from interp_frame_get_ip, so we don't end up in prev instruction. + */ + frame->state.ip = ip + 1; + + interp_push_lmf (&ext, frame); /* Poll safepoint */ mono_threads_safepoint (); - context_clear_safepoint_frame (context); + interp_pop_lmf (&ext); } #define SAFEPOINT \ do { \ if (G_UNLIKELY (mono_polling_required)) \ - do_safepoint (frame, context); \ + do_safepoint (frame, context, ip); \ } while (0) static MonoObject* @@ -1534,11 +1584,11 @@ interp_frame_arg_to_data (MonoInterpFrameHandle frame, MonoMethodSignature *sig, // If index == -1, we finished executing an InterpFrame and the result is at retval. if (index == -1) - stackval_to_data (sig->ret, iframe->retval, data, TRUE); + stackval_to_data (sig->ret, iframe->retval, data, sig->pinvoke && !sig->marshalling_disabled); else if (sig->hasthis && index == 0) *(gpointer*)data = iframe->stack->data.p; else - stackval_to_data (sig->params [index - sig->hasthis], STACK_ADD_BYTES (iframe->stack, get_arg_offset (imethod, sig, index)), data, sig->pinvoke); + stackval_to_data (sig->params [index - sig->hasthis], STACK_ADD_BYTES (iframe->stack, get_arg_offset (imethod, sig, index)), data, sig->pinvoke && !sig->marshalling_disabled); } static void @@ -1549,11 +1599,11 @@ interp_data_to_frame_arg (MonoInterpFrameHandle frame, MonoMethodSignature *sig, // Get result from pinvoke call, put it directly on top of execution stack in the caller frame if (index == -1) - stackval_from_data (sig->ret, iframe->retval, data, TRUE); + stackval_from_data (sig->ret, iframe->retval, data, sig->pinvoke && !sig->marshalling_disabled); else if (sig->hasthis && index == 0) iframe->stack->data.p = *(gpointer*)data; else - stackval_from_data (sig->params [index - sig->hasthis], STACK_ADD_BYTES (iframe->stack, get_arg_offset (imethod, sig, index)), data, sig->pinvoke); + stackval_from_data (sig->params [index - sig->hasthis], STACK_ADD_BYTES (iframe->stack, get_arg_offset (imethod, sig, index)), data, sig->pinvoke && !sig->marshalling_disabled); } static gpointer @@ -1685,7 +1735,7 @@ ves_pinvoke_method ( #else // Only the vt address has been returned, we need to copy the entire content on interp stack if (!context->has_resume_state && MONO_TYPE_ISSTRUCT (sig->ret)) - stackval_from_data (sig->ret, frame.retval, (char*)frame.retval->data.p, sig->pinvoke); + stackval_from_data (sig->ret, frame.retval, (char*)frame.retval->data.p, sig->pinvoke && !sig->marshalling_disabled); g_free (margs->iargs); g_free (margs->fargs); @@ -1930,7 +1980,7 @@ dump_args (InterpFrame *inv) GString *str = g_string_new (""); int i; MonoMethodSignature *signature = mono_method_signature_internal (inv->imethod->method); - + if (signature->param_count == 0 && !signature->hasthis) return g_string_free (str, FALSE); @@ -2163,8 +2213,6 @@ interp_entry (InterpEntryData *data) context->stack_pointer = (guchar*)sp; - g_assert (!context->safepoint_frame); - if (rmethod->needs_thread_attach) mono_threads_detach_coop (orig_domain, &attach_cookie); @@ -2282,7 +2330,7 @@ do_icall (MonoMethodSignature *sig, int op, stackval *ret_sp, stackval *sp, gpoi /* convert the native representation to the stackval representation */ if (sig) - stackval_from_data (sig->ret, ret_sp, (char*) &ret_sp->data.p, sig->pinvoke); + stackval_from_data (sig->ret, ret_sp, (char*) &ret_sp->data.p, sig->pinvoke && !sig->marshalling_disabled); } /* MONO_NO_OPTIMIZATION is needed due to usage of INTERP_PUSH_LMF_WITH_CTX. */ @@ -2634,29 +2682,34 @@ do_debugger_tramp (void (*tramp) (void), InterpFrame *frame) } static MONO_NEVER_INLINE MonoException* -do_transform_method (InterpFrame *frame, ThreadContext *context) +do_transform_method (InterpMethod *imethod, InterpFrame *frame, ThreadContext *context) { MonoLMFExt ext; /* Don't push lmf if we have no interp data */ gboolean push_lmf = frame->parent != NULL; + MonoException *ex = NULL; ERROR_DECL (error); -#if DEBUG_INTERP - char *mn = mono_method_full_name (frame->imethod->method, TRUE); - g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn); - g_free (mn); -#endif - /* Use the parent frame as the current frame is not complete yet */ if (push_lmf) interp_push_lmf (&ext, frame->parent); - mono_interp_transform_method (frame->imethod, context, error); +#if DEBUG_INTERP + if (imethod->method) { + char* mn = mono_method_full_name (imethod->method, TRUE); + g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn); + g_free (mn); + } +#endif + + mono_interp_transform_method (imethod, context, error); + if (!is_ok (error)) + ex = mono_error_convert_to_exception (error); if (push_lmf) interp_pop_lmf (&ext); - return mono_error_convert_to_exception (error); + return ex; } static void @@ -2879,7 +2932,7 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype if (type->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (type)) { size = mono_class_value_size (mono_class_from_mono_type_internal (type), NULL); } else if (type->type == MONO_TYPE_VALUETYPE) { - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (type->data.klass, NULL); else size = mono_class_value_size (type->data.klass, NULL); @@ -3232,7 +3285,7 @@ static long opcode_counts[MINT_LASTOP]; #define COUNT_OP(op) opcode_counts[op]++ #else -#define COUNT_OP(op) +#define COUNT_OP(op) #endif #if DEBUG_INTERP @@ -3249,11 +3302,31 @@ static long opcode_counts[MINT_LASTOP]; #define DUMP_INSTR() #endif +static MONO_NEVER_INLINE MonoException* +do_init_vtable (MonoVTable *vtable, MonoError *error, InterpFrame *frame, const guint16 *ip) +{ + MonoLMFExt ext; + MonoException *ex = NULL; + + /* + * When calling runtime functions we pass the ip of the instruction triggering the runtime call. + * Offset the subtraction from interp_frame_get_ip, so we don't end up in prev instruction. + */ + frame->state.ip = ip + 1; + + interp_push_lmf (&ext, frame); + mono_runtime_class_init_full (vtable, error); + if (!is_ok (error)) + ex = mono_error_convert_to_exception (error); + interp_pop_lmf (&ext); + return ex; +} + #define INIT_VTABLE(vtable) do { \ if (G_UNLIKELY (!(vtable)->initialized)) { \ - mono_runtime_class_init_full ((vtable), error); \ - if (!is_ok (error)) \ - THROW_EX (mono_error_convert_to_exception (error), ip); \ + MonoException *__init_vtable_ex = do_init_vtable ((vtable), error, frame, ip); \ + if (G_UNLIKELY (__init_vtable_ex)) \ + THROW_EX (__init_vtable_ex, ip); \ } \ } while (0); @@ -3363,7 +3436,7 @@ method_entry (ThreadContext *context, InterpFrame *frame, *out_ex = NULL; if (!G_UNLIKELY (frame->imethod->transformed)) { slow = TRUE; - MonoException *ex = do_transform_method (frame, context); + MonoException *ex = do_transform_method (frame->imethod, frame, context); if (ex) { *out_ex = ex; /* @@ -3478,7 +3551,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs #endif main_loop: /* - * using while (ip < end) may result in a 15% performance drop, + * using while (ip < end) may result in a 15% performance drop, * but it may be useful for debug */ while (1) { @@ -3559,7 +3632,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs MINT_IN_CASE(MINT_LDC_I4_8) LDC(8); MINT_IN_BREAK; - MINT_IN_CASE(MINT_LDC_I4_S) + MINT_IN_CASE(MINT_LDC_I4_S) LOCAL_VAR (ip [1], gint32) = (short)ip [2]; ip += 3; MINT_IN_BREAK; @@ -3584,7 +3657,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs ip += 4; MINT_IN_BREAK; } - MINT_IN_CASE(MINT_LDC_R8) + MINT_IN_CASE(MINT_LDC_R8) LOCAL_VAR (ip [1], gint64) = READ64 (ip + 2); /* note union usage */ ip += 6; MINT_IN_BREAK; @@ -3620,10 +3693,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs MONO_PROFILER_RAISE (method_tail_call, (frame->imethod->method, new_method->method)); if (!new_method->transformed) { - error_init_reuse (error); - - mono_interp_transform_method (new_method, context, error); - MonoException *ex = mono_error_convert_to_exception (error); + MonoException *ex = do_transform_method (new_method, frame, context); if (ex) THROW_EX (ex, ip); EXCEPTION_CHECKPOINT; @@ -3648,6 +3718,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs InterpMethod *del_imethod = (InterpMethod*)del->interp_invoke_impl; if (!del_imethod) { + // FIXME push/pop LMF if (is_multicast) { error_init_reuse (error); MonoMethod *invoke = mono_get_delegate_invoke_internal (del->object.vtable->klass); @@ -3712,6 +3783,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs cmethod = ftnptr_to_imethod (LOCAL_VAR (ip [2], gpointer), &need_unbox); if (cmethod->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { + // FIXME push/pop LMF cmethod = mono_interp_get_imethod (mono_marshal_get_native_wrapper (cmethod->method, FALSE, FALSE), error); mono_interp_error_cleanup (error); /* FIXME: don't swallow the error */ } @@ -3720,7 +3792,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs call_args_offset = ip [3]; if (need_unbox) { - MonoObject *this_arg = LOCAL_VAR (call_args_offset, MonoObject*); + MonoObject *this_arg = LOCAL_VAR (call_args_offset, MonoObject*); LOCAL_VAR (call_args_offset, gpointer) = mono_object_unbox_internal (this_arg); } ip += 4; @@ -3751,6 +3823,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs guchar* code = LOCAL_VAR (ip [2], guchar*); call_args_offset = ip [3]; + // FIXME push/pop LMF cmethod = mono_interp_get_native_func_wrapper (frame->imethod, csignature, code); ip += 5; @@ -3786,6 +3859,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs slot = (gint16)ip [4]; ip += 5; + // FIXME push/pop LMF cmethod = get_virtual_method_fast (cmethod, this_arg->vtable, slot); if (m_class_is_valuetype (this_arg->vtable->klass) && m_class_is_valuetype (cmethod->method->klass)) { /* unbox */ @@ -3800,6 +3874,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs code_type == IMETHOD_CODE_COMPILED); if (G_UNLIKELY (code_type == IMETHOD_CODE_UNKNOWN)) { + // FIXME push/pop LMF MonoMethodSignature *sig = mono_method_signature_internal (cmethod->method); if (mono_interp_jit_call_supported (cmethod->method, sig)) code_type = IMETHOD_CODE_COMPILED; @@ -3817,7 +3892,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs error_init_reuse (error); do_jit_call (context, (stackval*)(locals + return_offset), (stackval*)(locals + call_args_offset), frame, cmethod, error); if (!is_ok (error)) { - MonoException *ex = mono_error_convert_to_exception (error); + MonoException *ex = interp_error_convert_to_exception (frame, error, ip); THROW_EX (ex, ip); } @@ -3844,6 +3919,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs MonoObject *this_arg = LOCAL_VAR (call_args_offset, MonoObject*); + // FIXME push/pop LMF cmethod = get_virtual_method (cmethod, this_arg->vtable); if (m_class_is_valuetype (this_arg->vtable->klass) && m_class_is_valuetype (cmethod->method->klass)) { /* unbox */ @@ -3912,7 +3988,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs frame->state.ip = ip + 4; do_jit_call (context, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [2]), frame, rmethod, error); if (!is_ok (error)) { - MonoException *ex = mono_error_convert_to_exception (error); + MonoException *ex = interp_error_convert_to_exception (frame, error, ip); THROW_EX (ex, ip); } @@ -3930,7 +4006,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs frame->state.ip = ip + 6; do_jit_call (context, (stackval*)(locals + ip [1]), frame, rmethod, error); if (!is_ok (error)) { - MonoException *ex = mono_error_convert_to_exception (error); + MonoException *ex = interp_error_convert_to_exception (frame, error); THROW_EX (ex, ip); } @@ -4828,9 +4904,9 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 i1 = LOCAL_VAR (ip [2], gint32); gint32 i2 = LOCAL_VAR (ip [3], gint32); if (i2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); if (i2 == (-1) && i1 == G_MININT32) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = i1 / i2; ip += 4; MINT_IN_BREAK; @@ -4839,9 +4915,9 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint64 l1 = LOCAL_VAR (ip [2], gint64); gint64 l2 = LOCAL_VAR (ip [3], gint64); if (l2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); if (l2 == (-1) && l1 == G_MININT64) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 / l2; ip += 4; MINT_IN_BREAK; @@ -4855,7 +4931,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_DIV_UN_I4) { guint32 i2 = LOCAL_VAR (ip [3], guint32); if (i2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); LOCAL_VAR (ip [1], guint32) = LOCAL_VAR (ip [2], guint32) / i2; ip += 4; MINT_IN_BREAK; @@ -4863,7 +4939,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_DIV_UN_I8) { guint64 l2 = LOCAL_VAR (ip [3], guint64); if (l2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = LOCAL_VAR (ip [2], guint64) / l2; ip += 4; MINT_IN_BREAK; @@ -4872,9 +4948,9 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 i1 = LOCAL_VAR (ip [2], gint32); gint32 i2 = LOCAL_VAR (ip [3], gint32); if (i2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); if (i2 == (-1) && i1 == G_MININT32) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = i1 % i2; ip += 4; MINT_IN_BREAK; @@ -4883,9 +4959,9 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint64 l1 = LOCAL_VAR (ip [2], gint64); gint64 l2 = LOCAL_VAR (ip [3], gint64); if (l2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); if (l2 == (-1) && l1 == G_MININT64) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 % l2; ip += 4; MINT_IN_BREAK; @@ -4901,7 +4977,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_REM_UN_I4) { guint32 i2 = LOCAL_VAR (ip [3], guint32); if (i2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); LOCAL_VAR (ip [1], guint32) = LOCAL_VAR (ip [2], guint32) % i2; ip += 4; MINT_IN_BREAK; @@ -4909,7 +4985,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_REM_UN_I8) { guint64 l2 = LOCAL_VAR (ip [3], guint64); if (l2 == 0) - THROW_EX (mono_get_exception_divide_by_zero (), ip); + THROW_EX (interp_get_exception_divide_by_zero (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = LOCAL_VAR (ip [2], guint64) % l2; ip += 4; MINT_IN_BREAK; @@ -5188,6 +5264,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) { s = (MonoString*)mono_method_get_wrapper_data (method, strtoken); } else if (method->wrapper_type != MONO_WRAPPER_NONE) { + // FIXME push/pop LMF s = mono_string_new_wrapper_internal ((const char*)mono_method_get_wrapper_data (method, strtoken)); } else { g_assert_not_reached (); @@ -5203,9 +5280,10 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; newobj_class = (MonoClass*) frame->imethod->data_items [token]; + // FIXME push/pop LMF LOCAL_VAR (ip [1], MonoObject*) = ves_array_create (newobj_class, param_count, (stackval*)(locals + ip [2]), error); if (!is_ok (error)) - THROW_EX (mono_error_convert_to_exception (error), ip); + THROW_EX (interp_error_convert_to_exception (frame, error, ip), ip); ip += 5; MINT_IN_BREAK; } @@ -5227,10 +5305,11 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; return_offset = ip [1]; call_args_offset = ip [2]; + // FIXME push/pop LMF MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass)); if (G_UNLIKELY (!o)) { mono_error_set_out_of_memory (error, "Could not allocate %i bytes", m_class_get_instance_size (vtable->klass)); - THROW_EX (mono_error_convert_to_exception (error), ip); + THROW_EX (interp_error_convert_to_exception (frame, error, ip), ip); } // This is return value @@ -5247,10 +5326,11 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [ip [2]]; INIT_VTABLE (vtable); + // FIXME push/pop LMF MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass)); if (G_UNLIKELY (!o)) { mono_error_set_out_of_memory (error, "Could not allocate %i bytes", m_class_get_instance_size (vtable->klass)); - THROW_EX (mono_error_convert_to_exception (error), ip); + THROW_EX (interp_error_convert_to_exception (frame, error, ip), ip); } // This is return value @@ -5301,9 +5381,10 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; g_assert (!m_class_is_valuetype (newobj_class)); + // FIXME push/pop LMF MonoVTable *vtable = mono_class_vtable_checked (newobj_class, error); if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) { - MonoException *exc = mono_error_convert_to_exception (error); + MonoException *exc = interp_error_convert_to_exception (frame, error, ip); g_assert (exc); THROW_EX (exc, ip); } @@ -5321,7 +5402,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gpointer ptr = LOCAL_VAR (ip [2], gpointer); int len = LOCAL_VAR (ip [3], gint32); if (len < 0) - THROW_EX (mono_get_exception_argument_out_of_range ("length"), ip); + THROW_EX (interp_get_exception_argument_out_of_range ("length", frame, ip), ip); gpointer span = locals + ip [1]; *(gpointer*)span = ptr; *(gint32*)((gpointer*)span + 1) = len; @@ -5395,6 +5476,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; isinst = TRUE; } else if (m_class_is_array_special_interface (c)) { /* slow path */ + // FIXME push/pop LMF isinst = mono_interp_isinst (o, c); // FIXME: do not swallow the error } else { isinst = FALSE; @@ -5405,7 +5487,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (isinst_instr) LOCAL_VAR (ip [1], MonoObject*) = NULL; else - THROW_EX (mono_get_exception_invalid_cast (), ip); + THROW_EX (interp_get_exception_invalid_cast (frame, ip), ip); } else { LOCAL_VAR (ip [1], MonoObject*) = o; } @@ -5427,7 +5509,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (isinst_instr) LOCAL_VAR (ip [1], MonoObject*) = NULL; else - THROW_EX (mono_get_exception_invalid_cast (), ip); + THROW_EX (interp_get_exception_invalid_cast (frame, ip), ip); } else { LOCAL_VAR (ip [1], MonoObject*) = o; } @@ -5442,12 +5524,13 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoObject *o = LOCAL_VAR (ip [2], MonoObject*); if (o) { MonoClass* const c = (MonoClass*)frame->imethod->data_items [ip [3]]; + // FIXME push/pop LMF if (!mono_interp_isinst (o, c)) { // FIXME: do not swallow the error gboolean const isinst_instr = *ip == MINT_ISINST; if (isinst_instr) LOCAL_VAR (ip [1], MonoObject*) = NULL; else - THROW_EX (mono_get_exception_invalid_cast (), ip); + THROW_EX (interp_get_exception_invalid_cast (frame, ip), ip); } else { LOCAL_VAR (ip [1], MonoObject*) = o; } @@ -5471,7 +5554,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoClass *c = (MonoClass*)frame->imethod->data_items [ip [3]]; if (!(m_class_get_rank (o->vtable->klass) == 0 && m_class_get_element_class (o->vtable->klass) == m_class_get_element_class (c))) - THROW_EX (mono_get_exception_invalid_cast (), ip); + THROW_EX (interp_get_exception_invalid_cast (frame, ip), ip); LOCAL_VAR (ip [1], gpointer) = mono_object_unbox_internal (o); ip += 4; @@ -5480,7 +5563,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_THROW) { MonoException *ex = LOCAL_VAR (ip [1], MonoException*); if (!ex) - ex = mono_get_exception_null_reference (); + ex = interp_get_exception_null_reference (frame, ip); THROW_EX (ex, ip); MINT_IN_BREAK; @@ -5689,7 +5772,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U8_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = val; ip += 3; MINT_IN_BREAK; @@ -5697,7 +5780,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U8_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = val; ip += 3; MINT_IN_BREAK; @@ -5705,7 +5788,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I8_U8) { guint64 val = LOCAL_VAR (ip [2], guint64); if (val > G_MAXINT64) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = val; ip += 3; MINT_IN_BREAK; @@ -5713,34 +5796,35 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U8_R4) { float val = LOCAL_VAR (ip [2], float); if (!mono_try_trunc_u64 (val, (guint64*)(locals + ip [1]))) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U8_R8) { double val = LOCAL_VAR (ip [2], double); if (!mono_try_trunc_u64 (val, (guint64*)(locals + ip [1]))) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I8_R4) { float val = LOCAL_VAR (ip [2], float); if (!mono_try_trunc_i64 (val, (gint64*)(locals + ip [1]))) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I8_R8) { double val = LOCAL_VAR (ip [2], double); if (!mono_try_trunc_i64 (val, (gint64*)(locals + ip [1]))) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_BOX) { MonoVTable *vtable = (MonoVTable*)frame->imethod->data_items [ip [3]]; + // FIXME push/pop LMF MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass)); MONO_HANDLE_ASSIGN_RAW (tmp_handle, o); stackval_to_data (m_class_get_byval_arg (vtable->klass), (stackval*)(locals + ip [2]), mono_object_get_data (o), FALSE); @@ -5754,6 +5838,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoVTable *vtable = (MonoVTable*)frame->imethod->data_items [ip [3]]; MonoClass *c = vtable->klass; + // FIXME push/pop LMF MonoObject* o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (c)); MONO_HANDLE_ASSIGN_RAW (tmp_handle, o); mono_value_copy_internal (mono_object_get_data (o), locals + ip [2], c); @@ -5767,6 +5852,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoVTable *vtable = (MonoVTable*)frame->imethod->data_items [ip [3]]; MonoClass *c = vtable->klass; + // FIXME push/pop LMF MonoObject* o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (c)); MONO_HANDLE_ASSIGN_RAW (tmp_handle, o); mono_value_copy_internal (mono_object_get_data (o), LOCAL_VAR (ip [2], gpointer), c); @@ -5779,16 +5865,18 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_BOX_NULLABLE_PTR) { MonoClass *c = (MonoClass*)frame->imethod->data_items [ip [3]]; + // FIXME push/pop LMF LOCAL_VAR (ip [1], MonoObject*) = mono_nullable_box (LOCAL_VAR (ip [2], gpointer), c, error); mono_interp_error_cleanup (error); /* FIXME: don't swallow the error */ ip += 4; MINT_IN_BREAK; } MINT_IN_CASE(MINT_NEWARR) { + // FIXME push/pop LMF MonoVTable *vtable = (MonoVTable*)frame->imethod->data_items [ip [3]]; LOCAL_VAR (ip [1], MonoObject*) = (MonoObject*) mono_array_new_specific_checked (vtable, LOCAL_VAR (ip [2], gint32), error); if (!is_ok (error)) { - THROW_EX (mono_error_convert_to_exception (error), ip); + THROW_EX (interp_error_convert_to_exception (frame, error, ip), ip); } ip += 4; /*if (profiling_classes) { @@ -5820,7 +5908,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (s); int i32 = LOCAL_VAR (ip [3], int); if (i32 < 0 || i32 >= mono_string_length_internal (s)) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = mono_string_chars_internal (s)[i32]; ip += 4; MINT_IN_BREAK; @@ -5834,7 +5922,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; const gint32 length = *(gint32 *) (span + offset_length); if (index < 0 || index >= length) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); gsize element_size = (gsize)(gint16)ip [4]; gsize offset_pointer = (gsize)(gint16)ip [6]; @@ -5860,6 +5948,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; } MINT_IN_CASE(MINT_ARRAY_ELEMENT_SIZE) { + // FIXME push/pop LMF MonoObject *o = LOCAL_VAR (ip [2], MonoObject*); NULL_CHECK (o); LOCAL_VAR (ip [1], gint32) = mono_array_element_size (mono_object_class (o)); @@ -5879,7 +5968,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (ao); gint32 index = LOCAL_VAR (ip [3], gint32); if (index >= ao->max_length) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); guint16 size = ip [4]; LOCAL_VAR (ip [1], gpointer) = mono_array_addr_with_size_fast (ao, size, index); ip += 5; @@ -5900,7 +5989,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 lower = ao->bounds [i].lower_bound; guint32 len = ao->bounds [i].length; if (idx < lower || (guint32)(idx - lower) >= len) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); pos = (pos * len) + (guint32)(idx - lower); } @@ -5909,6 +5998,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; } MINT_IN_CASE(MINT_LDELEMA_TC) { + // FIXME push/pop LMF stackval *sp = (stackval*)(locals + ip [2]); MonoObject *o = (MonoObject*) sp [0].data.o; @@ -5927,7 +6017,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (o); \ gint32 aindex = LOCAL_VAR (ip [3], gint32); \ if (aindex >= mono_array_length_internal (o)) \ - THROW_EX (mono_get_exception_index_out_of_range (), ip); \ + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); \ LOCAL_VAR (ip [1], datatype) = mono_array_get_fast (o, elemtype, aindex); \ ip += 4; \ } while (0) @@ -5947,7 +6037,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (o); mono_u aindex = LOCAL_VAR (ip [3], gint32); if (aindex >= mono_array_length_internal (o)) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); guint16 size = ip [4]; char *src_addr = mono_array_addr_with_size_fast ((MonoArray *) o, size, aindex); @@ -5961,7 +6051,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (o); \ aindex = LOCAL_VAR (ip [2], gint32); \ if (aindex >= mono_array_length_internal (o)) \ - THROW_EX (mono_get_exception_index_out_of_range (), ip); \ + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); \ } while (0) #define STELEM(datatype, elemtype) do { \ @@ -5987,9 +6077,10 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoObject *ref = LOCAL_VAR (ip [3], MonoObject*); if (ref) { + // FIXME push/pop LMF gboolean isinst = mono_interp_isinst (ref, m_class_get_element_class (mono_object_class (o))); if (!isinst) - THROW_EX (mono_get_exception_array_type_mismatch (), ip); + THROW_EX (interp_get_exception_array_type_mismatch (frame, ip), ip); } mono_array_setref_fast ((MonoArray *) o, aindex, ref); ip += 4; @@ -6001,7 +6092,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (o); gint32 aindex = LOCAL_VAR (ip [2], gint32); if (aindex >= mono_array_length_internal (o)) - THROW_EX (mono_get_exception_index_out_of_range (), ip); + THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); guint16 size = ip [5]; char *dst_addr = mono_array_addr_with_size_fast ((MonoArray *) o, size, aindex); @@ -6013,7 +6104,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I4_U4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6021,7 +6112,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I4_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < G_MININT32 || val > G_MAXINT32) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint32) val; ip += 3; MINT_IN_BREAK; @@ -6029,7 +6120,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I4_U8) { guint64 val = LOCAL_VAR (ip [2], guint64); if (val > G_MAXINT32) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint32) val; ip += 3; MINT_IN_BREAK; @@ -6040,7 +6131,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val_r8 > ((double)G_MININT32 - 1) && val_r8 < ((double)G_MAXINT32 + 1)) LOCAL_VAR (ip [1], gint32) = (gint32) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6049,14 +6140,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > ((double)G_MININT32 - 1) && val < ((double)G_MAXINT32 + 1)) LOCAL_VAR (ip [1], gint32) = (gint32) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U4_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6064,7 +6155,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U4_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0 || val > G_MAXUINT32) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (guint32) val; ip += 3; MINT_IN_BREAK; @@ -6075,7 +6166,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val_r8 > -1.0 && val_r8 < ((double)G_MAXUINT32 + 1)) LOCAL_VAR (ip [1], gint32) = (guint32)val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6084,14 +6175,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > -1.0 && val < ((double)G_MAXUINT32 + 1)) LOCAL_VAR (ip [1], gint32) = (guint32)val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I2_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < G_MININT16 || val > G_MAXINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint16)val; ip += 3; MINT_IN_BREAK; @@ -6099,7 +6190,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I2_U4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0 || val > G_MAXINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint16)val; ip += 3; MINT_IN_BREAK; @@ -6107,7 +6198,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I2_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < G_MININT16 || val > G_MAXINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint16) val; ip += 3; MINT_IN_BREAK; @@ -6115,7 +6206,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I2_U8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0 || val > G_MAXINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint16) val; ip += 3; MINT_IN_BREAK; @@ -6125,7 +6216,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > (G_MININT16 - 1) && val < (G_MAXINT16 + 1)) LOCAL_VAR (ip [1], gint32) = (gint16) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6134,14 +6225,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > (G_MININT16 - 1) && val < (G_MAXINT16 + 1)) LOCAL_VAR (ip [1], gint32) = (gint16) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U2_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0 || val > G_MAXUINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6149,7 +6240,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U2_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0 || val > G_MAXUINT16) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (guint16) val; ip += 3; MINT_IN_BREAK; @@ -6159,7 +6250,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > -1.0f && val < (G_MAXUINT16 + 1)) LOCAL_VAR (ip [1], gint32) = (guint16) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6168,14 +6259,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > -1.0 && val < (G_MAXUINT16 + 1)) LOCAL_VAR (ip [1], gint32) = (guint16) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I1_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < G_MININT8 || val > G_MAXINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6183,7 +6274,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I1_U4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0 || val > G_MAXINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6191,7 +6282,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I1_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < G_MININT8 || val > G_MAXINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint8) val; ip += 3; MINT_IN_BREAK; @@ -6199,7 +6290,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I1_U8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0 || val > G_MAXINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (gint8) val; ip += 3; MINT_IN_BREAK; @@ -6209,7 +6300,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > (G_MININT8 - 1) && val < (G_MAXINT8 + 1)) LOCAL_VAR (ip [1], gint32) = (gint8) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6218,14 +6309,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > (G_MININT8 - 1) && val < (G_MAXINT8 + 1)) LOCAL_VAR (ip [1], gint32) = (gint8) val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U1_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0 || val > G_MAXUINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = val; ip += 3; MINT_IN_BREAK; @@ -6233,7 +6324,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_U1_I8) { gint64 val = LOCAL_VAR (ip [2], gint64); if (val < 0 || val > G_MAXUINT8) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = (guint8) val; ip += 3; MINT_IN_BREAK; @@ -6243,7 +6334,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > -1.0f && val < (G_MAXUINT8 + 1)) LOCAL_VAR (ip [1], gint32) = (guint8)val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } @@ -6252,14 +6343,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; if (val > -1.0 && val < (G_MAXUINT8 + 1)) LOCAL_VAR (ip [1], gint32) = (guint8)val; else - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CKFINITE) { double val = LOCAL_VAR (ip [2], double); if (!mono_isfinite (val)) - THROW_EX (mono_get_exception_arithmetic (), ip); + THROW_EX (interp_get_exception_arithmetic (frame, ip), ip); LOCAL_VAR (ip [1], double) = val; ip += 3; MINT_IN_BREAK; @@ -6289,7 +6380,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoClass *c = (MonoClass*)frame->imethod->data_items [ip [3]]; if (c != tref->klass) - THROW_EX (mono_get_exception_invalid_cast (), ip); + THROW_EX (interp_get_exception_invalid_cast (frame, ip), ip); LOCAL_VAR (ip [1], gpointer) = tref->value; ip += 4; @@ -6304,7 +6395,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 i1 = LOCAL_VAR (ip [2], gint32); gint32 i2 = LOCAL_VAR (ip [3], gint32); if (CHECK_ADD_OVERFLOW (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = i1 + i2; ip += 4; MINT_IN_BREAK; @@ -6313,7 +6404,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint64 l1 = LOCAL_VAR (ip [2], gint64); gint64 l2 = LOCAL_VAR (ip [3], gint64); if (CHECK_ADD_OVERFLOW64 (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 + l2; ip += 4; MINT_IN_BREAK; @@ -6322,7 +6413,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint32 i1 = LOCAL_VAR (ip [2], guint32); guint32 i2 = LOCAL_VAR (ip [3], guint32); if (CHECK_ADD_OVERFLOW_UN (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint32) = i1 + i2; ip += 4; MINT_IN_BREAK; @@ -6331,7 +6422,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint64 l1 = LOCAL_VAR (ip [2], guint64); guint64 l2 = LOCAL_VAR (ip [3], guint64); if (CHECK_ADD_OVERFLOW64_UN (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = l1 + l2; ip += 4; MINT_IN_BREAK; @@ -6340,7 +6431,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 i1 = LOCAL_VAR (ip [2], gint32); gint32 i2 = LOCAL_VAR (ip [3], gint32); if (CHECK_MUL_OVERFLOW (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = i1 * i2; ip += 4; MINT_IN_BREAK; @@ -6349,7 +6440,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint64 l1 = LOCAL_VAR (ip [2], gint64); gint64 l2 = LOCAL_VAR (ip [3], gint64); if (CHECK_MUL_OVERFLOW64 (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 * l2; ip += 4; MINT_IN_BREAK; @@ -6358,7 +6449,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint32 i1 = LOCAL_VAR (ip [2], guint32); guint32 i2 = LOCAL_VAR (ip [3], guint32); if (CHECK_MUL_OVERFLOW_UN (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint32) = i1 * i2; ip += 4; MINT_IN_BREAK; @@ -6367,7 +6458,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint64 l1 = LOCAL_VAR (ip [2], guint64); guint64 l2 = LOCAL_VAR (ip [3], guint64); if (CHECK_MUL_OVERFLOW64_UN (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint64) = l1 * l2; ip += 4; MINT_IN_BREAK; @@ -6376,7 +6467,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint32 i1 = LOCAL_VAR (ip [2], gint32); gint32 i2 = LOCAL_VAR (ip [3], gint32); if (CHECK_SUB_OVERFLOW (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint32) = i1 - i2; ip += 4; MINT_IN_BREAK; @@ -6385,7 +6476,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gint64 l1 = LOCAL_VAR (ip [2], gint64); gint64 l2 = LOCAL_VAR (ip [3], gint64); if (CHECK_SUB_OVERFLOW64 (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 - l2; ip += 4; MINT_IN_BREAK; @@ -6394,7 +6485,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint32 i1 = LOCAL_VAR (ip [2], guint32); guint32 i2 = LOCAL_VAR (ip [3], guint32); if (CHECK_SUB_OVERFLOW_UN (i1, i2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], guint32) = i1 - i2; ip += 4; MINT_IN_BREAK; @@ -6403,7 +6494,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; guint64 l1 = LOCAL_VAR (ip [2], guint64); guint64 l2 = LOCAL_VAR (ip [3], guint64); if (CHECK_SUB_OVERFLOW64_UN (l1, l2)) - THROW_EX (mono_get_exception_overflow (), ip); + THROW_EX (interp_get_exception_overflow (frame, ip), ip); LOCAL_VAR (ip [1], gint64) = l1 - l2; ip += 4; MINT_IN_BREAK; @@ -6450,8 +6541,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; ip += short_offset ? (gint16)*(ip + 1) : (gint32)READ32 (ip + 1); MINT_IN_BREAK; } - MINT_IN_CASE(MINT_ICALL_V_V) - MINT_IN_CASE(MINT_ICALL_P_V) + MINT_IN_CASE(MINT_ICALL_V_V) + MINT_IN_CASE(MINT_ICALL_P_V) MINT_IN_CASE(MINT_ICALL_PP_V) MINT_IN_CASE(MINT_ICALL_PPP_V) MINT_IN_CASE(MINT_ICALL_PPPP_V) @@ -6476,17 +6567,19 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; CHECK_RESUME_STATE (context); ip += 4; MINT_IN_BREAK; - MINT_IN_CASE(MINT_MONO_LDPTR) + MINT_IN_CASE(MINT_MONO_LDPTR) LOCAL_VAR (ip [1], gpointer) = frame->imethod->data_items [ip [2]]; ip += 3; MINT_IN_BREAK; MINT_IN_CASE(MINT_MONO_NEWOBJ) + // FIXME push/pop LMF LOCAL_VAR (ip [1], MonoObject*) = mono_interp_new ((MonoClass*)frame->imethod->data_items [ip [2]]); // FIXME: do not swallow the error ip += 3; MINT_IN_BREAK; MINT_IN_CASE(MINT_MONO_RETOBJ) + // FIXME push/pop LMF stackval_from_data (mono_method_signature_internal (frame->imethod->method)->ret, frame->stack, LOCAL_VAR (ip [1], gpointer), - mono_method_signature_internal (frame->imethod->method)->pinvoke); + mono_method_signature_internal (frame->imethod->method)->pinvoke && !mono_method_signature_internal (frame->imethod->method)->marshalling_disabled); frame_data_allocator_pop (&context->data_stack, frame); goto exit_frame; MINT_IN_CASE(MINT_MONO_SGEN_THREAD_INFO) @@ -6532,6 +6625,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; static T ss_tramp; if (!ss_tramp) { + // FIXME push/pop LMF void *tramp = mini_get_single_step_trampoline (); mono_memory_barrier (); ss_tramp = (T)tramp; @@ -6563,6 +6657,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; typedef void (*T) (void); static T bp_tramp; if (!bp_tramp) { + // FIXME push/pop LMF void *tramp = mini_get_breakpoint_trampoline (); mono_memory_barrier (); bp_tramp = (T)tramp; @@ -6724,6 +6819,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDFTN) { InterpMethod *m = (InterpMethod*)frame->imethod->data_items [ip [2]]; + // FIXME push/pop LMF LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m, FALSE); ip += 3; MINT_IN_BREAK; @@ -6733,6 +6829,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoObject *o = LOCAL_VAR (ip [2], MonoObject*); NULL_CHECK (o); + // FIXME push/pop LMF InterpMethod *res_method = get_virtual_method (virtual_method, o->vtable); gboolean need_unbox = m_class_is_valuetype (res_method->method->klass) && !m_class_is_valuetype (virtual_method->method->klass); LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (res_method, need_unbox); @@ -6744,6 +6841,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoMethod *cmethod = LOCAL_VAR (ip [2], MonoMethod*); + // FIXME push/pop LMF if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (cmethod))) { cmethod = mono_marshal_get_managed_wrapper (cmethod, NULL, (MonoGCHandle)0, error); mono_error_assert_ok (error); @@ -6766,6 +6864,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoProfilerCallContext *prof_ctx = g_new0 (MonoProfilerCallContext, 1); prof_ctx->interp_frame = frame; prof_ctx->method = frame->imethod->method; + // FIXME push/pop LMF if (flag & TRACING_FLAG) mono_trace_enter_method (frame->imethod->method, frame->imethod->jinfo, prof_ctx); if (flag & PROFILING_FLAG) @@ -6797,6 +6896,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; prof_ctx->method = frame->imethod->method; if (!is_void) prof_ctx->return_value = frame->retval; + // FIXME push/pop LMF if (flag & TRACING_FLAG) mono_trace_leave_method (frame->imethod->method, frame->imethod->jinfo, prof_ctx); if (flag & PROFILING_FLAG) @@ -6891,7 +6991,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; gpointer src = LOCAL_VAR (ip [2], gpointer); guint32 size = LOCAL_VAR (ip [3], guint32); if (size && (!dest || !src)) - THROW_EX (mono_get_exception_null_reference(), ip); + THROW_EX (interp_get_exception_null_reference(frame, ip), ip); else memcpy (dest, src, size); ip += 4; @@ -6912,22 +7012,23 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; } MINT_IN_CASE(MINT_MONO_RETHROW) { - /* + /* * need to clarify what this should actually do: * * Takes an exception from the stack and rethrows it. * This is useful for wrappers that don't want to have to - * use CEE_THROW and lose the exception stacktrace. + * use CEE_THROW and lose the exception stacktrace. */ MonoException *exc = LOCAL_VAR (ip [1], MonoException*); if (!exc) - exc = mono_get_exception_null_reference (); + exc = interp_get_exception_null_reference (frame, ip); THROW_EX_GENERAL (exc, ip, TRUE); MINT_IN_BREAK; } MINT_IN_CASE(MINT_LD_DELEGATE_METHOD_PTR) { + // FIXME push/pop LMF MonoDelegate *del = LOCAL_VAR (ip [2], MonoDelegate*); if (!del->interp_method) { /* Not created from interpreted code */ @@ -6950,7 +7051,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; LOCAL_VAR (ip [1], double) = mathfunc (LOCAL_VAR (ip [2], double), LOCAL_VAR (ip [3], double)); \ ip += 4; - MINT_IN_CASE(MINT_ABS) MATH_UNOP(fabs); MINT_IN_BREAK; MINT_IN_CASE(MINT_ASIN) MATH_UNOP(asin); MINT_IN_BREAK; MINT_IN_CASE(MINT_ASINH) MATH_UNOP(asinh); MINT_IN_BREAK; MINT_IN_CASE(MINT_ACOS) MATH_UNOP(acos); MINT_IN_BREAK; @@ -6990,7 +7090,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; #define MATH_BINOPF(mathfunc) \ LOCAL_VAR (ip [1], float) = mathfunc (LOCAL_VAR (ip [2], float), LOCAL_VAR (ip [3], float)); \ ip += 4; - MINT_IN_CASE(MINT_ABSF) MATH_UNOPF(fabsf); MINT_IN_BREAK; MINT_IN_CASE(MINT_ASINF) MATH_UNOPF(asinf); MINT_IN_BREAK; MINT_IN_CASE(MINT_ASINHF) MATH_UNOPF(asinhf); MINT_IN_BREAK; MINT_IN_CASE(MINT_ACOSF) MATH_UNOPF(acosf); MINT_IN_BREAK; @@ -7712,16 +7811,6 @@ metadata_update_prepare_to_invalidate (void) if (!info || !info->jit_data) continue; - ThreadContext *context = (ThreadContext*)info->jit_data->interp_context; - - /* If the thread was in the interpreter and hit a safepoint - * opcode and suspended, backup the frames since the last lmf. - */ - if (context && context->safepoint_frame) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "threadinfo=%p, has safepoint frame %p", info, context->safepoint_frame); - metadata_update_backup_frames (info, context->safepoint_frame); - } - MonoLMF *lmf = info->jit_data->lmf; while (lmf) { if (((gsize) lmf->previous_lmf) & 2) { diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 52b2c4bb1522c..59f909b24b365 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -708,7 +708,6 @@ OPDEF(MINT_LD_DELEGATE_METHOD_PTR, "ld_delegate_method_ptr", 3, 1, 1, MintOpNoAr // Math intrinsics // double -OPDEF(MINT_ABS, "abs", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ASIN, "asin", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ASINH, "asinh", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ACOS, "acos", 3, 1, 1, MintOpNoArgs) @@ -735,7 +734,6 @@ OPDEF(MINT_TAN, "tan", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_TANH, "tanh", 3, 1, 1, MintOpNoArgs) // float. These must be kept in the same order as their double counterpart -OPDEF(MINT_ABSF, "absf", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ASINF, "asinf", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ASINHF, "asinhf", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_ACOSF, "acosf", 3, 1, 1, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 8679774a33876..ba5075abd8166 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -778,7 +778,7 @@ init_bb_stack_state (TransformData *td, InterpBasicBlock *bb) } } -static void +static void handle_branch (TransformData *td, int long_op, int offset) { int target = td->ip + offset - td->il_code; @@ -806,7 +806,7 @@ handle_branch (TransformData *td, int long_op, int offset) td->last_ins->info.target_bb = target_bb; } -static void +static void one_arg_branch(TransformData *td, int mint_op, int offset, int inst_size) { int type = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type; @@ -835,7 +835,7 @@ interp_add_conv (TransformData *td, StackInfo *sp, InterpInst *prev_ins, int typ interp_ins_set_dreg (new_inst, sp->local); } -static void +static void two_arg_branch(TransformData *td, int mint_op, int offset, int inst_size) { int type1 = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type; @@ -854,7 +854,7 @@ two_arg_branch(TransformData *td, int mint_op, int offset, int inst_size) } else if (type1 == STACK_TYPE_R8 && type2 == STACK_TYPE_R4) { interp_add_conv (td, td->sp - 2, td->last_ins, STACK_TYPE_R8, MINT_CONV_R8_R4); } else if (type1 != type2) { - g_warning("%s.%s: branch type mismatch %d %d", + g_warning("%s.%s: branch type mismatch %d %d", m_class_get_name (td->method->klass), td->method->name, td->sp [-1].type, td->sp [-2].type); } @@ -910,7 +910,7 @@ binary_arith_op(TransformData *td, int mint_op) if (type2 == STACK_TYPE_MP) type2 = STACK_TYPE_I; if (type1 != type2) { - g_warning("%s.%s: %04x arith type mismatch %s %d %d", + g_warning("%s.%s: %04x arith type mismatch %s %d %d", m_class_get_name (td->method->klass), td->method->name, td->ip - td->il_code, mono_interp_opname (mint_op), type1, type2); } @@ -929,7 +929,7 @@ shift_op(TransformData *td, int mint_op) int op = mint_op + td->sp [-2].type - STACK_TYPE_I4; CHECK_STACK(td, 2); if (td->sp [-1].type != STACK_TYPE_I4) { - g_warning("%s.%s: shift type mismatch %d", + g_warning("%s.%s: shift type mismatch %d", m_class_get_name (td->method->klass), td->method->name, td->sp [-2].type); } @@ -940,7 +940,7 @@ shift_op(TransformData *td, int mint_op) interp_ins_set_dreg (td->last_ins, td->sp [-1].local); } -static int +static int can_store (int st_value, int vt_value) { if (st_value == STACK_TYPE_O || st_value == STACK_TYPE_MP) @@ -967,7 +967,7 @@ get_arg_type_exact (TransformData *td, int n, int *mt) return type; } -static void +static void load_arg(TransformData *td, int n) { gint32 size = 0; @@ -980,7 +980,7 @@ load_arg(TransformData *td, int n) if (mt == MINT_TYPE_VT) { klass = mono_class_from_mono_type_internal (type); - if (mono_method_signature_internal (td->method)->pinvoke) + if (mono_method_signature_internal (td->method)->pinvoke && !mono_method_signature_internal (td->method)->marshalling_disabled) size = mono_class_native_size (klass, NULL); else size = mono_class_value_size (klass, NULL); @@ -1006,12 +1006,12 @@ load_arg(TransformData *td, int n) } interp_add_ins (td, get_mov_for_type (mt, TRUE)); interp_ins_set_sreg (td->last_ins, n); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); if (mt == MINT_TYPE_VT) td->last_ins->data [0] = size; } -static void +static void store_arg(TransformData *td, int n) { gint32 size = 0; @@ -1023,7 +1023,7 @@ store_arg(TransformData *td, int n) if (mt == MINT_TYPE_VT) { MonoClass *klass = mono_class_from_mono_type_internal (type); - if (mono_method_signature_internal (td->method)->pinvoke) + if (mono_method_signature_internal (td->method)->pinvoke && !mono_method_signature_internal (td->method)->marshalling_disabled) size = mono_class_native_size (klass, NULL); else size = mono_class_value_size (klass, NULL); @@ -1060,7 +1060,7 @@ load_local (TransformData *td, int local) td->last_ins->data [0] = size; } -static void +static void store_local (TransformData *td, int local) { int mt = td->locals [local].mt; @@ -1070,7 +1070,7 @@ store_local (TransformData *td, int local) interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_I8, MINT_CONV_I8_I4); #endif if (!can_store(td->sp [-1].type, stack_type [mt])) { - g_warning("%s.%s: Store local stack type mismatch %d %d", + g_warning("%s.%s: Store local stack type mismatch %d %d", m_class_get_name (td->method->klass), td->method->name, stack_type [mt], td->sp [-1].type); } @@ -2180,9 +2180,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas if (csignature->param_count == 1 && csignature->params [0]->type == param_type) { // unops if (tm [0] == 'A') { - if (strcmp (tm, "Abs") == 0) { - *op = MINT_ABS; - } else if (strcmp (tm, "Asin") == 0){ + if (strcmp (tm, "Asin") == 0){ *op = MINT_ASIN; } else if (strcmp (tm, "Asinh") == 0){ *op = MINT_ASINH; @@ -2245,7 +2243,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } if (*op != -1 && is_float) { - *op = *op + (MINT_ABSF - MINT_ABS); + *op = *op + (MINT_ASINF - MINT_ASIN); } } else if (in_corlib && !strcmp (klass_name_space, "System") && (!strcmp (klass_name, "Span`1") || !strcmp (klass_name, "ReadOnlySpan`1"))) { if (!strcmp (tm, "get_Item")) { @@ -2830,7 +2828,7 @@ interp_inline_method (TransformData *td, MonoMethod *target_method, MonoMethodHe gboolean ret; unsigned int prev_max_stack_height, prev_locals_size; int prev_n_data_items; - int i; + int i; int prev_sp_offset; int prev_aggressive_inlining; MonoGenericContext *generic_context = NULL; @@ -3293,7 +3291,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target CHECK_STACK (td, csignature->param_count + csignature->hasthis); if (tailcall && !td->gen_sdb_seq_points && !calli && op == -1 && - (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && + (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0 && !(target_method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING)) { (void)mono_class_vtable_checked (target_method->klass, error); @@ -3332,7 +3330,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target int in_offset = td->ip - td->il_code; if (interp_ip_in_cbb (td, in_offset + 5)) - ++td->ip; /* gobble the CEE_RET if it isn't branched to */ + ++td->ip; /* gobble the CEE_RET if it isn't branched to */ td->ip += 5; return TRUE; } @@ -3397,7 +3395,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target MonoClass *klass = mono_class_from_mono_type_internal (csignature->ret); if (mt == MINT_TYPE_VT) { - if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE) + if (csignature->pinvoke && !csignature->marshalling_disabled && method->wrapper_type != MONO_WRAPPER_NONE) res_size = mono_class_native_size (klass, NULL); else res_size = mono_class_value_size (klass, NULL); @@ -3438,7 +3436,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target else g_error ("Unsupported opcode"); } - + if (op == MINT_LDLEN) { #ifdef MONO_BIG_ARRAYS SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_I8); @@ -4658,7 +4656,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, } switch (*td->ip) { - case CEE_NOP: + case CEE_NOP: /* lose it */ emitted_funccall_seq_point = FALSE; ++td->ip; @@ -4828,7 +4826,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, interp_ins_set_dreg (td->last_ins, td->sp [-1].local); ++td->ip; break; - case CEE_LDC_I4_S: + case CEE_LDC_I4_S: interp_add_ins (td, MINT_LDC_I4_S); td->last_ins->data [0] = ((gint8 *) td->ip) [1]; push_simple_type (td, STACK_TYPE_I4); @@ -4933,7 +4931,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, last_seq_point->flags |= INTERP_INST_FLAG_SEQ_POINT_NESTED_CALL; } else - emitted_funccall_seq_point = TRUE; + emitted_funccall_seq_point = TRUE; } last_seq_point = interp_add_ins (td, MINT_SDB_SEQ_POINT); // This seq point is actually associated with the instruction following the call @@ -5397,7 +5395,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, } ++td->ip; break; - case CEE_CONV_I: + case CEE_CONV_I: CHECK_STACK (td, 1); switch (td->sp [-1].type) { case STACK_TYPE_R8: @@ -5871,7 +5869,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, case CEE_UNBOX: CHECK_STACK (td, 1); token = read32 (td->ip + 1); - + if (method->wrapper_type != MONO_WRAPPER_NONE) klass = (MonoClass *)mono_method_get_wrapper_data (method, token); else { @@ -6948,7 +6946,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, interp_add_ins (td, MINT_LD_DELEGATE_METHOD_PTR); interp_ins_set_sreg (td->last_ins, td->sp [0].local); push_simple_type (td, STACK_TYPE_I); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); break; case CEE_MONO_CALLI_EXTRA_ARG: { int saved_local = td->sp [-1].local; @@ -7016,7 +7014,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, int size; CHECK_STACK (td, 1); MonoClass *klass = td->sp [-1].klass; - if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && !signature->marshalling_disabled) size = mono_class_native_size (klass, NULL); else size = mono_class_value_size (klass, NULL); @@ -7081,7 +7079,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, td->sp--; interp_ins_set_sreg (td->last_ins, td->sp [0].local); klass = (MonoClass *)mono_method_get_wrapper_data (method, token); - + /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/ if (td->sp > td->stack) @@ -7184,7 +7182,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, * to take into account the number of prefix bytes (usually the * throw point is just (ip - n_prefix_bytes). */ - case CEE_PREFIX1: + case CEE_PREFIX1: ++td->ip; switch (*td->ip) { case CEE_ARGLIST: @@ -7333,7 +7331,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, td->ip += 5; break; } - + int index = get_data_item_index (td, mono_interp_get_imethod (m, error)); goto_if_nok (error, exit); if (*td->ip == CEE_LDVIRTFTN) { @@ -7426,7 +7424,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, #if SIZEOF_VOID_P == 8 if (td->sp [-1].type == STACK_TYPE_I8) interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_I4, MINT_MOV_8); -#endif +#endif interp_add_ins (td, MINT_LOCALLOC); if (td->sp != td->stack + 1) g_warning("CEE_LOCALLOC: stack not empty"); @@ -7542,7 +7540,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, THROW_EX (mono_exception_from_name (mono_defaults.corlib, "System", "InvalidProgramException"), ip - 5); #endif size = mono_type_size (m_class_get_byval_arg (szclass), &align); - } + } interp_add_ins (td, MINT_LDC_I4); WRITE32_INS (td->last_ins, 0, &size); push_simple_type (td, STACK_TYPE_I4); @@ -9133,7 +9131,7 @@ static void initialize_global_var_cb (TransformData *td, int var, gpointer data) { initialize_global_var (td, var, (int)(gsize)data); -} +} static void initialize_global_vars (TransformData *td) @@ -9552,7 +9550,7 @@ interp_fix_localloc_ret (TransformData *td) g_assert (td->has_localloc); for (InterpBasicBlock *bb = td->entry_bb; bb != NULL; bb = bb->next_bb) { InterpInst *ins = bb->first_ins; - while (ins) { + while (ins) { if (ins->opcode >= MINT_RET && ins->opcode <= MINT_RET_VT) ins->opcode += MINT_RET_LOCALLOC - MINT_RET; ins = ins->next; @@ -9806,7 +9804,7 @@ tiered_patcher (MiniTieredPatchPointContext *ctx, gpointer patchsite) #endif -void +void mono_interp_transform_init (void) { mono_os_mutex_init_recursive(&calc_section); diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 4e30c67c85dd8..4f6a63b0480e4 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -217,7 +217,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign if (fsig->param_count == 2 && fsig->params [0]->type == MONO_TYPE_R8 && fsig->params [1]->type == MONO_TYPE_R8) { // Max and Min can only be optimized in fast math mode if (!strcmp (cmethod->name, "Max") && mono_use_fast_math) { - opcode = OP_FMAX; + opcode = OP_FMAX; } else if (!strcmp (cmethod->name, "Min") && mono_use_fast_math) { opcode = OP_FMIN; } else if (!strcmp (cmethod->name, "Pow")) { @@ -243,7 +243,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign // (float, float) if (fsig->param_count == 2 && fsig->params [0]->type == MONO_TYPE_R4 && fsig->params [1]->type == MONO_TYPE_R4) { if (!strcmp (cmethod->name, "Max") && mono_use_fast_math) { - opcode = OP_RMAX; + opcode = OP_RMAX; } else if (!strcmp (cmethod->name, "Min") && mono_use_fast_math) { opcode = OP_RMIN; } else if (!strcmp (cmethod->name, "Pow")) { @@ -509,7 +509,7 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu g_assert (ctx->method_inst->type_argc == 1); g_assert (fsig->param_count == 2); - if (fsig->params [1]->type == MONO_TYPE_I) { + if (fsig->params [1]->type == MONO_TYPE_I || fsig->params [1]->type == MONO_TYPE_U) { int dreg = alloc_preg (cfg); EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, args [0]->dreg, args [1]->dreg); ins->type = STACK_PTR; @@ -583,6 +583,23 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu MONO_INST_NEW (cfg, ins, OP_NOP); MONO_ADD_INS (cfg->cbb, ins); return ins; + } else if (!strcmp (cmethod->name, "IsNullRef")) { + g_assert (fsig->param_count == 1); + + MONO_EMIT_NEW_COMPARE_IMM (cfg, args [0]->dreg, 0); + int dreg = alloc_ireg (cfg); + EMIT_NEW_UNALU (cfg, ins, OP_PCEQ, dreg, -1); + return ins; + } else if (!strcmp (cmethod->name, "NullRef")) { + g_assert (ctx); + g_assert (ctx->method_inst); + g_assert (ctx->method_inst->type_argc == 1); + g_assert (fsig->param_count == 0); + + EMIT_NEW_PCONST (cfg, ins, NULL); + ins->type = STACK_MP; + ins->klass = mono_class_from_mono_type_internal (fsig->ret); + return ins; } return NULL; @@ -772,19 +789,19 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } #else index_reg = args [1]->dreg; -#endif +#endif MONO_EMIT_BOUNDS_CHECK (cfg, args [0]->dreg, MonoString, length, index_reg); #if defined(TARGET_X86) || defined(TARGET_AMD64) EMIT_NEW_X86_LEA (cfg, ins, args [0]->dreg, index_reg, 1, MONO_STRUCT_OFFSET (MonoString, chars)); add_reg = ins->dreg; - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, add_reg, 0); #else int mult_reg = alloc_preg (cfg); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, mult_reg, index_reg, 1); MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, mult_reg, args [0]->dreg); - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, add_reg, MONO_STRUCT_OFFSET (MonoString, chars)); #endif mini_type_from_op (cfg, ins, NULL, NULL); @@ -799,7 +816,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE; return ins; - } else + } else return NULL; } else if (cmethod->klass == mono_defaults.object_class) { if (strcmp (cmethod->name, "GetType") == 0 && fsig->param_count + fsig->hasthis == 1) { @@ -816,7 +833,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else if (!cfg->backend->emulate_mul_div && strcmp (cmethod->name, "InternalGetHashCode") == 0 && fsig->param_count == 1 && !mono_gc_is_moving ()) { int dreg = alloc_ireg (cfg); int t1 = alloc_ireg (cfg); - + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, t1, args [0]->dreg, 3); EMIT_NEW_BIALU_IMM (cfg, ins, OP_MUL_IMM, dreg, t1, 2654435761u); ins->type = STACK_I4; @@ -891,7 +908,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign EMIT_NEW_UNALU (cfg, ins, OP_MOVE, dreg, dreg); ins->type = STACK_I4; - + return ins; } #endif @@ -902,7 +919,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign if (strcmp (cmethod->name, "get_Rank") == 0 && fsig->param_count + fsig->hasthis == 1) { int dreg = alloc_ireg (cfg); int vtable_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOAD_MEMBASE, vtable_reg, + MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOAD_MEMBASE, vtable_reg, args [0]->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable)); EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU1_MEMBASE, dreg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank)); @@ -912,7 +929,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else if (strcmp (cmethod->name, "get_Length") == 0 && fsig->param_count + fsig->hasthis == 1) { int dreg = alloc_ireg (cfg); - EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, ins, OP_LOADI4_MEMBASE, dreg, + EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, ins, OP_LOADI4_MEMBASE, dreg, args [0]->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length)); mini_type_from_op (cfg, ins, NULL, NULL); @@ -1722,8 +1739,8 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return ins; } } else if (cmethod->klass == mono_class_try_get_math_class ()) { - /* - * There is general branchless code for Min/Max, but it does not work for + /* + * There is general branchless code for Min/Max, but it does not work for * all inputs: * http://everything2.com/?node_id=1051618 */ @@ -1738,7 +1755,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign int opcode = 0; const char *mname = cmethod->name; char c = mname [0]; - + if (c == 'A'){ if (strcmp (mname, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8) { opcode = OP_ABS; @@ -1758,7 +1775,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else if (strcmp (mname, "Atanh") == 0){ if (fabs (source) < 1) opcode = OP_ATANH; - } + } } else if (c == 'C'){ if (strcmp (mname, "Cos") == 0) { if (!isinf (source)) @@ -1797,7 +1814,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->type = STACK_R8; ins->dreg = mono_alloc_dreg (cfg, (MonoStackType) ins->type); ins->inst_p0 = dest; - + switch (opcode){ case OP_ABS: result = fabs (source); @@ -1924,7 +1941,11 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else if (((!strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.iOS") || !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.TVOS") || !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.MacCatalyst") || - !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.Mac")) && + !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.Mac") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.iOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.tvOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.MacCatalyst") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.macOS")) && !strcmp (cmethod_klass_name_space, "ObjCRuntime") && !strcmp (cmethod_klass_name, "Selector")) ) { @@ -2040,10 +2061,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } } - // Return false for IsSupported for all types in System.Runtime.Intrinsics.* + // Return false for IsSupported for all types in System.Runtime.Intrinsics.* // if it's not handled in mono_emit_simd_intrinsics - if (in_corlib && - !strncmp ("System.Runtime.Intrinsics", cmethod_klass_name_space, 25) && + if (in_corlib && + !strncmp ("System.Runtime.Intrinsics", cmethod_klass_name_space, 25) && !strcmp (cmethod->name, "get_IsSupported")) { EMIT_NEW_ICONST (cfg, ins, 0); ins->type = STACK_I4; @@ -2143,7 +2164,7 @@ static MonoInst* emit_array_unsafe_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set) { MonoClass *eklass; - + if (is_set) eklass = mono_class_from_mono_type_internal (fsig->params [2]); else diff --git a/src/mono/mono/mini/ir-emit.h b/src/mono/mono/mini/ir-emit.h index 6177261f3507f..a36efe38fbb43 100644 --- a/src/mono/mono/mini/ir-emit.h +++ b/src/mono/mono/mini/ir-emit.h @@ -113,9 +113,9 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type) * Macros used to generate intermediate representation macros * * The macros use a `MonoConfig` object as its context, and among other - * things it is used to associate instructions with the memory pool with + * things it is used to associate instructions with the memory pool with * it. - * + * * The macros come in three variations with slightly different * features, the patter is: NEW_OP, EMIT_NEW_OP, MONO_EMIT_NEW_OP, * the differences are as follows: @@ -131,25 +131,25 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type) * * `MONO_EMIT_NEW_OP`: These variations of the instructions are used when * you are merely interested in emitting the instruction into the `MonoConfig` - * parameter. + * parameter. */ #undef MONO_INST_NEW -/* - * FIXME: zeroing out some fields is not needed with the new IR, but the old +/* + * FIXME: zeroing out some fields is not needed with the new IR, but the old * JIT code still uses the left and right fields, so it has to stay. */ /* * MONO_INST_NEW: create a new MonoInst instance that is allocated on the MonoConfig pool. * - * @cfg: the MonoConfig object that will be used as the context for the + * @cfg: the MonoConfig object that will be used as the context for the * instruction. * @dest: this is the place where the instance of the `MonoInst` is stored. * @op: the value that should be stored in the MonoInst.opcode field * * This initializes an empty MonoInst that has been nulled out, it is allocated * from the memory pool associated with the MonoConfig, but it is not linked anywhere. - * the cil_code is set to the cfg->ip address. + * the cil_code is set to the cfg->ip address. */ #define MONO_INST_NEW(cfg,dest,op) do { \ (dest) = (MonoInst *)mono_mempool_alloc ((cfg)->mempool, sizeof (MonoInst)); \ @@ -173,8 +173,8 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type) (dest)->dreg = alloc_dreg ((cfg), STACK_I4); \ } while (0) -/* - * Avoid using this with a non-NULL val if possible as it is not AOT +/* + * Avoid using this with a non-NULL val if possible as it is not AOT * compatible. Use one of the NEW_xxxCONST variants instead. */ #define NEW_PCONST(cfg,dest,val) do { \ @@ -217,7 +217,7 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type) MONO_INST_NEW ((cfg), (dest), (op)); \ (dest)->dreg = dr; \ (dest)->sreg1 = sr1; \ - } while (0) + } while (0) #define NEW_BIALU(cfg,dest,op,dr,sr1,sr2) do { \ MONO_INST_NEW ((cfg), (dest), (op)); \ diff --git a/src/mono/mono/mini/jit.h b/src/mono/mono/mini/jit.h index 7f7e46403efee..c3413106b1ccd 100644 --- a/src/mono/mono/mini/jit.h +++ b/src/mono/mono/mini/jit.h @@ -13,19 +13,19 @@ MONO_BEGIN_DECLS -MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain * +MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain * mono_jit_init (const char *file); -MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain * +MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain * mono_jit_init_version (const char *root_domain_name, const char *runtime_version); -MONO_API MonoDomain * +MONO_API MonoDomain * mono_jit_init_version_for_test_only (const char *root_domain_name, const char *runtime_version); MONO_API int -mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, +mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]); -MONO_API void +MONO_API void mono_jit_cleanup (MonoDomain *domain); MONO_API mono_bool diff --git a/src/mono/mono/mini/liveness.c b/src/mono/mono/mini/liveness.c index 81416eb3115ca..866f10be6889f 100644 --- a/src/mono/mono/mini/liveness.c +++ b/src/mono/mono/mini/liveness.c @@ -25,7 +25,7 @@ #define BB_ID_SHIFT 18 -/* +/* * The liveness2 pass can't handle long vars on 32 bit platforms because the component * vars have the same 'idx'. */ @@ -100,7 +100,7 @@ static void optimize_initlocals (MonoCompile *cfg); /* mono_bitset_mp_new: - * + * * allocates a MonoBitSet inside a memory pool */ static MonoBitSet* @@ -156,7 +156,7 @@ visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, MonoPtrSet *visited) /* DREG */ regtype = spec [MONO_INST_DEST]; g_assert (((ins->dreg == -1) && (regtype == ' ')) || ((ins->dreg != -1) && (regtype != ' '))); - + if ((ins->dreg != -1) && get_vreg_to_inst (cfg, ins->dreg)) { MonoInst *var = get_vreg_to_inst (cfg, ins->dreg); int idx = var->inst_c0; @@ -169,7 +169,7 @@ visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, MonoPtrSet *visited) get_vreg_to_inst (cfg, MONO_LVREG_MS (var->dreg))->flags |= MONO_INST_VOLATILE; } } - + /* SREGS */ num_sregs = mono_inst_get_src_registers (ins, sregs); for (srcindex = 0; srcindex < num_sregs; ++srcindex) { @@ -193,7 +193,7 @@ visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, MonoPtrSet *visited) mono_ptrset_add (visited, bb); - /* + /* * Need to visit all bblocks reachable from this one since they can be * reached during exception handling. */ @@ -211,7 +211,7 @@ mono_liveness_handle_exception_clauses (MonoCompile *cfg) int i, j; gboolean *outer_try; - /* + /* * Determine which clauses are outer try clauses, i.e. they are not contained in any * other non-try clause. */ @@ -283,7 +283,7 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) int sreg, inst_num; MonoMethodVar *vars = cfg->vars; guint32 abs_pos = (bb->dfn << BB_ID_SHIFT); - + /* Start inst_num from > 0, so last_use.abs_pos is only 0 for dead variables */ for (inst_num = 2, ins = bb->code; ins; ins = ins->next, inst_num += 2) { const char *spec = INS_INFO (ins->opcode); @@ -308,11 +308,11 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) if (cfg->verbose_level > 1) printf ("\tGEN: R%d(%d)\n", var->dreg, idx); #endif - update_live_range (&vars [idx], abs_pos + inst_num); + update_live_range (&vars [idx], abs_pos + inst_num); if (!mono_bitset_test_fast (bb->kill_set, idx)) mono_bitset_set_fast (bb->gen_set, idx); vi->spill_costs += SPILL_COST_INCREMENT; - } + } /* SREGs must come first, so MOVE r <- r is handled correctly */ num_sregs = mono_inst_get_src_registers (ins, sregs); @@ -327,7 +327,7 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) if (cfg->verbose_level > 1) printf ("\tGEN: R%d(%d)\n", sreg, idx); #endif - update_live_range (&vars [idx], abs_pos + inst_num); + update_live_range (&vars [idx], abs_pos + inst_num); if (!mono_bitset_test_fast (bb->kill_set, idx)) mono_bitset_set_fast (bb->gen_set, idx); vi->spill_costs += SPILL_COST_INCREMENT; @@ -341,7 +341,7 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) MonoMethodVar *vi = MONO_VARINFO (cfg, idx); if (MONO_IS_STORE_MEMBASE (ins)) { - update_live_range (&vars [idx], abs_pos + inst_num); + update_live_range (&vars [idx], abs_pos + inst_num); if (!mono_bitset_test_fast (bb->kill_set, idx)) mono_bitset_set_fast (bb->gen_set, idx); vi->spill_costs += SPILL_COST_INCREMENT; @@ -350,7 +350,7 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) if (cfg->verbose_level > 1) printf ("\tKILL: R%d(%d)\n", ins->dreg, idx); #endif - update_live_range (&vars [idx], abs_pos + inst_num + 1); + update_live_range (&vars [idx], abs_pos + inst_num + 1); mono_bitset_set_fast (bb->kill_set, idx); vi->spill_costs += SPILL_COST_INCREMENT; } @@ -358,7 +358,7 @@ analyze_liveness_bb (MonoCompile *cfg, MonoBasicBlock *bb) } } -/* generic liveness analysis code. CFG specific parts are +/* generic liveness analysis code. CFG specific parts are * in update_gen_kill_set() */ void @@ -380,7 +380,7 @@ mono_analyze_liveness (MonoCompile *cfg) g_assert (!(cfg->comp_done & MONO_COMP_LIVENESS)); cfg->comp_done |= MONO_COMP_LIVENESS; - + if (max_vars == 0) return; @@ -401,9 +401,9 @@ mono_analyze_liveness (MonoCompile *cfg) #ifdef DEBUG_LIVENESS if (cfg->verbose_level > 1) { printf ("BLOCK BB%d (", bb->block_num); - for (j = 0; j < bb->out_count; j++) + for (j = 0; j < bb->out_count; j++) printf ("BB%d, ", bb->out_bb [j]->block_num); - + printf ("):\n"); } #endif @@ -454,10 +454,10 @@ mono_analyze_liveness (MonoCompile *cfg) #ifdef DEBUG_LIVENESS if (cfg->verbose_level > 1) { printf ("P: BB%d(%d): IN: ", bb->block_num, bb->dfn); - for (j = 0; j < bb->in_count; ++j) + for (j = 0; j < bb->in_count; ++j) printf ("BB%d ", bb->in_bb [j]->block_num); printf ("OUT:"); - for (j = 0; j < bb->out_count; ++j) + for (j = 0; j < bb->out_count; ++j) printf ("BB%d ", bb->out_bb [j]->block_num); printf ("\n"); } @@ -477,7 +477,7 @@ mono_analyze_liveness (MonoCompile *cfg) changed = FALSE; mono_bitset_copyto_fast (bb->live_out_set, old_live_out_set); } - + for (j = 0; j < bb->out_count; j++) { out_bb = bb->out_bb [j]; @@ -495,7 +495,7 @@ mono_analyze_liveness (MonoCompile *cfg) mono_bitset_union_fast (bb->live_out_set, out_bb->live_in_set); } } - + if (changed || !mono_bitset_equal (old_live_out_set, bb->live_out_set)) { if (!bb->live_in_set) bb->live_in_set = mono_bitset_mp_new_noinit (cfg->mempool, bitsize, max_vars); @@ -505,8 +505,8 @@ mono_analyze_liveness (MonoCompile *cfg) for (j = 0; j < bb->in_count; j++) { MonoBasicBlock *in_bb = bb->in_bb [j]; - /* - * Some basic blocks do not seem to be in the + /* + * Some basic blocks do not seem to be in the * cfg->bblocks array... */ if (in_bb->gen_set && !in_worklist [in_bb->dfn]) { @@ -525,9 +525,9 @@ mono_analyze_liveness (MonoCompile *cfg) } if (G_UNLIKELY (cfg->verbose_level > 1)) { - printf ("\tLIVE IN BB%d: ", bb->block_num); - mono_bitset_print (bb->live_in_set); - } + printf ("\tLIVE IN BB%d: ", bb->block_num); + mono_bitset_print (bb->live_in_set); + } } #ifdef DEBUG_LIVENESS @@ -594,7 +594,7 @@ mono_analyze_liveness (MonoCompile *cfg) MonoMethodVar *vi = MONO_VARINFO (cfg, i); if (cfg->varinfo [vi->idx]->opcode == OP_ARG) { if (vi->range.last_use.abs_pos == 0 && !(cfg->varinfo [vi->idx]->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) { - /* + /* * Can't eliminate the this variable in gshared code, since * it is needed during exception handling to identify the * method. @@ -613,11 +613,11 @@ mono_analyze_liveness (MonoCompile *cfg) if (cfg->verbose_level > 1) { for (i = cfg->num_bblocks - 1; i >= 0; i--) { MonoBasicBlock *bb = cfg->bblocks [i]; - - printf ("LIVE IN BB%d: ", bb->block_num); - mono_bitset_print (bb->live_in_set); - printf ("LIVE OUT BB%d: ", bb->block_num); - mono_bitset_print (bb->live_out_set); + + printf ("LIVE IN BB%d: ", bb->block_num); + mono_bitset_print (bb->live_in_set); + printf ("LIVE OUT BB%d: ", bb->block_num); + mono_bitset_print (bb->live_out_set); } for (i = 0; i < max_vars; i ++) { @@ -681,7 +681,7 @@ optimize_initlocals (MonoCompile *cfg) if ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_R4CONST)) { NULLIFY_INS (ins); MONO_VARINFO (cfg, var->inst_c0)->spill_costs -= 1; - /* + /* * We should shorten the liveness interval of these vars as well, but * don't have enough info to do that. */ @@ -801,7 +801,7 @@ mono_linterval_get_intersect_pos (MonoLiveInterval *i1, MonoLiveInterval *i2) return -1; } - + /** * mono_linterval_split * @@ -973,7 +973,7 @@ mono_analyze_liveness2 (MonoCompile *cfg) LIVENESS_DEBUG (printf ("LIVENESS BLOCK BB%d:\n", bb->block_num)); memset (last_use, 0, max_vars * sizeof (gint32)); - + /* For variables in bb->live_out, set last_use to block_to */ max = ((max_vars + (BITS_PER_CHUNK -1)) / BITS_PER_CHUNK); @@ -982,7 +982,7 @@ mono_analyze_liveness2 (MonoCompile *cfg) int k; bits_out = mono_bitset_get_fast (bb->live_out_set, j); - k = (j * BITS_PER_CHUNK); + k = (j * BITS_PER_CHUNK); while (bits_out) { if (bits_out & 1) { LIVENESS_DEBUG (printf ("Var R%d live at exit, set last_use to %x\n", cfg->varinfo [k]->dreg, block_to)); @@ -1030,7 +1030,7 @@ mono_analyze_liveness2 (MonoCompile *cfg) #if 0 for (idx = 0; idx < max_vars; ++idx) { MonoMethodVar *vi = MONO_VARINFO (cfg, idx); - + LIVENESS_DEBUG (printf ("LIVENESS R%d: ", cfg->varinfo [idx]->dreg)); LIVENESS_DEBUG (mono_linterval_print (vi->interval)); LIVENESS_DEBUG (printf ("\n")); @@ -1149,7 +1149,7 @@ mono_analyze_liveness_gc (MonoCompile *cfg) continue; memset (last_use, 0, max_vars * sizeof (gint32)); - + /* For variables in bb->live_out, set last_use to block_to */ max = ((max_vars + (BITS_PER_CHUNK -1)) / BITS_PER_CHUNK); @@ -1162,7 +1162,7 @@ mono_analyze_liveness_gc (MonoCompile *cfg) continue; bits_out = mono_bitset_get_fast (bb->live_out_set, j); - k = (j * BITS_PER_CHUNK); + k = (j * BITS_PER_CHUNK); while (bits_out) { if ((bits_out & 1) && cfg->varinfo [k]->flags & MONO_INST_GC_TRACK) { int vreg = get_vreg_from_var (cfg, cfg->varinfo [k]); diff --git a/src/mono/mono/mini/llvm-runtime.h b/src/mono/mono/mini/llvm-runtime.h index 22d4d136e49c8..bc1eaca1a2c7c 100644 --- a/src/mono/mono/mini/llvm-runtime.h +++ b/src/mono/mono/mini/llvm-runtime.h @@ -26,6 +26,6 @@ mono_llvm_cpp_catch_exception (MonoLLVMInvokeCallback cb, gpointer arg, gboolean G_END_DECLS #endif /* __MONO_LLVM_RUNTIME_H__ */ - + diff --git a/src/mono/mono/mini/llvmonly-runtime.c b/src/mono/mono/mini/llvmonly-runtime.c index 8da3e60cce81b..2aeb93b16a69f 100644 --- a/src/mono/mono/mini/llvmonly-runtime.c +++ b/src/mono/mono/mini/llvmonly-runtime.c @@ -111,7 +111,7 @@ mini_llvmonly_get_delegate_arg (MonoMethod *method, gpointer method_ptr) * This is used for: * - generic sharing (ARG is the rgctx) * - gsharedvt signature wrappers (ARG is a function descriptor) - * + * */ MonoFtnDesc* mini_llvmonly_create_ftndesc (MonoMethod *m, gpointer addr, gpointer arg) @@ -160,7 +160,7 @@ mini_llvmonly_add_method_wrappers (MonoMethod *m, gpointer compiled_method, gboo addr = compiled_method; if (add_unbox_tramp) { - /* + /* * The unbox trampolines call the method directly, so need to add * an rgctx tramp before them. */ diff --git a/src/mono/mono/mini/local-propagation.c b/src/mono/mono/mini/local-propagation.c index 19801edd1f281..8eb4db79b5581 100644 --- a/src/mono/mono/mini/local-propagation.c +++ b/src/mono/mono/mini/local-propagation.c @@ -383,7 +383,7 @@ mono_strength_reduction_ins (MonoCompile *cfg, MonoInst *ins, const char **spec) ins->opcode = OP_ICONST; MONO_INST_NULLIFY_SREGS (ins); ins->inst_c0 = 0; - } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && + } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1) && (!cfg->backend->optimized_div)) { gboolean is_long = ins->opcode == OP_LREM_IMM; int compensator_reg = alloc_ireg (cfg); @@ -600,21 +600,21 @@ mono_local_cprop (MonoCompile *cfg) def = defs [sreg]; /* Copy propagation */ - /* - * The first check makes sure the source of the copy did not change since + /* + * The first check makes sure the source of the copy did not change since * the copy was made. * The second check avoids volatile variables. - * The third check avoids copy propagating local vregs through a call, - * since the lvreg will be spilled + * The third check avoids copy propagating local vregs through a call, + * since the lvreg will be spilled * The fourth check avoids copy propagating a vreg in cases where * it would be eliminated anyway by reverse copy propagation later, - * because propagating it would create another use for it, thus making + * because propagating it would create another use for it, thus making * it impossible to use reverse copy propagation. */ /* Enabling this for floats trips up the fp stack */ - /* - * Enabling this for floats on amd64 seems to cause a failure in - * basic-math.cs, most likely because it gets rid of some r8->r4 + /* + * Enabling this for floats on amd64 seems to cause a failure in + * basic-math.cs, most likely because it gets rid of some r8->r4 * conversions. */ if (MONO_IS_MOVE (def) && @@ -707,7 +707,7 @@ mono_local_cprop (MonoCompile *cfg) } else if (((def->opcode == OP_ADD_IMM) || (def->opcode == OP_LADD_IMM)) && (MONO_IS_LOAD_MEMBASE (ins) || MONO_ARCH_IS_OP_MEMBASE (ins->opcode))) { /* ADD_IMM is created by spill_global_vars */ - /* + /* * We have to guarantee that def->sreg1 haven't changed since def->dreg * was defined. cfg->frame_reg is assumed to remain constant. */ @@ -806,7 +806,7 @@ mono_local_cprop (MonoCompile *cfg) def_index [ins->dreg] = ins_index; } } - + if (MONO_IS_CALL (ins)) last_call_index = ins_index; @@ -825,7 +825,7 @@ reg_is_softreg_no_fpstack (int reg, const char spec) #endif || (spec == 'v'); } - + static gboolean reg_is_softreg (int reg, const char spec) { @@ -864,7 +864,7 @@ mono_is_simd_accessor (MonoInst *ins) /** * mono_local_deadce: * - * Get rid of the dead assignments to local vregs like the ones created by the + * Get rid of the dead assignments to local vregs like the ones created by the * copyprop pass. */ void @@ -933,7 +933,7 @@ mono_local_deadce (MonoCompile *cfg) def = prev_f; spec2 = INS_INFO (def->opcode); - /* + /* * Perform a limited kind of reverse copy propagation, i.e. * transform B <- FOO; A <- B into A <- FOO * This isn't copyprop, not deadce, but it can only be performed @@ -953,17 +953,17 @@ mono_local_deadce (MonoCompile *cfg) /* Enabling this on x86 could screw up the fp stack */ if (reg_is_softreg_no_fpstack (ins->dreg, spec [MONO_INST_DEST])) { - /* + /* * Assignments to global vregs can only be eliminated if there is another * assignment to the same vreg later in the same bblock. */ - if (!mono_bitset_test_fast (used, ins->dreg) && + if (!mono_bitset_test_fast (used, ins->dreg) && (!get_vreg_to_inst (cfg, ins->dreg) || (!bb->extended && !vreg_is_volatile (cfg, ins->dreg) && mono_bitset_test_fast (defined, ins->dreg))) && MONO_INS_HAS_NO_SIDE_EFFECT (ins)) { /* Happens with CMOV instructions */ if (prev_f && prev_f->opcode == OP_ICOMPARE_IMM) { MonoInst *prev = prev_f; - /* + /* * Can't use DELETE_INS since that would interfere with the * FOR_EACH_INS loop. */ @@ -996,7 +996,7 @@ mono_local_deadce (MonoCompile *cfg) regpair = (guint32)(gssize)(l->data); reg = regpair & 0xffffff; - + mono_bitset_set_fast (used, reg); } } @@ -1007,7 +1007,7 @@ mono_local_deadce (MonoCompile *cfg) regpair = (guint32)(gssize)(l->data); reg = regpair & 0xffffff; - + mono_bitset_set_fast (used, reg); } } diff --git a/src/mono/mono/mini/main-core.c b/src/mono/mono/mini/main-core.c index 11866090e1704..66e85d713c947 100644 --- a/src/mono/mono/mini/main-core.c +++ b/src/mono/mono/mini/main-core.c @@ -48,7 +48,7 @@ MONO_API int STDAPICALLTYPE coreclr_create_delegate (void* hostHandle, unsigned // propertyKeys - Keys of properties of the app domain // propertyValues - Values of properties of the app domain // hostHandle - Output parameter, handle of the created host -// domainId - Output parameter, id of the created app domain +// domainId - Output parameter, id of the created app domain // // Returns: // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed @@ -65,7 +65,7 @@ int STDAPICALLTYPE coreclr_initialize (const char* exePath, const char* appDomai // // Parameters: // hostHandle - Handle of the host -// domainId - Id of the domain +// domainId - Id of the domain // argc - Number of arguments passed to the executed assembly // argv - Array of arguments passed to the executed assembly // managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint). @@ -86,7 +86,7 @@ int STDAPICALLTYPE coreclr_execute_assembly (void* hostHandle, unsigned int doma // // Parameters: // hostHandle - Handle of the host -// domainId - Id of the domain +// domainId - Id of the domain // latchedExitCode - Latched exit code after domain unloaded // // Returns: @@ -102,7 +102,7 @@ int STDAPICALLTYPE coreclr_shutdown_2 (void* hostHandle, unsigned int domainId, // // Parameters: // hostHandle - Handle of the host -// domainId - Id of the domain +// domainId - Id of the domain // entryPointAssemblyName - Name of the assembly which holds the custom entry point // entryPointTypeName - Name of the type which holds the custom entry point // entryPointMethodName - Name of the method which is the custom entry point diff --git a/src/mono/mono/mini/main.c b/src/mono/mono/mini/main.c index 36f5b4dce54bc..2e1bf2fd6decc 100644 --- a/src/mono/mono/mini/main.c +++ b/src/mono/mono/mini/main.c @@ -3,7 +3,7 @@ * The main entry point for the mono executable * * The main entry point does a few things: - * + * * * It probes whether the executable has a bundle appended * at the end, and if so, registers the various bundled * resources with Mono and executes the contained bundle @@ -90,7 +90,7 @@ mono_main_with_options (int argc, char *argv []) * "config:NAME" A configuration file (usually file.dll.config) in the payload that is * loaded as the config file for an assembly * "systemconfig:" Treats as a Mono system configuration, payload contains the config file. - * "options:" The payload contains command line options to initialize Mono, as if you + * "options:" The payload contains command line options to initialize Mono, as if you had set them on MONO_ENV_OPTIONS * "config_dir:DIR" Configures the MONO_PATH to point to point to DIR * "machineconfig:" The payload contains the machine.config file to use at runtime @@ -269,7 +269,7 @@ probe_embedded (const char *program, int *ref_argc, char **ref_argv []) p += 8; item_size = STREAM_INT (p); p += 4; - + if (mapaddress == NULL) { char *error_message = NULL; mapaddress = (guchar*)mono_file_map_error (directory_location - offset, MONO_MMAP_READ | MONO_MMAP_PRIVATE, @@ -323,9 +323,9 @@ probe_embedded (const char *program, int *ref_argc, char **ref_argv []) new_argv [j+1] = (*ref_argv)[j]; *ref_argv = new_argv; (*ref_argc)++; - + return TRUE; - + dofree: g_free (directory); doclose: diff --git a/src/mono/mono/mini/memory-access.c b/src/mono/mono/mini/memory-access.c index 51c748c9bbfdb..4af7668fe83d9 100644 --- a/src/mono/mono/mini/memory-access.c +++ b/src/mono/mono/mini/memory-access.c @@ -20,7 +20,7 @@ #define MAX_INLINE_COPIES 16 #define MAX_INLINE_COPY_SIZE 10000 -void +void mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align) { int val_reg; @@ -109,7 +109,7 @@ mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, } } -void +void mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int soffset, int size, int align) { int cur_reg; diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index d6ef76676cfb4..d1a1e91ed21d7 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -220,7 +220,7 @@ mini_ins_info[] = { #define MINI_OP(a,b,dest,src1,src2) ((src2) != NONE ? 2 : ((src1) != NONE ? 1 : 0)), #define MINI_OP3(a,b,dest,src1,src2,src3) ((src3) != NONE ? 3 : ((src2) != NONE ? 2 : ((src1) != NONE ? 1 : 0))), -/* +/* * This should contain the index of the last sreg + 1. This is not the same * as the number of sregs for opcodes like IA64_CMP_EQ_IMM. */ @@ -325,7 +325,7 @@ mono_type_to_regmove (MonoCompile *cfg, MonoType *type) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return OP_MOVE; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -450,7 +450,7 @@ mini_set_inline_failure (MonoCompile *cfg, const char *msg) } /* - * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. + * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. * foo (int i) { ldarg.0; box T; } */ #define UNVERIFIED do { \ @@ -729,7 +729,7 @@ mono_find_leave_clauses (MonoCompile *cfg, guchar *ip, guchar *target) for (i = 0; i < header->num_clauses; ++i) { clause = &header->clauses [i]; - if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) && + if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) && (!MONO_OFFSET_IN_CLAUSE (clause, (target - header->code)))) { MonoLeaveClause *leave = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoLeaveClause)); leave->index = i; @@ -820,7 +820,7 @@ mini_type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: inst->type = STACK_OBJ; return; case MONO_TYPE_I8: @@ -884,7 +884,7 @@ bin_num_table [STACK_MAX] [STACK_MAX] = { {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8, STACK_INV, STACK_INV, STACK_INV, STACK_R4} }; -static const char +static const char neg_table [] = { STACK_INV, STACK_I4, STACK_I8, STACK_PTR, STACK_R8, STACK_INV, STACK_INV, STACK_INV, STACK_R4 }; @@ -1029,7 +1029,7 @@ type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2) case OP_ICOMPARE_IMM: ins->type = bin_comp_table [src1->type] [src1->type] ? STACK_I4 : STACK_INV; if ((src1->type == STACK_I8) || ((TARGET_SIZEOF_VOID_P == 8) && ((src1->type == STACK_PTR) || (src1->type == STACK_OBJ) || (src1->type == STACK_MP)))) - ins->opcode = OP_LCOMPARE_IMM; + ins->opcode = OP_LCOMPARE_IMM; break; case MONO_CEE_BEQ: case MONO_CEE_BGE: @@ -1081,7 +1081,7 @@ type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2) ins->opcode = OP_ICONV_TO_R_UN; break; case STACK_I8: - ins->opcode = OP_LCONV_TO_R_UN; + ins->opcode = OP_LCONV_TO_R_UN; break; case STACK_R4: ins->opcode = OP_RCONV_TO_R8; @@ -1167,7 +1167,7 @@ type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2) ins->opcode += unops_op_map [src1->type]; break; case OP_CKFINITE: - ins->type = STACK_R8; + ins->type = STACK_R8; break; case MONO_CEE_CONV_U2: case MONO_CEE_CONV_U1: @@ -1330,7 +1330,7 @@ check_values_to_signature (MonoInst *args, MonoType *this_ins, MonoMethodSignatu #endif /* - * The got_var contains the address of the Global Offset Table when AOT + * The got_var contains the address of the Global Offset Table when AOT * compiling. */ MonoInst * @@ -1415,7 +1415,7 @@ mini_type_to_stack_type (MonoCompile *cfg, MonoType *t) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return STACK_OBJ; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -1492,7 +1492,7 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins) type = type_from_stack_type (ins); - /* inlining can result in deeper stacks */ + /* inlining can result in deeper stacks */ if (cfg->inline_depth || slot >= cfg->header->max_stack) return mono_compile_create_var (cfg, type, OP_LOCAL); @@ -1519,7 +1519,7 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins) static void mono_save_token_info (MonoCompile *cfg, MonoImage *image, guint32 token, gpointer key) { - /* + /* * Don't use this if a generic_context is set, since that means AOT can't * look up the method using just the image+token. * table == 0 means this is a reference made from a wrapper. @@ -1577,13 +1577,13 @@ handle_stack_args (MonoCompile *cfg, MonoInst **sp, int count) if (!found) { bb->out_stack = (MonoInst **)mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count); for (i = 0; i < count; ++i) { - /* + /* * try to reuse temps already allocated for this purpouse, if they occupy the same * stack slot and if they are of the same type. - * This won't cause conflicts since if 'local' is used to + * This won't cause conflicts since if 'local' is used to * store one of the values in the in_stack of a bblock, then - * the same variable will be used for the same outgoing stack - * slot as well. + * the same variable will be used for the same outgoing stack + * slot as well. * This doesn't work when inlining methods, since the bblocks * in the inlined methods do not inherit their in_stack from * the bblock they are inlined to. See bug #58863 for an @@ -1623,7 +1623,7 @@ handle_stack_args (MonoCompile *cfg, MonoInst **sp, int count) /* * It is possible that the out bblocks already have in_stack assigned, and - * the in_stacks differ. In this case, we will store to all the different + * the in_stacks differ. In this case, we will store to all the different * in_stacks. */ @@ -1880,7 +1880,7 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg) case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_FNPTR: - /* + /* * Some opcodes like ldloca returns 'transient pointers' which can be stored in * in native int. (#688008). */ @@ -1891,7 +1891,7 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: if (arg->type != STACK_OBJ) return 1; /* FIXME: check type compatibility */ @@ -2051,7 +2051,7 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: if (args [i]->type != STACK_OBJ) return TRUE; continue; @@ -2224,7 +2224,7 @@ mono_emit_jit_icall_by_info (MonoCompile *cfg, int il_offset, MonoJitICallInfo * } return mono_emit_jit_icall_id (cfg, mono_jit_icall_info_id (info), args); } - + static MonoInst* mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature *fsig) { @@ -2232,8 +2232,8 @@ mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature * if ((fsig->pinvoke || LLVM_ENABLED) && !m_type_is_byref (fsig->ret)) { int widen_op = -1; - /* - * Native code might return non register sized integers + /* + * Native code might return non register sized integers * without initializing the upper bits. */ switch (mono_type_to_load_membase (cfg, fsig->ret)) { @@ -2543,7 +2543,7 @@ emit_get_rgctx (MonoCompile *cfg, int context_used) /* We are passed a this pointer, return this->vtable */ EMIT_NEW_VARLOAD (cfg, this_ins, cfg->this_arg, mono_get_object_type ()); - + vtable_reg = alloc_preg (cfg); EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, vtable_reg, this_ins->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable)); return ins; @@ -3046,14 +3046,14 @@ mini_emit_check_array_type (MonoCompile *cfg, MonoInst *obj, MonoClass *array_cl MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, (gssize)vtable); } } - + MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "ArrayTypeMismatchException"); mini_reset_cast_details (cfg); } /** - * Handles unbox of a Nullable. If context_used is non zero, then shared + * Handles unbox of a Nullable. If context_used is non zero, then shared * generic code is generated. */ static MonoInst* @@ -3119,7 +3119,7 @@ handle_unbox (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, int context_use /* FIXME: generics */ g_assert (m_class_get_rank (klass) == 0); - + // Check rank == 0 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); @@ -3303,10 +3303,10 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_ return mono_emit_jit_icall_id (cfg, alloc_ftn, iargs); } - + /* * Returns NULL and set the cfg exception on error. - */ + */ MonoInst* mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used) { @@ -3383,7 +3383,7 @@ mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_us res->type = STACK_OBJ; res->klass = klass; MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - + /* Ref case */ MONO_START_BB (cfg, is_ref_bb); @@ -3607,7 +3607,7 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono } } - /* + /* * To avoid looking up the compiled code belonging to the target method * in mono_delegate_trampoline (), we allocate a per-domain memory slot to * store it, and we fill it after the method has been compiled. @@ -3842,7 +3842,7 @@ mono_emit_load_got_addr (MonoCompile *cfg) cfg->got_var_allocated = TRUE; - /* + /* * Add a dummy use to keep the got_var alive, since real uses might * only be generated by the back ends. * Add it to end_bblock, so the variable's lifetime covers the whole @@ -4056,7 +4056,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method) if (method_does_not_return (method)) return FALSE; - + return TRUE; } @@ -4169,7 +4169,7 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono return ins; } -#endif +#endif add_reg = alloc_ireg_mp (cfg); @@ -4235,21 +4235,21 @@ mini_emit_ldelema_2_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono #endif /* range checking */ - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, arr->dreg, MONO_STRUCT_OFFSET (MonoArray, bounds)); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low1_reg, + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low1_reg, bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound)); MONO_EMIT_NEW_BIALU (cfg, OP_PSUB, realidx1_reg, index1, low1_reg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high1_reg, + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high1_reg, bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, length)); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, high1_reg, realidx1_reg); MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low2_reg, + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low2_reg, bounds_reg, sizeof (MonoArrayBounds) + MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound)); MONO_EMIT_NEW_BIALU (cfg, OP_PSUB, realidx2_reg, index2, low2_reg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high2_reg, + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high2_reg, bounds_reg, sizeof (MonoArrayBounds) + MONO_STRUCT_OFFSET (MonoArrayBounds, length)); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, high2_reg, realidx2_reg); MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); @@ -4387,7 +4387,7 @@ mini_emit_memory_barrier (MonoCompile *cfg, int kind) * redirection. */ inline static MonoInst* -mini_redirect_call (MonoCompile *cfg, MonoMethod *method, +mini_redirect_call (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *signature, MonoInst **args, MonoInst *this_ins) { if (method->klass == mono_defaults.string_class) { @@ -4424,7 +4424,7 @@ mono_save_args (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **sp) * FIXME: We should use *args++ = sp [0], but that would mean the arg * would be different than the MonoInst's used to represent arguments, and * the ldelema implementation can't deal with that. - * Solution: When ldelema is used on an inline argument, create a var for + * Solution: When ldelema is used on an inline argument, create a var for * it, emit ldelema on that var, and emit the saving code below in * inline_method () if needed. */ @@ -4446,7 +4446,7 @@ check_inline_called_method_name_limit (MonoMethod *called_method) { int strncmp_result; static const char *limit = NULL; - + if (limit == NULL) { const char *limit_string = g_getenv ("MONO_INLINE_CALLED_METHOD_NAME_LIMIT"); @@ -4461,7 +4461,7 @@ check_inline_called_method_name_limit (MonoMethod *called_method) strncmp_result = strncmp (called_method_name, limit, strlen (limit)); g_free (called_method_name); - + //return (strncmp_result <= 0); return (strncmp_result == 0); } else { @@ -4476,7 +4476,7 @@ check_inline_caller_method_name_limit (MonoMethod *caller_method) { int strncmp_result; static const char *limit = NULL; - + if (limit == NULL) { const char *limit_string = g_getenv ("MONO_INLINE_CALLER_METHOD_NAME_LIMIT"); if (limit_string != NULL) { @@ -4491,7 +4491,7 @@ check_inline_caller_method_name_limit (MonoMethod *caller_method) strncmp_result = strncmp (caller_method_name, limit, strlen (limit)); g_free (caller_method_name); - + //return (strncmp_result <= 0); return (strncmp_result == 0); } else { @@ -4731,7 +4731,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, prev_cbb->next_bb = sbblock; link_bblock (cfg, prev_cbb, sbblock); - /* + /* * Get rid of the begin and end bblocks if possible to aid local * optimizations. */ @@ -4756,7 +4756,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, cfg->cbb = ebblock; } } else { - /* + /* * Its possible that the rvar is set in some prev bblock, but not in others. * (#1835). */ @@ -4779,7 +4779,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, if (rvar) { /* - * If the inlined method contains only a throw, then the ret var is not + * If the inlined method contains only a throw, then the ret var is not * set, so set it to a dummy value. */ if (!ret_var_set) @@ -4808,16 +4808,16 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, /* * Some of these comments may well be out-of-date. - * Design decisions: we do a single pass over the IL code (and we do bblock + * Design decisions: we do a single pass over the IL code (and we do bblock * splitting/merging in the few cases when it's required: a back jump to an IL * address that was not already seen as bblock starting point). * Code is validated as we go (full verification is still better left to metadata/verify.c). - * Complex operations are decomposed in simpler ones right away. We need to let the - * arch-specific code peek and poke inside this process somehow (except when the + * Complex operations are decomposed in simpler ones right away. We need to let the + * arch-specific code peek and poke inside this process somehow (except when the * optimizations can take advantage of the full semantic info of coarse opcodes). * All the opcodes of the form opcode.s are 'normalized' to opcode. - * MonoInst->opcode initially is the IL opcode or some simplification of that - * (OP_LOAD, OP_STORE). The arch-specific code may rearrange it to an arch-specific + * MonoInst->opcode initially is the IL opcode or some simplification of that + * (OP_LOAD, OP_STORE). The arch-specific code may rearrange it to an arch-specific * opcode with value bigger than OP_LAST. * At this point the IR can be handed over to an interpreter, a dumb code generator * or to the optimizing code generator that will translate it to SSA form. @@ -4825,7 +4825,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, * Profiling directed optimizations. * We may compile by default with few or no optimizations and instrument the code * or the user may indicate what methods to optimize the most either in a config file - * or through repeated runs where the compiler applies offline the optimizations to + * or through repeated runs where the compiler applies offline the optimizations to * each method and then decides if it was worth it. */ @@ -4867,7 +4867,7 @@ get_basic_blocks (MonoCompile *cfg, MonoMethodHeader* header, guint real_offset, opcode = &mono_opcodes [i]; switch (opcode->argument) { case MonoInlineNone: - ip++; + ip++; break; case MonoInlineString: case MonoInlineType: @@ -4907,7 +4907,7 @@ get_basic_blocks (MonoCompile *cfg, MonoMethodHeader* header, guint real_offset, cli_addr += 5 + 4 * n; target = start + cli_addr; GET_BBLOCK (cfg, bblock, target); - + for (j = 0; j < n; ++j) { target = start + cli_addr + (gint32)read32 (ip); GET_BBLOCK (cfg, bblock, target); @@ -4925,7 +4925,7 @@ get_basic_blocks (MonoCompile *cfg, MonoMethodHeader* header, guint real_offset, if (i == CEE_THROW) { guchar *bb_start = ip - 1; - + /* Find the start of the bblock containing the throw */ bblock = NULL; while ((bb_start >= start) && !bblock) { @@ -4998,7 +4998,7 @@ mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *conte } /* - * Return the original method is a wrapper is specified. We can only access + * Return the original method is a wrapper is specified. We can only access * the custom attributes from the original method. */ static MonoMethod* @@ -5154,7 +5154,7 @@ initialize_array_data (MonoCompile *cfg, MonoMethod *method, gboolean aot, gucha if (aot && data_ptr) data_ptr = (const char *)GUINT_TO_POINTER (rva); } else { - /*FIXME is it possible to AOT a SRE assembly not meant to be saved? */ + /*FIXME is it possible to AOT a SRE assembly not meant to be saved? */ g_assert (!aot); data_ptr = mono_field_get_data (field); } @@ -5263,7 +5263,7 @@ emit_stloc_ir (MonoCompile *cfg, MonoInst **sp, MonoMethodHeader *header, int n) if (!cfg->deopt && (opcode == OP_MOVE) && cfg->cbb->last_ins == sp [0] && ((sp [0]->opcode == OP_ICONST) || (sp [0]->opcode == OP_I8CONST))) { /* Optimize reg-reg moves away */ - /* + /* * Can't optimize other opcodes, since sp[0] might point to * the last ins of a decomposed opcode. */ @@ -6105,7 +6105,7 @@ mono_opcode_decode (guchar *ip, guint op_size, MonoOpcodeEnum il_op, MonoOpcodeP * * @start_bblock: if not NULL, the starting basic block, used during inlining. * @end_bblock: if not NULL, the ending basic block, used during inlining. - * @return_var: if not NULL, the place where the return value is stored, used during inlining. + * @return_var: if not NULL, the place where the return value is stored, used during inlining. * @inline_args: if not NULL, contains the arguments to the inline call * @inline_offset: if not zero, the real offset from the inline call, or zero otherwise. * @is_virtual_call: whether this method is being called as a result of a call to callvirt @@ -6115,12 +6115,12 @@ mono_opcode_decode (guchar *ip, guint op_size, MonoOpcodeEnum il_op, MonoOpcodeP * inlining existing methods. In the former case, the @start_bblock, * @end_bblock, @return_var, @inline_args are all set to NULL, and the * inline_offset is set to zero. - * + * * Returns: the inline cost, or -1 if there was an error processing this method. */ int -mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, - MonoInst *return_var, MonoInst **inline_args, +mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, + MonoInst *return_var, MonoInst **inline_args, guint inline_offset, gboolean is_virtual_call) { ERROR_DECL (error); @@ -6251,7 +6251,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } - /* + /* * Methods without init_locals set could cause asserts in various passes * (#497220). To work around this, we emit dummy initialization opcodes * (OP_DUMMY_ICONST etc.) which generate no code. These are only supported @@ -6348,7 +6348,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) mono_create_exvar_for_offset (cfg, clause->handler_offset); /* - * Linking the try block with the EH block hinders inlining as we won't be able to + * Linking the try block with the EH block hinders inlining as we won't be able to * merge the bblocks from inlining and produce an artificial hole for no good reason. */ if (COMPILE_LLVM (cfg)) @@ -6401,7 +6401,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b #else MonoInst *dummy_use; - /* + /* * Add a dummy use for the exvar so its liveness info will be * correct. */ @@ -6543,7 +6543,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ins->sreg1 = dreg; MONO_ADD_INS (cfg->cbb, ins); cfg->gsharedvt_locals_var_ins = ins; - + cfg->flags |= MONO_CFG_HAS_ALLOCA; /* if (init_locals) @@ -7014,7 +7014,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_ADD_INS (cfg->cbb, ins); } *f = parameter.f; - *sp++ = ins; + *sp++ = ins; break; } case MONO_CEE_LDC_R8: { @@ -7092,7 +7092,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* FIXME: check the signature matches */ cmethod = mini_get_method (cfg, method, token, NULL, generic_context); CHECK_CFG_ERROR; - + if (cfg->gshared && mono_method_check_context_used (cmethod)) GENERIC_SHARING_FAILURE (CEE_JMP); @@ -7214,17 +7214,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_assert (!fsig->hasthis && !fsig->pinvoke); - gboolean inline_wrapper = cfg->opt & MONO_OPT_INLINE || cfg->compile_aot; - if (inline_wrapper) { - int costs = inline_method (cfg, wrapper, fsig, sp, ip, cfg->real_offset, TRUE, NULL); - CHECK_CFG_EXCEPTION; - g_assert (costs > 0); - cfg->real_offset += 5; - inline_costs += costs; - ins = sp[0]; - } else { - ins = mono_emit_method_call (cfg, wrapper, /*args*/sp, NULL); - } + ins = mono_emit_method_call (cfg, wrapper, /*args*/sp, NULL); goto calli_end; } } @@ -7551,7 +7541,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoBasicBlock *tbb; GET_BBLOCK (cfg, tbb, next_ip); - /* + /* * Only extend try blocks with a finally, to avoid catching exceptions thrown * from Monitor.Enter like ArgumentNullException. */ @@ -7576,7 +7566,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } CHECK_CFG_ERROR; - /* + /* * If the callee is a shared method, then its static cctor * might not get called after the call was patched. */ @@ -7678,8 +7668,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_assert (!vtable_arg); if (!cfg->compile_aot) { - /* - * emit_get_rgctx_method () calls mono_class_vtable () so check + /* + * emit_get_rgctx_method () calls mono_class_vtable () so check * for type load errors before. */ mono_class_setup_vtable (cmethod->klass); @@ -8013,7 +8003,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (array_rank) { MonoInst *addr; - if (strcmp (cmethod->name, "Set") == 0) { /* array Set */ + if (strcmp (cmethod->name, "Set") == 0) { /* array Set */ MonoInst *val = sp [fsig->param_count]; if (val->type == STACK_OBJ) { @@ -8199,7 +8189,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } ins_flag = 0; constrained_class = NULL; - + if (need_seq_point) { //check is is a nested call and remove the non_empty_stack of the last call, only for non native methods if (!(method->flags & METHOD_IMPL_ATTRIBUTE_NATIVE)) { @@ -8222,10 +8212,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->method != method) { /* return from inlined method */ - /* + /* * If in_count == 0, that means the ret is unreachable due to * being preceded by a throw. In that case, inline_method () will - * handle setting the return value + * handle setting the return value * (test case: test_0_inline_throw ()). */ if (return_var && cfg->cbb->in_count) { @@ -8242,7 +8232,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b //g_assert (returnvar != -1); EMIT_NEW_TEMPSTORE (cfg, store, return_var->inst_c0, *sp); cfg->ret_var_set = TRUE; - } + } } else { if (cfg->lmf_var && cfg->cbb->in_count && (!cfg->llvm_only || cfg->deopt)) emit_pop_lmf (cfg); @@ -8251,7 +8241,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoType *ret_type = mini_get_underlying_type (mono_method_signature_internal (method)->ret); if (seq_points && !sym_seq_points) { - /* + /* * Place a seq point here too even through the IL stack is not * empty, so a step over on * call @@ -8415,7 +8405,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b n = read32 (ip + 1); --sp; src1 = sp [0]; - if ((src1->type != STACK_I4) && (src1->type != STACK_PTR)) + if ((src1->type != STACK_I4) && (src1->type != STACK_PTR)) UNVERIFIED; ip += 5; @@ -8432,7 +8422,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } if (sp != stack_start) { - /* + /* * Link the current bb with the targets as well, so handle_stack_args * will set their in_stack correctly. */ @@ -8843,8 +8833,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoInst *iargs [2]; if (image == mono_defaults.corlib) { - /* - * Avoid relocations in AOT and save some space by using a + /* + * Avoid relocations in AOT and save some space by using a * version of helper_ldstr specialized to mscorlib. */ EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (n)); @@ -8855,13 +8845,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b EMIT_NEW_ICONST (cfg, iargs [1], mono_metadata_token_index (n)); *sp = mono_emit_jit_icall (cfg, mono_helper_ldstr, iargs); } - } + } else if (cfg->compile_aot) { NEW_LDSTRCONST (cfg, ins, image, n); *sp = ins; MONO_ADD_INS (cfg->cbb, ins); - } + } else { NEW_PCONST (cfg, ins, NULL); ins->type = STACK_OBJ; @@ -8930,13 +8920,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b n = fsig->param_count; CHECK_STACK (n); - /* + /* * Generate smaller code for the common newobj instruction in * argument checking code. */ if (cfg->cbb->out_of_line && m_class_get_image (cmethod->klass) == mono_defaults.corlib && is_exception_class (cmethod->klass) && n <= 2 && - ((n < 1) || (!m_type_is_byref (fsig->params [0]) && fsig->params [0]->type == MONO_TYPE_STRING)) && + ((n < 1) || (!m_type_is_byref (fsig->params [0]) && fsig->params [0]->type == MONO_TYPE_STRING)) && ((n < 2) || (!m_type_is_byref (fsig->params [1]) && fsig->params [1]->type == MONO_TYPE_STRING))) { MonoInst *iargs [3]; @@ -9047,7 +9037,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_assert (!context_used); g_assert (!vtable_arg); /* we simply pass a null pointer */ - EMIT_NEW_PCONST (cfg, *sp, NULL); + EMIT_NEW_PCONST (cfg, *sp, NULL); /* now call the string ctor */ alloc = mini_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, NULL, NULL, NULL); } else { @@ -9058,7 +9048,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b alloc = NULL; - /* + /* * The code generated by mini_emit_virtual_call () expects * iargs [0] to be a boxed instance, but luckily the vcall * will be transformed into a normal call there. @@ -9113,7 +9103,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } else { *sp++ = alloc; } - + inline_costs += 5; if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, next_ip - header->code))) emit_seq_point (cfg, method, next_ip, FALSE, TRUE); @@ -9278,8 +9268,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } // Optimize - // - // box + // + // box // call object::GetType() // guint32 gettype_token; @@ -9297,7 +9287,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } ins->type = STACK_OBJ; ins->klass = mono_defaults.systemtype_class; - *sp++ = ins; + *sp++ = ins; next_ip = ip; break; } @@ -9305,13 +9295,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } // Optimize - // + // // box // ldnull // ceq (or cgt.un) - // + // // to just - // + // // ldc.i4.0 (or 1) guchar* ldnull_ip; if ((ldnull_ip = il_read_op (next_ip, end, CEE_LDNULL, MONO_CEE_LDNULL)) && ip_in_bb (cfg, cfg->cbb, ldnull_ip)) { @@ -9321,7 +9311,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b else if ((ip = il_read_op (ldnull_ip, end, CEE_PREFIX1, MONO_CEE_CGT_UN))) is_neq = TRUE; - if ((is_eq || is_neq) && ip_in_bb (cfg, cfg->cbb, ip) && + if ((is_eq || is_neq) && ip_in_bb (cfg, cfg->cbb, ip) && !mono_class_is_nullable (klass) && !mini_is_gsharedvt_klass (klass)) { next_ip = ip; il_op = (MonoOpcodeEnum) (is_eq ? CEE_LDC_I4_0 : CEE_LDC_I4_1); @@ -9331,7 +9321,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b break; } } - + guint32 isinst_tk = 0; if ((ip = il_read_op_and_token (next_ip, end, CEE_ISINST, MONO_CEE_ISINST, &isinst_tk)) && ip_in_bb (cfg, cfg->cbb, ip)) { @@ -9342,13 +9332,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b !mono_class_is_open_constructed_type (m_class_get_byval_arg (isinst_class))) { // Optimize - // + // // box // isinst [Type] // brfalse/brtrue - // + // // to - // + // // ldc.i4.0 (or 1) // brfalse/brtrue // @@ -9366,14 +9356,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } // Optimize - // + // // box // isinst [Type] // ldnull // ceq/cgt.un - // + // // to - // + // // ldc.i4.0 (or 1) // guchar* ldnull_ip = NULL; @@ -9384,7 +9374,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b else if ((ip = il_read_op (ldnull_ip, end, CEE_PREFIX1, MONO_CEE_CGT_UN))) is_neq = TRUE; - if ((is_eq || is_neq) && ip_in_bb (cfg, cfg->cbb, ip) && + if ((is_eq || is_neq) && ip_in_bb (cfg, cfg->cbb, ip) && !mono_class_is_nullable (klass) && !mini_is_gsharedvt_klass (klass)) { gboolean isinst = mono_class_is_assignable_from_internal (isinst_class, klass); next_ip = ip; @@ -9399,13 +9389,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } // Optimize - // + // // box // isinst [Type] // unbox.any - // + // // to - // + // // nop // guchar* unbox_ip = NULL; @@ -9448,7 +9438,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b printf ("\n"); } - /* + /* * We need to link both bblocks, since it is needed for handling stack * arguments correctly (See test_0_box_brtrue_opt_regress_81102). * Branching to only one of them would lead to inconsistencies, so @@ -9968,7 +9958,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b case MONO_TYPE_I1: EMIT_NEW_ICONST (cfg, *sp, *((gint8 *)addr)); sp++; - break; + break; case MONO_TYPE_CHAR: case MONO_TYPE_U2: EMIT_NEW_ICONST (cfg, *sp, *((guint16 *)addr)); @@ -9982,7 +9972,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b case MONO_TYPE_I4: EMIT_NEW_ICONST (cfg, *sp, *((gint32 *)addr)); sp++; - break; + break; case MONO_TYPE_U4: EMIT_NEW_ICONST (cfg, *sp, *((guint32 *)addr)); sp++; @@ -10134,7 +10124,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b *sp++ = ins; inline_costs += 1; - /* + /* * we inline/optimize the initialization sequence if possible. * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing * for small sizes open code the memcpy @@ -10515,7 +10505,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_INST_NEW (cfg, ins, OP_NOT_REACHED); MONO_ADD_INS (cfg->cbb, ins); sp = stack_start; - + link_bblock (cfg, cfg->cbb, end_bblock); start_new_bblock = 1; /* This can complicate code generation for llvm since the return value might not be defined */ @@ -10549,7 +10539,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_assert (sp >= stack_start); sp = stack_start; - /* + /* * If this leave statement is in a catch block, check for a * pending exception, and rethrow it if necessary. * We avoid doing this in runtime invoke wrappers, since those are called @@ -10558,7 +10548,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b for (i = 0; i < header->num_clauses; ++i) { MonoExceptionClause *clause = &header->clauses [i]; - /* + /* * Use <= in the final comparison to handle clauses with multiple * leave statements, like in bug #78024. * The ordering of the exception clauses guarantees that we find the @@ -10579,9 +10569,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b NEW_BBLOCK (cfg, dont_throw); /* - * Currently, we always rethrow the abort exception, despite the - * fact that this is not correct. See thread6.cs for an example. - * But propagating the abort exception is more important than + * Currently, we always rethrow the abort exception, despite the + * fact that this is not correct. See thread6.cs for an example. + * But propagating the abort exception is more important than * getting the semantics right. */ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, exc_ins->dreg, 0); @@ -10645,7 +10635,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (COMPILE_LLVM (cfg)) { MonoBasicBlock *target_bb; - /* + /* * Link the finally bblock with the target, since it will * conceptually branch there. */ @@ -10654,7 +10644,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b link_bblock (cfg, tblock, target_bb); } } - } + } MONO_INST_NEW (cfg, ins, OP_BR); MONO_ADD_INS (cfg->cbb, ins); @@ -11167,7 +11157,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b case MONO_CEE_ARGLIST: { /* somewhat similar to LDTOKEN */ MonoInst *addr, *vtvar; - vtvar = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_defaults.argumenthandle_class), OP_LOCAL); + vtvar = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_defaults.argumenthandle_class), OP_LOCAL); EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0); EMIT_NEW_UNALU (cfg, ins, OP_ARGLIST, -1, addr->dreg); @@ -11767,7 +11757,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_free (mname); } - if ((cfg->verbose_level > 2) && (cfg->method == method)) + if ((cfg->verbose_level > 2) && (cfg->method == method)) mono_print_code (cfg, "AFTER METHOD-TO-IR"); goto cleanup; @@ -11778,7 +11768,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b g_assert (!is_ok (cfg->error)); goto cleanup; - + exception_exit: if (cfg->verbose_level > 3) g_print ("exiting due to exception"); @@ -11822,7 +11812,7 @@ store_membase_reg_to_store_membase_imm (int opcode) } return -1; -} +} int mono_op_to_op_imm (int opcode) @@ -12128,7 +12118,7 @@ op_to_op_src2_membase (MonoCompile *cfg, int load_opcode, int opcode) #ifdef TARGET_X86 if (!((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE))) return -1; - + switch (opcode) { case OP_COMPARE: case OP_ICOMPARE: @@ -12300,7 +12290,7 @@ mono_handle_global_vregs (MonoCompile *cfg) /* Find local vregs used in more than one bb */ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { - MonoInst *ins = bb->code; + MonoInst *ins = bb->code; int block_num = bb->block_num; if (cfg->verbose_level > 2) @@ -12439,7 +12429,7 @@ mono_handle_global_vregs (MonoCompile *cfg) /* Putting R4 vars into registers doesn't work currently */ /* The gsharedvt vars are implicitly referenced by ldaddr opcodes, but those opcodes are only generated later */ if ((var->opcode != OP_ARG) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && (vreg_to_bb [var->dreg] != -1) && (m_class_get_byval_arg (var->klass)->type != MONO_TYPE_R4) && !cfg->disable_vreg_to_lvreg && var != cfg->gsharedvt_info_var && var != cfg->gsharedvt_locals_var && var != cfg->lmf_addr_var) { - /* + /* * Make that the variable's liveness interval doesn't contain a call, since * that would cause the lvreg to be spilled, making the whole optimization * useless. @@ -12488,7 +12478,7 @@ mono_handle_global_vregs (MonoCompile *cfg) } } - /* + /* * Compress the varinfo and vars tables so the liveness computation is faster and * takes up less space. */ @@ -12559,7 +12549,7 @@ mono_allocate_gsharedvt_vars (MonoCompile *cfg) /** * mono_spill_global_vars: * - * Generate spill code for variables which are not allocated to registers, + * Generate spill code for variables which are not allocated to registers, * and replace vregs with their allocated hregs. *need_local_opts is set to TRUE if * code is generated which could be optimized by the local optimization passes. */ @@ -12634,11 +12624,11 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) ins->flags |= MONO_INST_GC_TRACK; } } - + /* FIXME: widening and truncation */ /* - * As an optimization, when a variable allocated to the stack is first loaded into + * As an optimization, when a variable allocated to the stack is first loaded into * an lvreg, we will remember the lvreg and use it the next time instead of loading * the variable again. */ @@ -12648,7 +12638,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * lvregs_size); lvregs_len = 0; - /* + /* * These arrays contain the first and last instructions accessing a given * variable. * Since we emit bblocks in the same order we process them here, and we @@ -12665,7 +12655,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) live_range_end = g_new0 (MonoInst*, cfg->next_vreg); live_range_start_bb = g_new (MonoBasicBlock*, cfg->next_vreg); live_range_end_bb = g_new (MonoBasicBlock*, cfg->next_vreg); - + /* Add spill loads/stores */ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { MonoInst *ins; @@ -12691,7 +12681,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) if (ins->opcode == OP_NOP) continue; - /* + /* * We handle LDADDR here as well, since it can only be decomposed * when variable addresses are known. */ @@ -12835,7 +12825,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) if (var->opcode == OP_REGVAR) { ins->dreg = var->dreg; } else if ((ins->dreg == ins->sreg1) && (spec [MONO_INST_DEST] == 'i') && (spec [MONO_INST_SRC1] == 'i') && !vreg_to_lvreg [ins->dreg] && (op_to_op_dest_membase (store_opcode, ins->opcode) != -1)) { - /* + /* * Instead of emitting a load+store, use a _membase opcode. */ g_assert (var->opcode == OP_REGOFFSET); @@ -12924,7 +12914,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) def_ins = store_ins; - /* + /* * We can't assign ins->dreg to var->dreg here, since the * sregs could use it. So set a flag, and do it after * the sregs. @@ -13142,7 +13132,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) } } } - + /* * Emit LIVERANGE_START/LIVERANGE_END opcodes, the backend will implement them * by storing the current native offset into MonoMethodVar->live_range_start/end. @@ -13199,7 +13189,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) * - get rid of TEMPLOADs if possible and use vregs instead * - clean up usage of OP_P/OP_ opcodes * - cleanup usage of DUMMY_USE - * - cleanup the setting of ins->type for MonoInst's which are pushed on the + * - cleanup the setting of ins->type for MonoInst's which are pushed on the * stack * - set the stack type and allocate a dreg in the EMIT_NEW macros * - get rid of all the 2 stuff when the new JIT is ready. @@ -13211,7 +13201,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) * - most back ends unify fp compare+branch, fp compare+ceq * - integrate mono_save_args into inline_method * - get rid of the empty bblocks created by MONO_EMIT_NEW_BRACH_BLOCK2 - * - handle long shift opts on 32 bit platforms somehow: they require + * - handle long shift opts on 32 bit platforms somehow: they require * 3 sregs (2 for arg1 and 1 for arg2) * - make byref a 'normal' type. * - use vregs for bb->out_stacks if possible, handle_global_vreg will make them a @@ -13232,7 +13222,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) * - promote RuntimeXHandles to vregs * - vtype cleanups: * - add a NEW_VARLOADA_VREG macro - * - the vtype optimizations are blocked by the LDADDR opcodes generated for + * - the vtype optimizations are blocked by the LDADDR opcodes generated for * accessing vtype fields. * - get rid of I8CONST on 64 bit platforms * - dealing with the increase in code size due to branches created during opcode @@ -13255,7 +13245,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts) * specific function. * - unify the float comparison opcodes with the other comparison opcodes, i.e. * fcompare + branchCC. - * - create a helper function for allocating a stack slot, taking into account + * - create a helper function for allocating a stack slot, taking into account * MONO_CFG_HAS_SPILLUP. * - merge r68207. * - optimize mono_regstate2_alloc_int/float. @@ -13281,8 +13271,8 @@ NOTES no longer contains the necessary information. But it is easier to do. - later: harder to implement, enables more optimizations. - Branches inside bblocks: - - created when decomposing complex opcodes. - - branches to another bblock: harmless, but not tracked by the branch + - created when decomposing complex opcodes. + - branches to another bblock: harmless, but not tracked by the branch optimizations, so need to branch to a label at the start of the bblock. - branches to inside the same bblock: very problematic, trips up the local reg allocator. Can be fixed by spitting the current bblock, but that is a @@ -13297,7 +13287,7 @@ NOTES - earlier -> saves work later on since the IR will be smaller/simpler - later -> can work on more instructions - Handling of valuetypes: - - When a vtype is pushed on the stack, a new temporary is created, an + - When a vtype is pushed on the stack, a new temporary is created, an instruction computing its address (LDADDR) is emitted and pushed on the stack. Need to optimize cases when the vtype is used immediately as in argument passing, stloc etc. diff --git a/src/mono/mono/mini/mini-amd64-gsharedvt.c b/src/mono/mono/mini/mini-amd64-gsharedvt.c index 77fc0e3b89189..b2a202195ca58 100644 --- a/src/mono/mono/mini/mini-amd64-gsharedvt.c +++ b/src/mono/mono/mini/mini-amd64-gsharedvt.c @@ -62,7 +62,7 @@ arg_info_desc (ArgInfo *info) g_string_append_printf (str, "offset %d reg %s storage %s nregs %d", info->offset, mono_arch_regname (info->reg), storage_name (info->storage), info->nregs); if (info->storage == ArgValuetypeInReg) - g_string_append_printf (str, " {(%s %s), (%s %s)", + g_string_append_printf (str, " {(%s %s), (%s %s)", storage_name (info->pair_storage [0]), mono_arch_regname (info->pair_regs [0]), storage_name (info->pair_storage [1]), @@ -432,7 +432,7 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr #ifdef DEBUG_AMD64_GSHAREDVT printf ("final map:\n"); for (i = 0; i < map->len; i += 2) { - printf ("\t[%d] src %x dst %x\n ", + printf ("\t[%d] src %x dst %x\n ", i / 2, GPOINTER_TO_UINT (g_ptr_array_index (map, i)), GPOINTER_TO_UINT (g_ptr_array_index (map, i + 1))); diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 7b5c36779f1b0..838fb352d75e3 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -100,7 +100,7 @@ mono_arch_regname (int reg) case AMD64_RBX: return "%rbx"; case AMD64_RCX: return "%rcx"; case AMD64_RDX: return "%rdx"; - case AMD64_RSP: return "%rsp"; + case AMD64_RSP: return "%rsp"; case AMD64_RBP: return "%rbp"; case AMD64_RDI: return "%rdi"; case AMD64_RSI: return "%rsi"; @@ -505,7 +505,7 @@ allocate_storage_for_valuetype_win64 (ArgInfo *arg_info, MonoType *type, gboolea if (!allocate_parameter_register_for_valuetype_win64 (arg_info, !MONO_TYPE_ISSTRUCT (type) ? arg_class : ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg)) { /* No more registers, fallback passing parameter on stack as value. */ assert (arg_info->pair_storage [0] == ArgNone && arg_info->pair_storage [1] == ArgNone && arg_info->pair_size [0] == 0 && arg_info->pair_size [1] == 0 && arg_info->nregs == 0); - + /* Passing value directly on stack, so use size of value. */ arg_info->storage = ArgOnStack; arg_size = ALIGN_TO (arg_size, sizeof (target_mgreg_t)); @@ -519,7 +519,7 @@ allocate_storage_for_valuetype_win64 (ArgInfo *arg_info, MonoType *type, gboolea if (!allocate_parameter_register_for_valuetype_win64 (arg_info, ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg)) { /* No more registers, fallback passing address to parameter on stack. */ assert (arg_info->pair_storage [0] == ArgNone && arg_info->pair_storage [1] == ArgNone && arg_info->pair_size [0] == 0 && arg_info->pair_size [1] == 0 && arg_info->nregs == 0); - + /* Passing an address to value on stack, so use size of register as argument size. */ arg_info->storage = ArgValuetypeAddrOnStack; arg_size = sizeof (target_mgreg_t); @@ -561,7 +561,7 @@ get_valuetype_size_win64 (MonoClass *klass, gboolean pinvoke, ArgInfo *arg_info, *arg_class = ARG_CLASS_NO_CLASS; assert (klass != NULL && arg_info != NULL && type != NULL && arg_class != NULL && arg_size != NULL); - + if (pinvoke) { /* Calculate argument class type and size of marshalled type. */ MonoMarshalType *info = mono_marshal_load_type_info (klass); @@ -602,11 +602,11 @@ add_valuetype_win64 (MonoMethodSignature *signature, ArgInfo *arg_info, MonoType guint32 arg_size = SIZEOF_REGISTER; MonoClass *klass = NULL; ArgumentClass arg_class; - + assert (signature != NULL && arg_info != NULL && type != NULL && current_int_reg != NULL && current_float_reg != NULL && stack_size != NULL); klass = mono_class_from_mono_type_internal (type); - get_valuetype_size_win64 (klass, signature->pinvoke, arg_info, type, &arg_class, &arg_size); + get_valuetype_size_win64 (klass, signature->pinvoke && !signature->marshalling_disabled, arg_info, type, &arg_class, &arg_size); /* Only drop value type if its not an empty struct as input that must be represented in call */ if ((arg_size == 0 && !arg_info->pass_empty_struct) || (arg_info->pass_empty_struct && is_return)) { @@ -640,7 +640,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, int struct_size; klass = mono_class_from_mono_type_internal (type); - size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke); + size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke && !sig->marshalling_disabled); if (!sig->pinvoke && ((is_return && (size == 8)) || (!is_return && (size <= 16)))) { /* We pass and return vtypes of size 8 in a register */ @@ -650,7 +650,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, /* If this struct can't be split up naturally into 8-byte */ /* chunks (registers), pass it on the stack. */ - if (sig->pinvoke) { + if (sig->pinvoke && !sig->marshalling_disabled) { MonoMarshalType *info = mono_marshal_load_type_info (klass); g_assert (info); struct_size = info->native_size; @@ -662,7 +662,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, * handle nested structures. */ fields_array = g_array_new (FALSE, TRUE, sizeof (StructFieldInfo)); - collect_field_info_nested (klass, fields_array, 0, sig->pinvoke, m_class_is_unicode (klass)); + collect_field_info_nested (klass, fields_array, 0, sig->pinvoke && !sig->marshalling_disabled, m_class_is_unicode (klass)); fields = (StructFieldInfo*)fields_array->data; nfields = fields_array->len; @@ -972,7 +972,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == 0)) { gr = PARAM_REGS; fr = FLOAT_PARAM_REGS; - + /* Emit the signature cookie just before the implicit arguments */ add_general (&gr, &stack_size, &cinfo->sig_cookie); } @@ -991,8 +991,8 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) { /* We allways pass the sig cookie on the stack for simplicity */ - /* - * Prevent implicit arguments + the sig cookie from being passed + /* + * Prevent implicit arguments + the sig cookie from being passed * in registers. */ gr = PARAM_REGS; @@ -1077,7 +1077,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n > 0) && (sig->sentinelpos == sig->param_count)) { gr = PARAM_REGS; fr = FLOAT_PARAM_REGS; - + /* Emit the signature cookie just before the implicit arguments */ add_general (&gr, &stack_size, &cinfo->sig_cookie); } @@ -1349,7 +1349,7 @@ mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the argument area on the stack. */ @@ -1518,7 +1518,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; - if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || + if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) continue; @@ -1584,7 +1584,7 @@ mono_arch_compute_omit_fp (MonoCompile *cfg) ArgInfo *ainfo = &cinfo->args [i]; if (ainfo->storage == ArgOnStack || ainfo->storage == ArgValuetypeAddrInIReg || ainfo->storage == ArgValuetypeAddrOnStack) { - /* + /* * The stack offset can only be determined when the frame * size is known. */ @@ -1628,7 +1628,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -1666,8 +1666,8 @@ mono_arch_fill_argument_info (MonoCompile *cfg) /* * Contrary to mono_arch_allocate_vars (), the information should describe - * where the arguments are at the beginning of the method, not where they can be - * accessed during the execution of the method. The later makes no sense for the + * where the arguments are at the beginning of the method, not where they can be + * accessed during the execution of the method. The later makes no sense for the * global register allocator, since a variable can be in more than one location. */ switch (cinfo->ret.storage) { @@ -1714,7 +1714,7 @@ mono_arch_fill_argument_info (MonoCompile *cfg) } } } - + void mono_arch_allocate_vars (MonoCompile *cfg) { @@ -1832,7 +1832,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->locals_min_stack_offset = - (offset + locals_stack_size); cfg->locals_max_stack_offset = - offset; } - + for (i = cfg->locals_start; i < cfg->num_varinfo; i++) { if (offsets [i] != -1) { MonoInst *ins = cfg->varinfo [i]; @@ -1863,7 +1863,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) inreg = FALSE; - /* + /* * Under AMD64, all registers used to pass arguments to functions * are volatile across calls. * FIXME: Optimize this. @@ -1910,10 +1910,10 @@ mono_arch_allocate_vars (MonoCompile *cfg) indir->inst_basereg = cfg->frame_reg; indir->inst_offset = ainfo->offset + ARGS_OFFSET; } - + ins->opcode = OP_VTARG_ADDR; ins->inst_left = indir; - + break; } default: @@ -2056,11 +2056,11 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) NOT_IMPLEMENTED; g_assert (cinfo->sig_cookie.storage == ArgOnStack); - + /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup_full (m_class_get_image (cfg->method->klass), call->signature); @@ -2112,7 +2112,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) /* * LLVM always uses the native ABI while we use our own ABI, the * only difference is the handling of vtypes: - * - we only pass/receive them in registers in some cases, and only + * - we only pass/receive them in registers in some cases, and only * in 1 or 2 integer registers. */ switch (cinfo->ret.storage) { @@ -2228,7 +2228,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) return; } - /* + /* * Emit all arguments which are passed on the stack to prevent register * allocation problems. */ @@ -2311,7 +2311,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) guint32 align; guint32 size; - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_type_native_stack_size (t, &align); else { /* @@ -2460,9 +2460,9 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) MonoInst *vtaddr, *load; g_assert (ainfo->storage == ArgValuetypeAddrInIReg || (ainfo->storage == ArgValuetypeAddrOnStack && ainfo->pair_storage [0] == ArgNone)); - + vtaddr = mono_compile_create_var (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL); - vtaddr->backend.is_pinvoke = call->signature->pinvoke; + vtaddr->backend.is_pinvoke = call->signature->pinvoke && !call->signature->marshalling_disabled; MONO_INST_NEW (cfg, load, OP_LDADDR); cfg->has_indirection = TRUE; @@ -2528,7 +2528,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg); return; } - + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg); } @@ -2591,7 +2591,7 @@ dyn_call_supported (MonoMethodSignature *sig, CallInfo *cinfo) /* * mono_arch_dyn_call_prepare: * - * Return a pointer to an arch-specific structure which contains information + * Return a pointer to an arch-specific structure which contains information * needed by mono_arch_get_dyn_call_args (). Return NULL if OP_DYN_CALL is not * supported for SIG. * This function is equivalent to ffi_prep_cif in libffi. @@ -2658,7 +2658,7 @@ mono_arch_dyn_call_prepare (MonoMethodSignature *sig) /* Align to 16 bytes */ if (info->nstack_args & 1) info->nstack_args ++; - + return (MonoDynCallInfo*)info; } @@ -2697,7 +2697,7 @@ mono_arch_dyn_call_get_buf_size (MonoDynCallInfo *info) * RET should point to a memory buffer large enought to hold the result of the * call. * This function should be as fast as possible, any work which does not depend - * on the actual values of the arguments should be done in + * on the actual values of the arguments should be done in * mono_arch_dyn_call_prepare (). * start_dyn_call + OP_DYN_CALL + finish_dyn_call is equivalent to ffi_call in * libffi. @@ -2909,7 +2909,7 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g * Store the result of a dyn call into the return value buffer passed to * start_dyn_call (). * This function should be as fast as possible, any work which does not depend - * on the actual values of the arguments should be done in + * on the actual values of the arguments should be done in * mono_arch_dyn_call_prepare (). */ void @@ -3014,7 +3014,7 @@ mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf) } else { \ EMIT_COND_BRANCH (tins, cond, signed); \ } \ - } while (0); + } while (0); #define EMIT_SSE2_FPFUNC(code, op, dreg, sreg1) do { \ amd64_movsd_membase_reg (code, AMD64_RSP, -8, (sreg1)); \ @@ -3045,7 +3045,7 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji patch.target = call->fptr; } - /* + /* * FIXME: Add support for thunks */ { @@ -3053,7 +3053,7 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji /* * Indirect calls are expensive so try to make a near call if possible. - * The caller memory is allocated by the code manager so it is + * The caller memory is allocated by the code manager so it is * guaranteed to be at a 32 bit offset. */ @@ -3073,7 +3073,7 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji /* The target is in malloc-ed memory */ near_call = FALSE; } else { - /* + /* * The call might go directly to a native function without * the wrapper. */ @@ -3095,7 +3095,7 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji near_call = TRUE; no_patch = TRUE; } else { - /* + /* * This is not really an optimization, but required because the * generic class init trampolines use R11 to pass the vtable. */ @@ -3144,7 +3144,7 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji } if (near_call) { - /* + /* * Align the call displacement to an address divisible by 4 so it does * not span cache lines. This is required for code patching to work on SMP * systems. @@ -3209,9 +3209,9 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IADD_IMM: case OP_LADD_IMM: if ((ins->sreg1 < MONO_MAX_IREGS) && (ins->dreg >= MONO_MAX_IREGS) && (ins->inst_imm > 0)) { - /* + /* * X86_LEA is like ADD, but doesn't have the - * sreg1==dreg restriction. inst_imm > 0 is needed since LEA sign-extends + * sreg1==dreg restriction. inst_imm > 0 is needed since LEA sign-extends * its operand to 64 bit. */ ins->opcode = ins->opcode == OP_IADD_IMM ? OP_X86_LEA_MEMBASE : OP_AMD64_LEA_MEMBASE; @@ -3223,8 +3223,8 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) if ((ins->sreg1 == ins->sreg2) && (ins->sreg1 == ins->dreg)) { MonoInst *ins2; - /* - * Replace STORE_MEMBASE_IMM 0 with STORE_MEMBASE_REG since + /* + * Replace STORE_MEMBASE_IMM 0 with STORE_MEMBASE_REG since * the latter has length 2-3 instead of 6 (reverse constant * propagation). These instruction sequences are very common * in the initlocals bblock. @@ -3248,9 +3248,9 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_COMPARE_IMM: case OP_LCOMPARE_IMM: - /* OP_COMPARE_IMM (reg, 0) - * --> - * OP_AMD64_TEST_NULL (reg) + /* OP_COMPARE_IMM (reg, 0) + * --> + * OP_AMD64_TEST_NULL (reg) */ if (!ins->inst_imm) ins->opcode = OP_AMD64_TEST_NULL; @@ -3260,7 +3260,7 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) ins->opcode = OP_X86_TEST_NULL; break; case OP_AMD64_ICOMPARE_MEMBASE_IMM: - /* + /* * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_X86_COMPARE_MEMBASE_IMM offset(basereg), imm * --> @@ -3310,7 +3310,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) } case OP_LXOR: /* - * Use IXOR to avoid a rex prefix if possible. The cpu will sign extend the + * Use IXOR to avoid a rex prefix if possible. The cpu will sign extend the * 0 result into 64 bits. */ if ((ins->sreg1 == ins->sreg2) && (ins->sreg1 == ins->dreg)) { @@ -3321,8 +3321,8 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) if ((ins->sreg1 == ins->sreg2) && (ins->sreg1 == ins->dreg)) { MonoInst *ins2; - /* - * Replace STORE_MEMBASE_IMM 0 with STORE_MEMBASE_REG since + /* + * Replace STORE_MEMBASE_IMM 0 with STORE_MEMBASE_REG since * the latter has length 2-3 instead of 6 (reverse constant * propagation). These instruction sequences are very common * in the initlocals bblock. @@ -3649,7 +3649,7 @@ emit_simd_gt_un_op (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int typ case MONO_TYPE_U1: USE_MAX: { // dreg = max(sreg1, sreg2) != sreg2 - + int temp_reg1 = mono_alloc_ireg (cfg); int temp_reg2 = mono_alloc_ireg (cfg); int temp_reg3 = mono_alloc_ireg (cfg); @@ -3812,7 +3812,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *ins, *n, *temp; /* - * FIXME: Need to add more instructions, but the current machine + * FIXME: Need to add more instructions, but the current machine * description can't model some parts of the composite instructions like * cdq. */ @@ -4091,7 +4091,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) bb->max_vreg = cfg->next_vreg; } -static const int +static const int branch_cc_table [] = { X86_CC_EQ, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT, X86_CC_NE, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT, @@ -4197,19 +4197,19 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) amd64_push_reg (code, AMD64_RDI); offset += 8; } - + amd64_shift_reg_imm (code, X86_SHR, sreg, 3); if (sreg != AMD64_RCX) amd64_mov_reg_reg (code, AMD64_RCX, sreg, 8); amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX); - + amd64_lea_membase (code, AMD64_RDI, AMD64_RSP, offset); if (cfg->param_area) amd64_alu_reg_imm (code, X86_ADD, AMD64_RDI, cfg->param_area); amd64_cld (code); amd64_prefix (code, X86_REP_PREFIX); amd64_stosl (code); - + if (tree->dreg != AMD64_RDI && sreg != AMD64_RDI) amd64_pop_reg (code, AMD64_RDI); if (tree->dreg != AMD64_RCX && sreg != AMD64_RCX) @@ -4455,10 +4455,10 @@ mono_amd64_emit_tls_set (guint8 *code, int sreg, int tls_offset) static guint8* emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offset) { - /* + /* * The ip field is not set, the exception handling code will obtain it from the stack location pointed to by the sp field. */ - /* + /* * sp is saved right before calls but we need to save it here too so * async stack walks would work. */ @@ -4956,8 +4956,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_patch (label, code); } - /* - * This is the address which is saved in seq points, + /* + * This is the address which is saved in seq points, */ mono_add_seq_point (cfg, bb, ins, code - cfg->native_code); @@ -5056,7 +5056,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_LMUL_IMM: case OP_IMUL_IMM: { guint32 size = (ins->opcode == OP_IMUL_IMM) ? 4 : 8; - + switch (ins->inst_imm) { case 2: /* MOV r1, r2 */ @@ -5639,7 +5639,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Set argument registers */ for (i = 0; i < PARAM_REGS; ++i) amd64_mov_reg_membase (code, param_regs [i], AMD64_R11, MONO_STRUCT_OFFSET (DynCallArgs, regs) + (i * sizeof (target_mgreg_t)), sizeof (target_mgreg_t)); - + /* Make the call */ amd64_call_reg (code, AMD64_R10); @@ -5745,7 +5745,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) for (i = 0; i < size; i += 8) amd64_mov_membase_reg (code, AMD64_RSP, i, ins->dreg, 8); - amd64_mov_reg_reg (code, ins->dreg, AMD64_RSP, 8); + amd64_mov_reg_reg (code, ins->dreg, AMD64_RSP, 8); } else { amd64_mov_reg_imm (code, ins->dreg, size); ins->sreg1 = ins->dreg; @@ -5775,7 +5775,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ins->backend.pc_offset = code - cfg->native_code; break; } - case OP_CALL_HANDLER: + case OP_CALL_HANDLER: /* Align stack */ amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8); mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb); @@ -5830,13 +5830,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) //if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins) //break; if (ins->inst_target_bb->native_offset) { - amd64_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); + amd64_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); } else { mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); if (optimize_branch_pred && x86_is_imm8 (ins->inst_target_bb->max_offset - offset)) x86_jump8 (code, 0); - else + else x86_jump32 (code, 0); } break; @@ -5893,14 +5893,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_COND_EXC_NO: case OP_COND_EXC_C: case OP_COND_EXC_NC: - EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_EQ], + EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_EQ], (ins->opcode < OP_COND_EXC_NE_UN), (const char *)ins->inst_p1); break; case OP_COND_EXC_IOV: case OP_COND_EXC_INO: case OP_COND_EXC_IC: case OP_COND_EXC_INC: - EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_IEQ], + EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_IEQ], (ins->opcode < OP_COND_EXC_INE_UN), (const char *)ins->inst_p1); break; @@ -6008,12 +6008,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE); break; case OP_FCONV_TO_U4: - code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); + code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); break; case OP_FCONV_TO_I4: - case OP_FCONV_TO_I: code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE); break; + case OP_FCONV_TO_I: case OP_FCONV_TO_I8: code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, TRUE); break; @@ -6053,7 +6053,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_sse_movss_reg_reg (code, ins->dreg, ins->sreg1); break; - case OP_LCONV_TO_R_UN: { + case OP_LCONV_TO_R_UN: { guint8 *br [2]; /* Based on gcc code */ @@ -6124,13 +6124,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: amd64_sse_subsd_reg_reg (code, ins->dreg, ins->sreg2); - break; + break; case OP_FMUL: amd64_sse_mulsd_reg_reg (code, ins->dreg, ins->sreg2); - break; + break; case OP_FDIV: amd64_sse_divsd_reg_reg (code, ins->dreg, ins->sreg2); - break; + break; case OP_FNEG: { static double r8_0 = -0.0; @@ -6244,11 +6244,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (ins->dreg == ins->sreg1); amd64_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2); amd64_cmov_reg (code, X86_CC_LT, FALSE, ins->dreg, ins->sreg2); - break; + break; case OP_X86_FPOP: - break; + break; case OP_FCOMPARE: - /* + /* * The two arguments are swapped because the fbranch instructions * depend on this for the non-sse case to work. */ @@ -6264,7 +6264,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FCNEQ: case OP_FCEQ: { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ guchar *unordered_check; @@ -6290,7 +6290,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } case OP_FCLT: case OP_FCLT_UN: { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ amd64_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg); @@ -6322,7 +6322,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } case OP_FCGT: case OP_FCGT_UN: { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ guchar *unordered_check; @@ -6576,7 +6576,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, size); /* dreg contains the old value, add with sreg2 value */ amd64_alu_reg_reg_size (code, X86_ADD, dreg, ins->sreg2, size); - + if (ins->dreg != dreg) amd64_mov_reg_reg (code, ins->dreg, dreg, size); @@ -6601,7 +6601,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) else size = 4; - /* + /* * See http://msdn.microsoft.com/en-us/magazine/cc302329.aspx for * an explanation of how this works. */ @@ -6970,7 +6970,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PMAXD_UN: amd64_sse_pmaxud_reg_reg (code, ins->sreg1, ins->sreg2); break; - + case OP_PMAXB: amd64_sse_pmaxsb_reg_reg (code, ins->sreg1, ins->sreg2); break; @@ -7114,7 +7114,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PSUBW_SAT: amd64_sse_psubsw_reg_reg (code, ins->sreg1, ins->sreg2); break; - + case OP_PMULW: amd64_sse_pmullw_reg_reg (code, ins->sreg1, ins->sreg2); break; @@ -7179,22 +7179,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PSHRQ_REG: amd64_sse_psrlq_reg_reg (code, ins->dreg, ins->sreg2); break; - + /*TODO: This is appart of the sse spec but not added case OP_PSARQ: amd64_sse_psraq_reg_imm (code, ins->dreg, ins->inst_imm); break; case OP_PSARQ_REG: amd64_sse_psraq_reg_reg (code, ins->dreg, ins->sreg2); - break; + break; */ - + case OP_PSHLQ: amd64_sse_psllq_reg_imm (code, ins->dreg, ins->inst_imm); break; case OP_PSHLQ_REG: amd64_sse_psllq_reg_reg (code, ins->dreg, ins->sreg2); - break; + break; case OP_CVTDQ2PD: amd64_sse_cvtdq2pd_reg_reg (code, ins->dreg, ins->sreg1); break; @@ -7350,7 +7350,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /*FIXME the peephole pass should have killed this*/ if (ins->dreg != ins->sreg1) amd64_sse_movaps_reg_reg (code, ins->dreg, ins->sreg1); - break; + break; case OP_XZERO: amd64_sse_pxor_reg_reg (code, ins->dreg, ins->dreg); break; @@ -7382,7 +7382,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCONV_TO_U2: amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE); break; - } + } break; case OP_EXPAND_I2: @@ -7544,7 +7544,7 @@ static int get_max_epilog_size (MonoCompile *cfg) { int max_epilog_size = 16; - + if (cfg->method->save_lmf) max_epilog_size += 256; @@ -7625,7 +7625,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* Offset between RSP and the CFA */ cfa_offset = 0; - /* + /* * The prolog consists of the following parts: * FP present: * - push rbp @@ -7674,7 +7674,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) } if (cfg->arch.omit_fp) { - /* + /* * On enter, the stack is misaligned by the pushing of the return * address. It is either made aligned by the pushing of %rbp, or by * this. @@ -7778,7 +7778,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (mini_debug_options.init_stacks) { /* Fill the stack frame with a dummy value to force deterministic behavior */ - + /* Save registers to the red zone */ amd64_mov_membase_reg (code, AMD64_RSP, -8, AMD64_RDI, 8); amd64_mov_membase_reg (code, AMD64_RSP, -16, AMD64_RCX, 8); @@ -7860,7 +7860,7 @@ MONO_RESTORE_WARNING /* Take prolog and epilog instrumentation into account */ if (bb == cfg->bb_entry || bb == cfg->bb_exit) max_length += max_epilog_size; - + bb->max_length = max_length; } } @@ -8112,7 +8112,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) mono_emit_unwind_op_remember_state (cfg, code); /* the code restoring the registers must be kept in sync with OP_TAILCALL */ - + if (method->save_lmf) { if (cfg->used_int_regs & (1 << AMD64_RBP)) amd64_mov_reg_membase (code, AMD64_RBP, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), 8); @@ -8368,7 +8368,7 @@ mono_arch_flush_register_windows (void) { } -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return amd64_use_imm32 (imm); @@ -8897,7 +8897,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho } else if (strcmp (cmethod->name, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8) { opcode = OP_ABS; } - + if (opcode && fsig->param_count == 1) { MONO_INST_NEW (cfg, ins, opcode); ins->type = STACK_R8; @@ -8928,7 +8928,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho opcode = OP_LMAX_UN; } } - + if (opcode && fsig->param_count == 2) { MONO_INST_NEW (cfg, ins, opcode); ins->type = fsig->params [0]->type == MONO_TYPE_I4 ? STACK_I4 : STACK_I8; @@ -9086,7 +9086,7 @@ mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) { g_assert_not_reached (); } - + /* * mono_arch_start_single_stepping: * @@ -9097,7 +9097,7 @@ mono_arch_start_single_stepping (void) { ss_trampoline = mini_get_single_step_trampoline (); } - + /* * mono_arch_stop_single_stepping: * diff --git a/src/mono/mono/mini/mini-arch.h b/src/mono/mono/mini/mini-arch.h index da89dbb0439e1..5a4c89f0bf868 100644 --- a/src/mono/mono/mini/mini-arch.h +++ b/src/mono/mono/mini/mini-arch.h @@ -39,4 +39,4 @@ #define MONO_ARCH_LOCALLOC_ALIGNMENT MONO_ARCH_FRAME_ALIGNMENT #endif -#endif /* __MONO_MINI_ARCH_H__ */ +#endif /* __MONO_MINI_ARCH_H__ */ diff --git a/src/mono/mono/mini/mini-arm.c b/src/mono/mono/mini/mini-arm.c index 3f3b4a9bc88b3..69360a1946d64 100644 --- a/src/mono/mono/mini/mini-arm.c +++ b/src/mono/mono/mini/mini-arm.c @@ -89,7 +89,7 @@ static gboolean thumb2_supported = FALSE; */ static gboolean eabi_supported = FALSE; -/* +/* * Whenever to use the iphone ABI extensions: * http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/index.html * Basically, r7 is used as a frame pointer and it should point to the saved r7 + lr. @@ -577,7 +577,7 @@ emit_restore_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset) * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the activation frame. */ @@ -605,12 +605,12 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit arg_info [0].size = frame_size; for (k = 0; k < param_count; k++) { - size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke); + size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke && !csig->marshalling_disabled); /* ignore alignment for now */ align = 1; - frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); + frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); arg_info [k].pad = pad; frame_size += size; arg_info [k + 1].pad = 0; @@ -1012,7 +1012,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) mono_arch_compute_omit_fp (cfg); - /* + /* * FIXME: Interface calls might go through a static rgctx trampoline which * sets V5, but it doesn't save it, so we need to save it ourselves, and * avoid using it. @@ -1042,7 +1042,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -1333,7 +1333,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) cinfo->ret.nregs = nfields; cinfo->ret.esize = esize; } else { - if (is_pinvoke) { + if (sig->pinvoke && !sig->marshalling_disabled) { int native_size = mono_class_native_size (mono_class_from_mono_type_internal (t), &align); int max_size; @@ -1496,7 +1496,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) align = sizeof (target_mgreg_t); } else { MonoClass *klass = mono_class_from_mono_type_internal (sig->params [i]); - if (is_pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (klass, &align); else size = mini_type_stack_size_full (t, &align, FALSE); @@ -1888,7 +1888,7 @@ mono_arch_compute_omit_fp (MonoCompile *cfg) ArgInfo *ainfo = &cinfo->args [i]; if (ainfo->storage == RegTypeBase || ainfo->storage == RegTypeBaseGen || ainfo->storage == RegTypeStructByVal) { - /* + /* * The stack offset can only be determined when the frame * size is known. */ @@ -1963,7 +1963,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) } } /* local vars are at a positive offset from the stack pointer */ - /* + /* * also note that if the function uses alloca, we use FP * to point at the local variables. */ @@ -2147,7 +2147,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) offset &= ~(align - 1); cfg->sig_cookie = offset; offset += size; - } + } for (i = 0; i < sig->param_count; ++i) { ainfo = cinfo->args + i; @@ -2173,7 +2173,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (ins->opcode != OP_REGVAR) { ins->opcode = OP_REGOFFSET; ins->inst_basereg = cfg->frame_reg; - size = mini_type_stack_size_full (sig->params [i], &ualign, sig->pinvoke); + size = mini_type_stack_size_full (sig->params [i], &ualign, sig->pinvoke && !sig->marshalling_disabled); align = ualign; /* FIXME: if a structure is misaligned, our memcpy doesn't work, * since it loads/stores misaligned words, which don't do the right thing. @@ -2273,11 +2273,11 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) NOT_IMPLEMENTED; g_assert (cinfo->sig_cookie.storage == RegTypeBase); - + /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup (call->signature); @@ -2309,7 +2309,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) /* * LLVM always uses the native ABI while we use our own ABI, the * only difference is the handling of vtypes: - * - we only pass/receive them in registers in some cases, and only + * - we only pass/receive them in registers in some cases, and only * in 1 or 2 integer registers. */ switch (cinfo->ret.storage) { @@ -2404,7 +2404,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) sig = call->signature; n = sig->param_count + sig->hasthis; - + cinfo = get_call_info (cfg->mempool, sig); switch (cinfo->ret.storage) { @@ -2813,7 +2813,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) #endif /* #ifndef DISABLE_JIT */ -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return TRUE; @@ -2920,7 +2920,7 @@ mono_arch_dyn_call_prepare (MonoMethodSignature *sig) info->param_types = g_new0 (MonoType*, sig->param_count); for (i = 0; i < sig->param_count; ++i) info->param_types [i] = mini_get_underlying_type (sig->params [i]); - + return (MonoDynCallInfo*)info; } @@ -3186,7 +3186,7 @@ if (0 && ins->inst_true_bb->native_offset) { \ mono_add_patch_info (cfg, code - cfg->native_code, \ MONO_PATCH_INFO_EXC, exc_name); \ ARM_BL_COND (code, (condcode), 0); \ - } while (0); + } while (0); #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) EMIT_COND_SYSTEM_EXCEPTION_FLAGS(branch_cc_table [(cond)], (exc_name)) @@ -3204,17 +3204,17 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *last_ins = mono_inst_prev (ins, FILTER_IL_SEQ_POINT); switch (ins->opcode) { - case OP_MUL_IMM: - case OP_IMUL_IMM: + case OP_MUL_IMM: + case OP_IMUL_IMM: /* Already done by an arch-independent pass */ break; case OP_LOAD_MEMBASE: case OP_LOADI4_MEMBASE: - /* - * OP_STORE_MEMBASE_REG reg, offset(basereg) + /* + * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg */ - if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG + if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG || last_ins->opcode == OP_STORE_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { @@ -3227,7 +3227,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->sreg1 = last_ins->sreg1; } - /* + /* * Note: reg1 must be different from the basereg in the second load * OP_LOAD_MEMBASE offset(basereg), reg1 * OP_LOAD_MEMBASE offset(basereg), reg2 @@ -3252,11 +3252,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) //g_assert_not_reached (); #if 0 - /* - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + /* + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg * --> - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_ICONST reg, imm */ } else if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM @@ -3276,7 +3276,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_ICONV_TO_I1 : OP_ICONV_TO_U1; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; case OP_LOADU2_MEMBASE: @@ -3285,20 +3285,20 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_ICONV_TO_I2 : OP_ICONV_TO_U2; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; case OP_MOVE: ins->opcode = OP_MOVE; - /* - * OP_MOVE reg, reg + /* + * OP_MOVE reg, reg */ if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); continue; } - /* - * OP_MOVE sreg, dreg + /* + * OP_MOVE sreg, dreg * OP_MOVE dreg, sreg */ if (last_ins && last_ins->opcode == OP_MOVE && @@ -3312,7 +3312,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) } } -/* +/* * the branch_cc_table should maintain the order of these * opcodes. case CEE_BEQ: @@ -3326,17 +3326,17 @@ case CEE_BGT_UN: case CEE_BLE_UN: case CEE_BLT_UN: */ -static const guchar +static const guchar branch_cc_table [] = { - ARMCOND_EQ, - ARMCOND_GE, - ARMCOND_GT, + ARMCOND_EQ, + ARMCOND_GE, + ARMCOND_GT, ARMCOND_LE, - ARMCOND_LT, - - ARMCOND_NE, - ARMCOND_HS, - ARMCOND_HI, + ARMCOND_LT, + + ARMCOND_NE, + ARMCOND_HS, + ARMCOND_HI, ARMCOND_LS, ARMCOND_LO }; @@ -3902,7 +3902,7 @@ arm_patch_general (MonoCompile *cfg, guchar *code, const guchar *target) return; } } - + handle_thunk (cfg, code, target); return; } @@ -3930,7 +3930,7 @@ arm_patch_general (MonoCompile *cfg, guchar *code, const guchar *target) * address constant // execution never reaches here */ if ((ins & 0x0ffffff0) == 0x12fff10) { - /* Branch and exchange: the address is constructed in a reg + /* Branch and exchange: the address is constructed in a reg * We can patch BX when the code sequence is the following: * ldr ip, [pc, #0] ; 0x8 * b 0xc @@ -4009,7 +4009,7 @@ arm_patch (guchar *code, const guchar *target) arm_patch_general (NULL, code, target); } -/* +/* * Return the >= 0 uimm8 value if val can be represented with a byte + rotation * (with the rotation amount in *rot_amount. rot_amount is already adjusted * to be used with the emit macros. @@ -4562,8 +4562,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BREAK: /* - * gdb does not like encountering the hw breakpoint ins in the debugged code. - * So instead of emitting a trap, we emit a call a C function and place a + * gdb does not like encountering the hw breakpoint ins in the debugged code. + * So instead of emitting a trap, we emit a call a C function and place a * breakpoint there. */ //*(int*)code = 0xef9f0001; @@ -4697,7 +4697,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) */ ARM_NOP (code); } else { - /* + /* * A placeholder for a possible breakpoint inserted by * mono_arch_set_breakpoint (). */ @@ -5308,7 +5308,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Save result */ ARM_LDR_IMM (code, ARMREG_IP, var->inst_basereg, var->inst_offset); - ARM_STR_IMM (code, ARMREG_R0, ARMREG_IP, MONO_STRUCT_OFFSET (DynCallArgs, res)); + ARM_STR_IMM (code, ARMREG_R0, ARMREG_IP, MONO_STRUCT_OFFSET (DynCallArgs, res)); ARM_STR_IMM (code, ARMREG_R1, ARMREG_IP, MONO_STRUCT_OFFSET (DynCallArgs, res2)); if (IS_HARD_FLOAT) ARM_FSTD (code, ARM_VFP_D0, ARMREG_IP, MONO_STRUCT_OFFSET (DynCallArgs, fpregs)); @@ -5405,7 +5405,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_IP); break; } - case OP_CALL_HANDLER: + case OP_CALL_HANDLER: mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb); code = mono_arm_patchable_bl (code, ARMCOND_AL); cfg->thunk_area += THUNK_SIZE; @@ -5423,17 +5423,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_BR: /*if (ins->inst_target_bb->native_offset) { ARM_B (code, 0); - //x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); + //x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); } else*/ { mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); code = mono_arm_patchable_b (code, ARMCOND_AL); - } + } break; case OP_BR_REG: ARM_MOV_REG_REG (code, ARMREG_PC, ins->sreg1); break; case OP_SWITCH: - /* + /* * In the normal case we have: * ldr pc, [pc, ins->sreg1 << 2] * nop @@ -5558,7 +5558,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) *(guint32*)code = ((guint32*)(ins->inst_p0))[1]; code += 4; } else { - /* FIXME: we can optimize the imm load by dealing with part of + /* FIXME: we can optimize the imm load by dealing with part of * the displacement in LDFD (aligning to 512). */ code = mono_arm_emit_load_imm (code, ARMREG_LR, (guint32)(gsize)ins->inst_p0); @@ -5700,7 +5700,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_LCONV_TO_OVF_I4_2: { guint8 *high_bit_not_set, *valid_negative, *invalid_negative, *valid_positive; - /* + /* * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */ @@ -5713,7 +5713,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ARM_B_COND (code, ARMCOND_EQ, 0); /*branch if upper part == 0xFFFFFFFF (lower part has bit 31 set) */ invalid_negative = code; ARM_B_COND (code, ARMCOND_AL, 0); - + arm_patch (high_bit_not_set, code); ARM_CMP_REG_IMM8 (code, ins->sreg2, 0); @@ -5735,13 +5735,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: ARM_VFP_SUBD (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FMUL: ARM_VFP_MULD (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FDIV: ARM_VFP_DIVD (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FNEG: ARM_NEGD (code, ins->dreg, ins->sreg1); break; @@ -5925,13 +5925,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_RSUB: ARM_VFP_SUBS (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_RMUL: ARM_VFP_MULS (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_RDIV: ARM_VFP_DIVS (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_RNEG: ARM_NEGS (code, ins->dreg, ins->sreg1); break; @@ -6050,7 +6050,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } - + cpos += max_len; last_ins = ins; @@ -6141,7 +6141,7 @@ mono_arm_unaligned_stack (MonoMethod *method) /* * Stack frame layout: - * + * * ------------------- fp * MonoLMF structure or saved registers * ------------------- @@ -6176,7 +6176,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) prev_sp_offset = 0; if (iphone_abi) { - /* + /* * The iphone uses R7 as the frame pointer, and it points at the saved * r7+lr: * @@ -6340,7 +6340,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = cinfo->args + i; inst = cfg->args [i]; - + if (cfg->verbose_level > 2) g_print ("Saving argument %d (type: %d)\n", i, ainfo->storage); @@ -6521,7 +6521,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) int soffset = 0; int cur_reg; int size = 0; - size = mini_type_stack_size_full (inst->inst_vtype, NULL, sig->pinvoke); + size = mini_type_stack_size_full (inst->inst_vtype, NULL, sig->pinvoke && !sig->marshalling_disabled); for (cur_reg = 0; cur_reg < ainfo->size; ++cur_reg) { if (arm_is_imm12 (doffset)) { ARM_STR_IMM (code, ainfo->reg + cur_reg, inst->inst_basereg, doffset); @@ -6716,7 +6716,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) } mono_emit_unwind_op_def_cfa (cfg, code, ARMREG_SP, ((iphone_abi ? 3 : 0) + nused_int_regs) * 4); /* restore iregs */ - ARM_POP (code, regmask); + ARM_POP (code, regmask); if (iphone_abi) { for (i = 0; i < 16; i++) { if (regmask & (1 << i)) @@ -6790,8 +6790,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg) } /* count the number of exception infos */ - - /* + + /* * make sure we have enough space for exceptions */ for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { @@ -7055,14 +7055,14 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entri ARM_STR_IMM (code, ARMREG_R1, ARMREG_SP, 3 * sizeof (target_mgreg_t)); /* Restore registers and branch */ ARM_POP4 (code, ARMREG_R0, ARMREG_R1, ARMREG_IP, ARMREG_PC); - + code = arm_emit_value_and_patch_ldr (code, target_code_ins, (gsize)item->value.target_code); } else { vtable_offset = DISTANCE (vtable, &vtable->vtable[item->value.vtable_slot]); if (!arm_is_imm12 (vtable_offset)) { - /* + /* * We need to branch to a computed address but we don't have - * a free register to store it, since IP must contain the + * a free register to store it, since IP must contain the * vtable address. So we push the two values to the stack, and * load them both using LDM. */ @@ -7074,7 +7074,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entri ARM_STR_IMM (code, ARMREG_R1, ARMREG_SP, 3 * sizeof (target_mgreg_t)); /* Restore registers and branch */ ARM_POP4 (code, ARMREG_R0, ARMREG_R1, ARMREG_IP, ARMREG_PC); - + code = arm_emit_value_and_patch_ldr (code, vtable_offset_ins, vtable_offset); } else { ARM_POP2 (code, ARMREG_R0, ARMREG_R1); @@ -7097,7 +7097,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entri ARM_STR_IMM (code, ARMREG_R1, ARMREG_SP, 3 * sizeof (target_mgreg_t)); /* Restore registers and branch */ ARM_POP4 (code, ARMREG_R0, ARMREG_R1, ARMREG_IP, ARMREG_PC); - + code = arm_emit_value_and_patch_ldr (code, target_code_ins, (gsize)fail_tramp); item->jmp_code = NULL; } @@ -7233,7 +7233,7 @@ mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip) mono_arch_flush_icache (code - 16, 16); #if 0 - /* This is currently implemented by emitting an SWI instruction, which + /* This is currently implemented by emitting an SWI instruction, which * qemu/linux seems to convert to a SIGILL. */ *(int*)code = (0xef << 24) | 8; @@ -7275,7 +7275,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) mono_arch_flush_icache (ip, code - ip); } } - + /* * mono_arch_start_single_stepping: * @@ -7289,7 +7289,7 @@ mono_arch_start_single_stepping (void) else single_step_tramp = mini_get_single_step_trampoline (); } - + /* * mono_arch_stop_single_stepping: * diff --git a/src/mono/mono/mini/mini-arm.h b/src/mono/mono/mini/mini-arm.h index f53c35cad848d..12581b13992b3 100644 --- a/src/mono/mono/mini/mini-arm.h +++ b/src/mono/mono/mini/mini-arm.h @@ -119,7 +119,7 @@ #define MONO_ARCH_FRAME_ALIGNMENT 8 #endif -/* fixme: align to 16byte instead of 32byte (we align to 32byte to get +/* fixme: align to 16byte instead of 32byte (we align to 32byte to get * reproduceable results for benchmarks */ #define MONO_ARCH_CODE_ALIGNMENT 32 @@ -273,7 +273,7 @@ typedef enum { /* keep the size of the structure a multiple of 8 */ struct MonoLMF { - /* + /* * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and * the other fields are not valid. */ diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index b93b4aa6a8567..28b97fac4786a 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -3,7 +3,7 @@ * ARM64 backend for the Mono code generator * * Copyright 2013 Xamarin, Inc (http://www.xamarin.com) - * + * * Based on mini-arm.c: * * Authors: @@ -1738,7 +1738,7 @@ mono_arch_dyn_call_prepare (MonoMethodSignature *sig) break; } } - + return (MonoDynCallInfo*)info; } @@ -2104,7 +2104,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; - if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || + if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) continue; @@ -2587,11 +2587,11 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) NOT_IMPLEMENTED; g_assert (cinfo->sig_cookie.storage == ArgOnStack); - + /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup (call->signature); @@ -2876,7 +2876,7 @@ mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, #endif -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return (imm >= -((gint64)1<<31) && imm <= (((gint64)1<<31)-1)); @@ -3314,8 +3314,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BREAK: /* - * gdb does not like encountering the hw breakpoint ins in the debugged code. - * So instead of emitting a trap, we emit a call a C function and place a + * gdb does not like encountering the hw breakpoint ins in the debugged code. + * So instead of emitting a trap, we emit a call a C function and place a * breakpoint there. */ code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break)); @@ -3428,7 +3428,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (var->opcode == OP_REGOFFSET); /* Load the address of the bp trampoline into IP0 */ arm_ldrx (code, ARMREG_IP0, var->inst_basereg, var->inst_offset); - /* + /* * A placeholder for a possible breakpoint inserted by * mono_arch_set_breakpoint (). */ @@ -4226,7 +4226,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) arm_uxthw (code, dreg, dreg); break; case OP_FCONV_TO_I4: - case OP_FCONV_TO_I: arm_fcvtzs_dx (code, dreg, sreg1); arm_sxtwx (code, dreg, dreg); break; @@ -4234,6 +4233,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) arm_fcvtzu_dx (code, dreg, sreg1); break; case OP_FCONV_TO_I8: + case OP_FCONV_TO_I: arm_fcvtzs_dx (code, dreg, sreg1); break; case OP_FCONV_TO_U8: @@ -5148,12 +5148,12 @@ mono_arch_emit_prolog (MonoCompile *cfg) g_assert (ins->opcode == OP_REGOFFSET); - code = emit_strx (code, MONO_ARCH_RGCTX_REG, ins->inst_basereg, ins->inst_offset); + code = emit_strx (code, MONO_ARCH_RGCTX_REG, ins->inst_basereg, ins->inst_offset); mono_add_var_location (cfg, cfg->rgctx_var, TRUE, MONO_ARCH_RGCTX_REG, 0, 0, code - cfg->native_code); mono_add_var_location (cfg, cfg->rgctx_var, FALSE, ins->inst_basereg, ins->inst_offset, code - cfg->native_code, 0); } - + /* * Move arguments to their registers/stack locations. */ diff --git a/src/mono/mono/mini/mini-arm64.h b/src/mono/mono/mini/mini-arm64.h index 7555c5e7854f0..8feacf8f81e49 100644 --- a/src/mono/mono/mini/mini-arm64.h +++ b/src/mono/mono/mini/mini-arm64.h @@ -82,7 +82,7 @@ #define MONO_ARCH_LMF_REG_SP 11 struct MonoLMF { - /* + /* * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and * the other fields are not valid. */ diff --git a/src/mono/mono/mini/mini-codegen.c b/src/mono/mono/mini/mini-codegen.c index 77464dcf88cbb..171520d2818c1 100644 --- a/src/mono/mono/mini/mini-codegen.c +++ b/src/mono/mono/mini/mini-codegen.c @@ -69,9 +69,9 @@ static int translate_bank (MonoRegState *rs, int bank, int hreg) { } /* - * Every hardware register belongs to a register type or register bank. bank 0 + * Every hardware register belongs to a register type or register bank. bank 0 * contains the int registers, bank 1 contains the fp registers. - * int registers are used 99% of the time, so they are special cased in a lot of + * int registers are used 99% of the time, so they are special cased in a lot of * places. */ @@ -83,7 +83,7 @@ static const int regbank_size [] = { MONO_MAX_XREGS }; -static const int regbank_load_ops [] = { +static const int regbank_load_ops [] = { OP_LOADR_MEMBASE, OP_LOADR8_MEMBASE, OP_LOADR_MEMBASE, @@ -91,7 +91,7 @@ static const int regbank_load_ops [] = { OP_LOADX_MEMBASE }; -static const int regbank_store_ops [] = { +static const int regbank_store_ops [] = { OP_STORER_MEMBASE_REG, OP_STORER8_MEMBASE_REG, OP_STORER_MEMBASE_REG, @@ -99,7 +99,7 @@ static const int regbank_store_ops [] = { OP_STOREX_MEMBASE }; -static const int regbank_move_ops [] = { +static const int regbank_move_ops [] = { OP_MOVE, OP_FMOVE, OP_MOVE, @@ -315,7 +315,7 @@ resize_spill_info (MonoCompile *cfg, int bank) /* * returns the offset used by spillvar. It allocates a new - * spill variable if necessary. + * spill variable if necessary. */ static int mono_spillvar_offset (MonoCompile *cfg, int spillvar, int bank) @@ -381,7 +381,7 @@ mono_spillvar_offset (MonoCompile *cfg, int spillvar, int bank) #define sreg1_is_fp(spec) sreg_is_fp (0,(spec)) #define sreg2_is_fp(spec) sreg_is_fp (1,(spec)) -#define reg_is_simd(desc) ((desc) == 'x') +#define reg_is_simd(desc) ((desc) == 'x') #ifdef MONO_ARCH_NEED_SIMD_BANK @@ -612,7 +612,7 @@ mono_print_ins_index_strbuf (int i, MonoInst *ins) if (ins->opcode == OP_VCALL || ins->opcode == OP_VCALL_REG || ins->opcode == OP_VCALL_MEMBASE) { /* - * These are lowered opcodes, but they are in the .md files since the old + * These are lowered opcodes, but they are in the .md files since the old * JIT passes them to backends. */ if (ins->dreg != -1) @@ -744,7 +744,7 @@ print_regtrack (RegTrack *t, int num) int i; char buf [32]; const char *r; - + for (i = 0; i < num; ++i) { if (!t [i].born_in) continue; @@ -804,7 +804,7 @@ get_vreg_bank (MonoCompile *cfg, int reg, int bank) } /* - * Force the spilling of the variable in the symbolic register 'reg', and free + * Force the spilling of the variable in the symbolic register 'reg', and free * the hreg it was assigned to. */ static void @@ -923,7 +923,7 @@ get_register_spilling (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **last, Mo else i = mono_regstate_alloc_int (rs, regmask (sel)); g_assert (i == sel); - + return sel; } @@ -983,7 +983,7 @@ static void create_spilled_store (MonoCompile *cfg, MonoBasicBlock *bb, int spill, int reg, int prev_reg, MonoInst **last, MonoInst *ins, MonoInst *insert_before, int bank) { MonoInst *store, *def; - + bank = get_vreg_bank (cfg, prev_reg, bank); MONO_INST_NEW (cfg, store, regbank_store_ops [bank]); @@ -1120,7 +1120,7 @@ static gboolean desc_to_fixed_reg_inited = FALSE; * Local register allocation. * We first scan the list of instructions and we save the liveness info of * each register (when the register is first used, when it's value is set etc.). - * We also reverse the list of instructions because assigning registers backwards allows + * We also reverse the list of instructions because assigning registers backwards allows * for more tricks to be used. */ void @@ -1187,7 +1187,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) cfg->reginfo_len = MAX (1024, max * 2); reginfo = (RegTrack *)mono_mempool_alloc (cfg->mempool, sizeof (RegTrack) * cfg->reginfo_len); cfg->reginfo = reginfo; - } + } else g_assert (cfg->reginfo_len >= rs->next_vreg); @@ -1196,9 +1196,9 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) memset (cfg->reginfo, 0, cfg->reginfo_len * sizeof (RegTrack)); } - /* + /* * For large methods, next_vreg can be very large, so g_malloc0 time can - * be prohibitive. So we manually init the reginfo entries used by the + * be prohibitive. So we manually init the reginfo entries used by the * bblock. */ for (ins = bb->code; ins; ins = ins->next) { @@ -1212,7 +1212,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST])) { /** * In the new IR, the two vregs of the regpair do not alias the - * original long vreg. shift the vreg here so the rest of the + * original long vreg. shift the vreg here so the rest of the * allocator doesn't have to care about it. */ ins->dreg ++; @@ -1252,7 +1252,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (G_UNLIKELY (spec == (gpointer)/*FIXME*/MONO_ARCH_CPU_SPEC)) { g_error ("Opcode '%s' missing from machine description file.", mono_inst_name (ins->opcode)); } - + DEBUG (mono_print_ins_index (i, ins)); num_sregs = mono_inst_get_src_registers (ins, sregs); @@ -1416,7 +1416,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) for (k = 0; k < num_sregs; ++k) { if (k != j) sreg_masks [k] &= ~ (regmask (dest_sreg)); - } + } /* * Spill sreg1/2 if they are assigned to dest_sreg. @@ -1466,9 +1466,9 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (k != j) sreg_masks [k] &= ~ (regmask (dest_sreg)); } - /* + /* * Prevent the dreg from being allocated to dest_sreg - * too, since it could force sreg1 to be allocated to + * too, since it could force sreg1 to be allocated to * the same reg on x86. */ dreg_mask &= ~ (regmask (dest_sreg)); @@ -1485,7 +1485,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) sreg_masks [k] &= ~ (regmask (dest_sreg)); } - /* + /* * First check if dreg is assigned to dest_sreg2, since we * can't spill a dreg. */ @@ -1494,9 +1494,9 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) else val = -1; if (val == dest_sreg && ins->dreg != sreg) { - /* - * the destination register is already assigned to - * dest_sreg2: we need to allocate another register for it + /* + * the destination register is already assigned to + * dest_sreg2: we need to allocate another register for it * and then copy from this to dest_sreg2. */ int new_dest; @@ -1527,7 +1527,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* sreg2 already assigned to another register */ /* * We couldn't emit a copy from val to dest_sreg2, because - * val might be spilled later while processing this + * val might be spilled later while processing this * instruction. So we spill sreg2 so it can be allocated to * dest_sreg2. */ @@ -1564,7 +1564,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } if (spec_dest == 'b') { - /* + /* * The dest reg is read by the instruction, not written, so * avoid allocating sreg1/sreg2 to the same reg. */ @@ -1607,7 +1607,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (dreg_fixed_mask) { g_assert (!bank); if (is_global_ireg (ins->dreg)) { - /* + /* * The argument is already in a hard reg, but that reg is * not usable by this instruction, so allocate a new one. */ @@ -1678,7 +1678,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) mono_regstate_free_int (rs, rs->vassign [reg2]); } - } + } DEBUG (printf ("\tassigned dreg-high %s to dest R%d\n", mono_arch_regname (val), reg2)); assign_reg (cfg, rs, reg2, val, bank); @@ -1693,7 +1693,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } if (prev_dreg >= 0 && is_soft_reg (prev_dreg, bank) && (spec_dest != 'b')) { - /* + /* * In theory, we could free up the hreg even if the vreg is alive, * but branches inside bblocks force us to assign the same hreg * to a vreg every time it is encountered. @@ -1728,7 +1728,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } if (spec_dest == 'b') { - /* + /* * The dest reg is read by the instruction, not written, so * avoid allocating sreg1/sreg2 to the same reg. */ @@ -1818,13 +1818,13 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) MonoCallInst *call = (MonoCallInst*)ins; GSList *list; - /* + /* * This needs to be done before assigning sreg1, so sreg1 will * not be assigned one of the argument regs. */ - /* - * Assign all registers in call->out_reg_args to the proper + /* + * Assign all registers in call->out_reg_args to the proper * argument registers. */ @@ -1910,7 +1910,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (sreg_fixed_masks [0]) { g_assert (!bank); if (is_global_ireg (sregs [0])) { - /* + /* * The argument is already in a hard reg, but that reg is * not usable by this instruction, so allocate a new one. */ @@ -1951,8 +1951,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } if ((ins->opcode == OP_MOVE) && !spill && !bank && is_local_ireg (ins->dreg) && (rs->ifree_mask & (regmask (ins->dreg)))) { - /* - * Allocate the same hreg to sreg1 as well so the + /* + * Allocate the same hreg to sreg1 as well so the * peephole can get rid of the move. */ sreg_masks [0] = regmask (ins->dreg); @@ -1981,7 +1981,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) sreg_masks [j] &= ~(regmask (dest_sregs [0])); val = dest_sregs [0]; } - + sregs [0] = val; } else { @@ -2029,7 +2029,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) mono_regstate_free_int (rs, rs->vassign [reg2]); #endif } - } + } sreg1_high = val; DEBUG (printf ("\tassigned sreg1 hreg %s to dest R%d\n", mono_arch_regname (val), reg2)); @@ -2043,7 +2043,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) int bank = reg_bank (spec_src1); if (ins->dreg == sregs [1]) { - /* + /* * copying sreg1 to dreg could clobber sreg2, so allocate a new * register for it. */ @@ -2065,7 +2065,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* FIXME: */ g_assert_not_reached (); - /* + /* * sreg1 and dest are already allocated to the same regpair by the * SREG1 allocation code. */ @@ -2176,7 +2176,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) DEBUG (printf ("freeable %s\n", mono_arch_regname (ins->sreg2))); mono_regstate_free_int (rs, ins->sreg2); }*/ - + DEBUG (mono_print_ins_index (i, ins)); } @@ -2222,7 +2222,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (sp - 1 - i > 0) { /* First move it to %st(0) */ DEBUG (printf ("\tswap %%st(0) and %%st(%d)\n", sp - 1 - i)); - + MONO_INST_NEW (cfg, fxch, OP_X86_FXCH); fxch->inst_imm = sp - 1 - i; @@ -2233,10 +2233,10 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) fpstack [sp - 1] = fpstack [i]; fpstack [i] = tmp; } - + /* Then move it to %st(1) */ DEBUG (printf ("\tswap %%st(0) and %%st(1)\n")); - + MONO_INST_NEW (cfg, fxch, OP_X86_FXCH); fxch->inst_imm = 1; @@ -2319,7 +2319,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (sp && bb != cfg->bb_exit && !(bb->out_count == 1 && bb->out_bb [0] == cfg->bb_exit)) { /* Remove remaining items from the fp stack */ - /* + /* * These can remain for example as a result of a dead fmove like in * System.Collections.Generic.EqualityComparer.Equals (). */ @@ -2534,7 +2534,7 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) MonoInst *last_ins = mono_inst_prev (ins, filter); switch (ins->opcode) { - case OP_MUL_IMM: + case OP_MUL_IMM: /* remove unnecessary multiplication with 1 */ if (ins->inst_imm == 1) { if (ins->dreg != ins->sreg1) @@ -2545,10 +2545,10 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) break; case OP_LOAD_MEMBASE: case OP_LOADI4_MEMBASE: - /* + /* * Note: if reg1 = reg2 the load op is removed * - * OP_STORE_MEMBASE_REG reg1, offset(basereg) + * OP_STORE_MEMBASE_REG reg1, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg2 * --> * OP_STORE_MEMBASE_REG reg1, offset(basereg) @@ -2568,8 +2568,8 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) ins->opcode = OP_MOVE; ins->sreg1 = last_ins->sreg1; } - - /* + + /* * Note: reg1 must be different from the basereg in the second load * Note: if reg1 = reg2 is equal then second load is removed * @@ -2595,11 +2595,11 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) //g_assert_not_reached (); #if 0 - /* - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + /* + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg * --> - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_ICONST reg, imm */ } else if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM @@ -2614,10 +2614,10 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) break; case OP_LOADI1_MEMBASE: case OP_LOADU1_MEMBASE: - /* + /* * Note: if reg1 = reg2 the load op is removed * - * OP_STORE_MEMBASE_REG reg1, offset(basereg) + * OP_STORE_MEMBASE_REG reg1, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg2 * --> * OP_STORE_MEMBASE_REG reg1, offset(basereg) @@ -2632,10 +2632,10 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) break; case OP_LOADI2_MEMBASE: case OP_LOADU2_MEMBASE: - /* + /* * Note: if reg1 = reg2 the load op is removed * - * OP_STORE_MEMBASE_REG reg1, offset(basereg) + * OP_STORE_MEMBASE_REG reg1, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg2 * --> * OP_STORE_MEMBASE_REG reg1, offset(basereg) @@ -2671,16 +2671,16 @@ mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) /* * Removes: * - * OP_MOVE reg, reg + * OP_MOVE reg, reg */ if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); break; } - /* + /* * Removes: * - * OP_MOVE sreg, dreg + * OP_MOVE sreg, dreg * OP_MOVE dreg, sreg */ if (last_ins && last_ins->opcode == ins->opcode && diff --git a/src/mono/mono/mini/mini-cross-helpers.c b/src/mono/mono/mini/mini-cross-helpers.c index e61ed81727d1f..3ccb2bc72d18d 100644 --- a/src/mono/mono/mini/mini-cross-helpers.c +++ b/src/mono/mono/mini/mini-cross-helpers.c @@ -66,7 +66,7 @@ mono_cross_helpers_run (void) if (g_hasenv ("DUMP_CROSS_OFFSETS")) mono_dump_jit_offsets (); #endif - + #if defined (HAS_CROSS_COMPILER_OFFSETS) && !defined (MONO_CROSS_COMPILE) mono_metadata_cross_helpers_run (); diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index c350d4307bd62..f814096630b0b 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -335,7 +335,7 @@ mono_get_rethrow_preserve_exception_addr (void) return &rethrow_preserve_exception_func; } -static gboolean +static gboolean is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip) { MonoTryBlockHoleTableJitInfo *table; @@ -554,11 +554,11 @@ find_jit_info (MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, /* mono_find_jit_info: * - * This function is used to gather information from @ctx. It return the + * This function is used to gather information from @ctx. It return the * MonoJitInfo of the corresponding function, unwinds one stack frame and - * stores the resulting context into @new_ctx. It also stores a string + * stores the resulting context into @new_ctx. It also stores a string * describing the stack location into @trace (if not NULL), and modifies - * the @lmf if necessary. @native_offset return the IP offset from the + * the @lmf if necessary. @native_offset return the IP offset from the * start of the function or -1 if that info is not available. */ MonoJitInfo * @@ -883,7 +883,7 @@ mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_inf klass = mrgctx->class_vtable->klass; context.method_inst = mrgctx->method_inst; if (!mini_method_is_default_method (method)) - g_assert (context.method_inst); + g_assert (context.method_inst); } else { MonoVTable *vtable = (MonoVTable *)generic_info; @@ -926,7 +926,7 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) ERROR_DECL (error); MonoGenericContext context; MonoMethod *method; - + if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this) return jinfo_get_method (ji); context = mono_get_generic_context_from_stack_frame (ji, generic_info); @@ -949,7 +949,7 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) * The walk ends when no more stack frames are found or when the callback * returns a TRUE value. */ - + gboolean mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data) { @@ -1225,7 +1225,7 @@ mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnw * State must be valid (state->valid == TRUE). * * If you are using this function to unwind another thread, make sure it is suspended. - * + * * If \p state is null, we capture the current context. */ void @@ -1246,7 +1246,7 @@ mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, return; mono_walk_stack_full (func, - &state->ctx, + &state->ctx, (MonoJitTlsData *)state->unwind_data [MONO_UNWIND_DATA_JIT_TLS], (MonoLMF *)state->unwind_data [MONO_UNWIND_DATA_LMF], unwind_options, user_data, FALSE); @@ -1403,14 +1403,14 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsD if (new_reg_locations [i]) reg_locations [i] = new_reg_locations [i]; } - + ctx = new_ctx; } } MonoBoolean -ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, - MonoReflectionMethod **method, +ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, + MonoReflectionMethod **method, gint32 *iloffset, gint32 *native_offset, MonoString **file, gint32 *line, gint32 *column) { @@ -1864,7 +1864,7 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt guint32 free_stack; int clause_index_start = 0; gboolean unwind_res = TRUE; - + StackFrameInfo frame; if (out_prev_ji) @@ -1944,7 +1944,7 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt MonoJitExceptionInfo *ei = &ji->clauses [i]; gboolean filtered = FALSE; - /* + /* * During stack overflow, wait till the unwinding frees some stack * space before running handlers/finalizers. */ @@ -2124,7 +2124,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu mono_error_assert_ok (error); MONO_OBJECT_SETREF_INTERNAL (ex, message, msg); obj = (MonoObject *)ex; - } + } /* * Allocate a new exception object instead of the preconstructed ones. @@ -2157,7 +2157,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu if (mono_ex->caught_in_unmanaged) is_caught_unmanaged = TRUE; - + if (mono_object_isinst_checked (obj, mono_defaults.exception_class, error)) { mono_ex = (MonoException*)obj; @@ -2305,7 +2305,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu gboolean unwind_res = TRUE; StackFrameInfo frame; gpointer ip; - + if (resume) { resume = FALSE; ji = jit_tls->resume_state.ji; @@ -2377,7 +2377,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu MonoJitExceptionInfo *ei = &ji->clauses [i]; gboolean filtered = FALSE; - /* + /* * During stack overflow, wait till the unwinding frees some stack * space before running handlers/finalizers. */ @@ -2415,8 +2415,8 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu #endif if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { - /* - * Filter clauses should only be run in the + /* + * Filter clauses should only be run in the * first pass of exception handling. */ filtered = (filter_idx == first_filter_idx); @@ -2424,7 +2424,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu } error_init (error); - if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && + if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, error)) || filtered) { /* * This guards against the situation that we abort a thread that is executing a finally clause @@ -2534,7 +2534,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) { mono_set_lmf (lmf); if (ji->from_llvm) { - /* + /* * LLVM compiled finally handlers follow the design * of the c++ ehabi, i.e. they call a resume function * at the end instead of returning to the caller. @@ -2978,7 +2978,7 @@ mono_handle_native_crash (const char *signal, MonoContext *mctx, MONO_SIG_HANDLE /* * A crash indicates something went very wrong so we can no longer depend - * on anything working. So try to print out lots of diagnostics, starting + * on anything working. So try to print out lots of diagnostics, starting * with ones which have a greater chance of working. */ @@ -3047,7 +3047,7 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx) mono_runtime_printf_err ("%s\n", text->str); //to print the native callstack #else mono_runtime_printf ("%s", text->str); -#endif +#endif #if HOST_WIN32 && TARGET_WIN32 && _DEBUG OutputDebugStringA(text->str); @@ -3256,6 +3256,8 @@ mono_thread_state_init (MonoThreadUnwindState *ctx) #if defined(MONO_CROSS_COMPILE) ctx->valid = FALSE; //A cross compiler doesn't need to suspend. +#elif defined(HOST_WASI) + // TODO: For WASI, we need to review how thread state is initialized #elif MONO_ARCH_HAS_MONO_CONTEXT MONO_CONTEXT_GET_CURRENT (ctx->ctx); #else @@ -3625,7 +3627,7 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg break; } else mono_error_assert_ok (error); - + if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { g_assert_not_reached (); } diff --git a/src/mono/mono/mini/mini-gc.c b/src/mono/mono/mini/mini-gc.c index 8e44adf6e81f7..9c1477bb68aa0 100644 --- a/src/mono/mono/mini/mini-gc.c +++ b/src/mono/mono/mini/mini-gc.c @@ -80,7 +80,7 @@ typedef struct { * runtime, since it includes columns which are 0. */ int stack_bitmap_width; - /* + /* * A bitmap whose width equals nslots, and whose height equals ncallsites. * The bitmap contains a 1 if the corresponding stack slot has type SLOT_REF at the * given callsite. @@ -157,7 +157,7 @@ typedef struct { /* Number of registers stored in gc maps */ #define NREGS MONO_MAX_IREGS -/* +/* * The GC Map itself. * Contains information needed to mark a stack frame. * This is a transient structure, created from a compressed representation on-demand. @@ -187,7 +187,7 @@ typedef struct { /* The offsets below are into an external bitmaps array */ - /* + /* * A bitmap whose width is equal to bitmap_width, and whose height is equal to ncallsites. * The bitmap contains a 1 if the corresponding stack slot has type SLOT_REF at the * given callsite. @@ -262,7 +262,7 @@ typedef struct { gint32 scanned_registers; gint32 scanned_native; gint32 scanned_other; - + gint32 all_slots; gint32 noref_slots; gint32 ref_slots; @@ -544,7 +544,7 @@ encode_gc_map (GCMap *map, guint8 *buf, guint8 **endbuf) encode_uleb128 (map->ncallsites, buf, &buf); *endbuf = buf; -} +} /* * decode_gc_map: @@ -907,7 +907,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) /* All the other frames are at a call site */ if (tls->nframes == MAX_FRAMES) { - /* + /* * Can't save information since the array is full. So scan the rest of the * stack conservatively. */ @@ -949,7 +949,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) } precise_frame_limit_inited = TRUE; } - + if (precise_frame_limit != -1) { if (precise_frame_count [FALSE] == precise_frame_limit) printf ("LAST PRECISE FRAME: %s\n", mono_method_full_name (method, TRUE)); @@ -1000,7 +1000,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) } cindex = i; - /* + /* * This is not neccessary true on x86 because frames have a different size at each * call site. */ @@ -1048,7 +1048,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) for (i = 0; i < NREGS; ++i) { if (!(map->used_int_regs & (1 << i))) continue; - + if (!(map->reg_pin_mask & (1 << i))) continue; @@ -1176,8 +1176,8 @@ precise_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end, void *gc_dat DEBUG (char *fname = mono_method_full_name (jinfo_get_method (fi->ji), TRUE); fprintf (logfile, "Mark(1): %s\n", fname); g_free (fname)); - /* - * FIXME: Add a function to mark using a bitmap, to avoid doing a + /* + * FIXME: Add a function to mark using a bitmap, to avoid doing a * call for each object. */ @@ -1241,7 +1241,7 @@ precise_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end, void *gc_dat } else { DEBUG (fprintf (logfile, "\treg %s saved at %p: %p\n", mono_arch_regname (fi->regs [i]), ptr, obj)); } - } + } } /* @@ -1261,7 +1261,7 @@ precise_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end, void *gc_dat * * This is called by the GC twice to mark a thread stack. PRECISE is FALSE at the first * call, and TRUE at the second. USER_DATA points to a TlsData - * structure filled up by thread_suspend_func. + * structure filled up by thread_suspend_func. */ static void thread_mark_func (gpointer user_data, guint8 *stack_start, guint8 *stack_end, gboolean precise, void *gc_data) @@ -1571,7 +1571,7 @@ process_other_slots (MonoCompile *cfg) int cfa_slot = data >> 16; GCSlotType type = data & 0xff; int slot; - + /* * Map the cfa relative slot to an fp relative slot. * slot_addr == cfa - *4/8 @@ -1595,7 +1595,7 @@ process_other_slots (MonoCompile *cfg) int offset = data >> 16; GCSlotType type = data & 0xff; int slot; - + slot = fp_offset_to_slot (cfg, offset); set_slot_everywhere (gcfg, slot, type); @@ -1760,7 +1760,7 @@ process_variables (MonoCompile *cfg) gboolean pin = FALSE; int size; int size_in_slots; - + if (ins->backend.is_pinvoke) size = mono_class_native_size (ins->klass, NULL); else @@ -1912,7 +1912,7 @@ process_variables (MonoCompile *cfg) static int sp_offset_to_fp_offset (MonoCompile *cfg, int sp_offset) { - /* + /* * Convert a sp relative offset to a slot index. This is * platform specific. */ @@ -1926,7 +1926,7 @@ sp_offset_to_fp_offset (MonoCompile *cfg, int sp_offset) #ifdef MONO_X86_NO_PUSHES return (- cfg->arch.sp_fp_offset + sp_offset); #else - return (- cfg->arch.sp_fp_offset - sp_offset); + return (- cfg->arch.sp_fp_offset - sp_offset); #endif #else NOT_IMPLEMENTED; @@ -2028,7 +2028,7 @@ process_finally_clauses (MonoCompile *cfg) for (i = 0; i < cfg->header->num_clauses; ++i) { clause = &cfg->header->clauses [i]; - + if (MONO_OFFSET_IN_HANDLER (clause, bb->real_offset)) { if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) { is_in_finally = TRUE; @@ -2237,7 +2237,7 @@ create_map (MonoCompile *cfg) nregs = gcfg->nregs; callsites = gcfg->callsites; - /* + /* * Compute the real size of the bitmap i.e. ignore NOREF columns at the beginning and at * the end. Also, compute whenever the map needs ref/pin bitmaps, and collect stats. */ @@ -2323,7 +2323,7 @@ create_map (MonoCompile *cfg) reg_pin_bitmap_width = ALIGN_TO (npin_regs, 8) / 8; reg_pin_bitmap_size = reg_pin_bitmap_width * ncallsites; bitmaps_size = (has_ref_slots ? stack_bitmap_size : 0) + (has_pin_slots ? stack_bitmap_size : 0) + (has_ref_regs ? reg_ref_bitmap_size : 0) + (has_pin_regs ? reg_pin_bitmap_size : 0); - + map = mono_mempool_alloc0 (cfg->mempool, sizeof (GCMap)); map->frame_reg = cfg->frame_reg; diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index f05a78aa8d804..91811f678deb6 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -1763,7 +1763,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) * stack, pass this address to the interp_entry and when we return it we use * CEE_MONO_LDNATIVEOBJ */ - return_native_struct = sig->ret->type == MONO_TYPE_VALUETYPE && sig->pinvoke; + return_native_struct = sig->ret->type == MONO_TYPE_VALUETYPE && sig->pinvoke && !sig->marshalling_disabled; /* Create the signature for the wrapper */ csig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count * sizeof (MonoType*))); diff --git a/src/mono/mono/mini/mini-llvm-cpp.h b/src/mono/mono/mini/mini-llvm-cpp.h index aaf2ef031f30e..5d376c1de80e3 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.h +++ b/src/mono/mono/mini/mini-llvm-cpp.h @@ -63,15 +63,15 @@ void mono_llvm_dump_type (LLVMTypeRef type); LLVMValueRef -mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, +mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef ArraySize, int alignment, const char *Name); -LLVMValueRef +LLVMValueRef mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, const char *Name, gboolean is_volatile); -LLVMValueRef +LLVMValueRef mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier); @@ -79,11 +79,11 @@ LLVMValueRef mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, const char *Name, gboolean is_volatile, int alignment); -LLVMValueRef +LLVMValueRef mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal, gboolean is_volatile, BarrierKind kind); -LLVMValueRef +LLVMValueRef mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal, gboolean is_volatile, int alignment); @@ -233,4 +233,4 @@ mono_llvm_inline_asm (LLVMBuilderRef builder, LLVMTypeRef type, G_END_DECLS -#endif /* __MONO_MINI_LLVM_CPP_H__ */ +#endif /* __MONO_MINI_LLVM_CPP_H__ */ diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index cd6a279c223d8..c222a8d80c76a 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -7486,7 +7486,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) addresses [ins->dreg] = addresses [ins->sreg1]; } else { if (!addresses [ins->sreg1]) { - addresses [ins->sreg1] = build_alloca (ctx, t); + addresses [ins->sreg1] = build_named_alloca (ctx, t, "llvm_outarg_vt"); g_assert (values [ins->sreg1]); LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, t)), addresses [ins->sreg1]); addresses [ins->dreg] = addresses [ins->sreg1]; @@ -7496,6 +7496,11 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) LLVMValueRef v = LLVMBuildLoad (builder, addresses [ins->sreg1], "llvm_outarg_vt_copy"); LLVMBuildStore (builder, convert (ctx, v, type_to_llvm_type (ctx, t)), addresses [ins->dreg]); } else { + if (values [ins->sreg1]) { + LLVMTypeRef src_t = LLVMTypeOf (values [ins->sreg1]); + LLVMValueRef dst = convert (ctx, addresses [ins->sreg1], LLVMPointerType (src_t, 0)); + LLVMBuildStore (builder, values [ins->sreg1], dst); + } addresses [ins->dreg] = addresses [ins->sreg1]; } } diff --git a/src/mono/mono/mini/mini-mips.c b/src/mono/mono/mini/mini-mips.c index 666c3cd51f936..d8fe51f52c8e0 100644 --- a/src/mono/mono/mini/mini-mips.c +++ b/src/mono/mono/mini/mini-mips.c @@ -95,7 +95,7 @@ static gpointer bp_trigger_page; do { \ code = mips_emit_exc_by_name (code, exc_name); \ cfg->bb_exit->max_offset += 16; \ - } while (0) + } while (0) #define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \ MonoInst *inst; \ @@ -192,7 +192,7 @@ mono_arch_flush_register_windows (void) { } -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return TRUE; @@ -462,7 +462,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the activation frame. */ @@ -473,7 +473,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit guint32 size, align, pad; int offset = 0; - if (MONO_TYPE_ISSTRUCT (csig->ret)) { + if (MONO_TYPE_ISSTRUCT (csig->ret)) { frame_size += sizeof (target_mgreg_t); offset += 4; } @@ -488,12 +488,12 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit arg_info [0].size = frame_size; for (k = 0; k < param_count; k++) { - size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke); + size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke && !csig->marshalling_disabled); /* ignore alignment for now */ align = 1; - frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); + frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); arg_info [k].pad = pad; frame_size += size; arg_info [k + 1].pad = 0; @@ -768,7 +768,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -1156,7 +1156,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) alignment = sizeof (target_mgreg_t); } else { klass = mono_class_from_mono_type_internal (sig->params [i]); - if (is_pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (klass, NULL); else size = mono_class_value_size (klass, NULL); @@ -1390,7 +1390,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* spill down, we'll fix it in a separate pass */ // cfg->flags |= MONO_CFG_HAS_SPILLUP; - /* this is bug #60332: remove when #59509 is fixed, so no weird vararg + /* this is bug #60332: remove when #59509 is fixed, so no weird vararg * call convs needs to be handled this way. */ if (cfg->flags & MONO_CFG_HAS_VARARGS) @@ -1480,7 +1480,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) offset &= ~(align - 1); cfg->sig_cookie = offset; offset += size; - } + } offset += SIZEOF_REGISTER - 1; offset &= ~(SIZEOF_REGISTER - 1); @@ -1537,7 +1537,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst = cfg->args [i]; if (inst->opcode != OP_REGVAR) { MonoType *arg_type; - + if (sig->hasthis && (i == 0)) arg_type = mono_get_object_type (); else @@ -1599,10 +1599,10 @@ mono_arch_create_vars (MonoCompile *cfg) } /* Fixme: we need an alignment solution for enter_method and mono_arch_call_opcode, - * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info + * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info */ -/* +/* * take the arguments and generate the arch-specific * instructions to properly call the function in call. * This includes pushing, moving arguments to the right register @@ -1622,9 +1622,9 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) cfg->disable_aot = TRUE; /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup (call->signature); @@ -1651,7 +1651,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) sig = call->signature; n = sig->param_count + sig->hasthis; - + cinfo = get_call_info (cfg->mempool, sig); if (cinfo->struct_ret) call->used_iregs |= 1 << cinfo->struct_ret; @@ -1827,7 +1827,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) #endif cfg->param_area = (cfg->param_area + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1); cfg->flags |= MONO_CFG_HAS_CALLS; - /* + /* * should set more info in call, such as the stack space * used by the args that needs to be added back to esp */ @@ -1846,7 +1846,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) #if 0 if (cfg->verbose_level > 0) { char* nm = mono_method_full_name (cfg->method, TRUE); - g_print ("Method %s outarg_vt struct doffset=%d ainfo->size=%d ovf_size=%d\n", + g_print ("Method %s outarg_vt struct doffset=%d ainfo->size=%d ovf_size=%d\n", nm, doffset, ainfo->size, ovf_size); g_free (nm); } @@ -1878,7 +1878,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) guint32 size; /* FIXME: alignment? */ - if (call->signature->pinvoke) { + if (call->signature->pinvoke && !call->signature->marshalling_disabled) { size = mono_type_native_stack_size (m_class_get_byval_arg (src->klass), NULL); vtcopy->backend.is_pinvoke = 1; } else { @@ -1978,7 +1978,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *last_ins = ins->prev; switch (ins->opcode) { - case OP_MUL_IMM: + case OP_MUL_IMM: /* remove unnecessary multiplication with 1 */ if (ins->inst_imm == 1) { if (ins->dreg != ins->sreg1) { @@ -1997,11 +1997,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_LOAD_MEMBASE: case OP_LOADI4_MEMBASE: - /* - * OP_STORE_MEMBASE_REG reg, offset(basereg) + /* + * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg */ - if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG + if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG || last_ins->opcode == OP_STORE_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { @@ -2015,7 +2015,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) } break; } - /* + /* * Note: reg1 must be different from the basereg in the second load * OP_LOAD_MEMBASE offset(basereg), reg1 * OP_LOAD_MEMBASE offset(basereg), reg2 @@ -2041,11 +2041,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) break; } #if 0 - /* - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + /* + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg * --> - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_ICONST reg, imm */ if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM @@ -2066,7 +2066,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_ICONV_TO_I1 : OP_ICONV_TO_U1; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; case OP_LOADU2_MEMBASE: @@ -2075,22 +2075,22 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_ICONV_TO_I2 : OP_ICONV_TO_U2; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; case OP_ICONV_TO_I4: case OP_ICONV_TO_U4: case OP_MOVE: ins->opcode = OP_MOVE; - /* - * OP_MOVE reg, reg + /* + * OP_MOVE reg, reg */ if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); continue; } - /* - * OP_MOVE sreg, dreg + /* + * OP_MOVE sreg, dreg * OP_MOVE dreg, sreg */ if (last_ins && last_ins->opcode == OP_MOVE && @@ -2537,7 +2537,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) MONO_BB_FOR_EACH_INS (bb, ins) { mono_print_ins_index (idx++, ins); } - + } #endif @@ -2999,7 +2999,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) MONO_BB_FOR_EACH_INS (bb, ins) { mono_print_ins_index (idx++, ins); } - + } #endif @@ -3422,8 +3422,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BREAK: /* - * gdb does not like encountering the hw breakpoint ins in the debugged code. - * So instead of emitting a trap, we emit a call a C function and place a + * gdb does not like encountering the hw breakpoint ins in the debugged code. + * So instead of emitting a trap, we emit a call a C function and place a * breakpoint there. */ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break)); @@ -3516,7 +3516,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_mfhi (code, ins->dreg); break; } - case OP_IDIV_UN: + case OP_IDIV_UN: case OP_IREM_UN: { guint32 *divisor_is_zero = (guint32 *)(void *)code; @@ -3927,7 +3927,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_nop (code); break; } - case OP_CALL_HANDLER: + case OP_CALL_HANDLER: mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); mips_lui (code, mips_t9, mips_zero, 0); mips_addiu (code, mips_t9, mips_t9, 0); @@ -4281,16 +4281,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: mips_fsubd (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FMUL: mips_fmuld (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FDIV: mips_fdivd (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FNEG: mips_fnegd (code, ins->dreg, ins->sreg1); - break; + break; case OP_FCEQ: mips_fcmpd (code, MIPS_FPU_EQ, ins->sreg1, ins->sreg2); mips_addiu (code, ins->dreg, mips_zero, 1); @@ -4399,7 +4399,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_fbtrue (code, 0); mips_nop (code); } - + mips_fcmpd (code, cond, ins->sreg1, ins->sreg2); mips_nop (code); mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); @@ -4460,7 +4460,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } - + cpos += max_len; last_ins = ins; @@ -4654,7 +4654,7 @@ mips_adjust_stackframe(MonoCompile *cfg) /* * Stack frame layout: - * + * * ------------------- sp + cfg->stack_usage + cfg->param_area * param area incoming * ------------------- sp + cfg->stack_usage + MIPS_STACK_PARAM_OFFSET @@ -4663,7 +4663,7 @@ mips_adjust_stackframe(MonoCompile *cfg) * ra * ------------------- sp + cfg->stack_usage-4 * spilled regs - * ------------------- sp + + * ------------------- sp + * MonoLMF structure optional * ------------------- sp + cfg->arch.lmf_offset * saved registers s0-s8 @@ -4694,12 +4694,12 @@ mono_arch_emit_prolog (MonoCompile *cfg) guint32 lmf_offset = cfg->arch.lmf_offset; int cfa_offset = 0; MonoBasicBlock *bb; - + sig = mono_method_signature_internal (method); cfg->code_size = 768 + sig->param_count * 20; code = cfg->native_code = g_malloc (cfg->code_size); - /* + /* * compute max_offset in order to use short forward jumps. */ max_offset = 0; @@ -4872,7 +4872,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = cinfo->args + i; inst = cfg->args [pos]; - + if (cfg->verbose_level > 2) g_print ("Saving argument %d (type: %d)\n", i, ainfo->storage); if (inst->opcode == OP_REGVAR) { @@ -5184,8 +5184,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg) int max_epilog_size = 50; /* count the number of exception infos */ - - /* + + /* * make sure we have enough space for exceptions * 24 is the simulated call to throw_exception_by_name */ @@ -5230,7 +5230,7 @@ void mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg) { int this_dreg = mips_a0; - + if (vt_reg != -1) this_dreg = mips_a1; @@ -5480,7 +5480,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) mono_arch_flush_icache (ip, code - ip); } - + /* * mono_arch_start_single_stepping: * @@ -5491,7 +5491,7 @@ mono_arch_start_single_stepping (void) { mono_mprotect (ss_trigger_page, mono_pagesize (), 0); } - + /* * mono_arch_stop_single_stepping: * diff --git a/src/mono/mono/mini/mini-mips.h b/src/mono/mono/mini/mini-mips.h index e3fabff76d490..b3a9920adf4e7 100644 --- a/src/mono/mono/mini/mini-mips.h +++ b/src/mono/mono/mini/mini-mips.h @@ -193,7 +193,7 @@ typedef gdouble mips_freg; #define MONO_ARCH_FRAME_ALIGNMENT 8 -/* fixme: align to 16byte instead of 32byte (we align to 32byte to get +/* fixme: align to 16byte instead of 32byte (we align to 32byte to get * reproduceable results for benchmarks */ #define MONO_ARCH_CODE_ALIGNMENT 32 @@ -423,4 +423,4 @@ typedef struct { guint8 *mips_emit_load_const (guint8 *code, int dreg, target_mgreg_t v); -#endif /* __MONO_MINI_MIPS_H__ */ +#endif /* __MONO_MINI_MIPS_H__ */ diff --git a/src/mono/mono/mini/mini-native-types.c b/src/mono/mono/mini/mini-native-types.c index 9faebab38b2e9..a9a3a0f8e484b 100644 --- a/src/mono/mono/mini/mini-native-types.c +++ b/src/mono/mono/mini/mini-native-types.c @@ -374,6 +374,14 @@ mono_class_is_magic_assembly (MonoClass *klass) return TRUE; if (!strcmp ("Xamarin.MacCatalyst", aname)) return TRUE; + if (!strcmp ("Microsoft.iOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.macOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.watchOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.MacCatalyst", aname)) + return TRUE; /* regression test suite */ if (!strcmp ("builtin-types", aname)) return TRUE; diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index f41585485a911..f4b6fa56581dd 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -982,7 +982,7 @@ MINI_OP(OP_PMULQ, "pmulq", XREG, XREG, XREG) MINI_OP(OP_PMULW_HIGH_UN, "pmulw_high_un", XREG, XREG, XREG) MINI_OP(OP_PMULW_HIGH, "pmulw_high", XREG, XREG, XREG) -/*SSE2 Shift ops must have the _reg version right after as code depends on this ordering.*/ +/*SSE2 Shift ops must have the _reg version right after as code depends on this ordering.*/ MINI_OP(OP_PSHRW, "pshrw", XREG, XREG, NONE) MINI_OP(OP_PSHRW_REG, "pshrw_reg", XREG, XREG, XREG) @@ -1254,12 +1254,12 @@ MINI_OP(OP_CMOV_LLE_UN, "cmov_lle_un", IREG, IREG, IREG) MINI_OP(OP_CMOV_LLT_UN, "cmov_llt_un", IREG, IREG, IREG) /* Debugging support */ -/* +/* * Marks the start of the live range of the variable in inst_c0, that is the * first instruction where the variable has a value. */ MINI_OP(OP_LIVERANGE_START, "liverange_start", NONE, NONE, NONE) -/* +/* * Marks the end of the live range of the variable in inst_c0, that is the * first instruction where the variable no longer has a value. */ diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index a173516415bcb..b706de969f5ce 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -176,7 +176,7 @@ save_old_signal_handler (int signo, struct sigaction *old_action) } handler_to_save->sa_mask = old_action->sa_mask; handler_to_save->sa_flags = old_action->sa_flags; - + if (!mono_saved_signal_handlers) mono_saved_signal_handlers = g_hash_table_new_full (NULL, NULL, NULL, g_free); g_hash_table_insert (mono_saved_signal_handlers, GINT_TO_POINTER (signo), handler_to_save); @@ -321,7 +321,7 @@ add_signal_handler (int signo, MonoSignalHandler handler, int flags) #endif sa.sa_flags |= SA_ONSTACK; - /* + /* * libgc will crash when trying to do stack marking for threads which are on * an altstack, so delay the suspend signal after the signal handler has * executed. @@ -331,11 +331,11 @@ add_signal_handler (int signo, MonoSignalHandler handler, int flags) } #endif if (signo == SIGSEGV) { - /* + /* * Delay abort signals while handling SIGSEGVs since they could go unnoticed. */ sigset_t block_mask; - + sigemptyset (&block_mask); } #else @@ -347,7 +347,7 @@ add_signal_handler (int signo, MonoSignalHandler handler, int flags) /* if there was already a handler in place for this signal, store it */ if (! (previous_sa.sa_flags & SA_SIGINFO) && - (SIG_DFL == previous_sa.sa_handler)) { + (SIG_DFL == previous_sa.sa_handler)) { /* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */ } else { if (mono_do_signal_chaining) @@ -958,7 +958,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) const char *argv [10]; memset (argv, 0, sizeof (char*) * 10); - char commands_filename [100]; + char commands_filename [100]; commands_filename [0] = '\0'; g_snprintf (commands_filename, sizeof (commands_filename), "/tmp/mono-gdb-commands.%d", crashed_pid); diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index df2cd3b6f362b..ed8bf63f631a1 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -155,7 +155,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse /* the hardware has multiple load/store units and the move is long enough to use more then one register, then use load/load/store/store to execute 2 instructions per cycle. */ - if ((cpu_hw_caps & PPC_MULTIPLE_LS_UNITS) && (dreg != ppc_r11) && (sreg != ppc_r11)) { + if ((cpu_hw_caps & PPC_MULTIPLE_LS_UNITS) && (dreg != ppc_r11) && (sreg != ppc_r11)) { while (size >= 16) { ppc_ldptr (code, ppc_r0, soffset, sreg); ppc_ldptr (code, ppc_r11, soffset+8, sreg); @@ -163,7 +163,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse ppc_stptr (code, ppc_r11, doffset+8, dreg); size -= 16; soffset += 16; - doffset += 16; + doffset += 16; } } while (size >= 8) { @@ -174,7 +174,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse doffset += 8; } #else - if ((cpu_hw_caps & PPC_MULTIPLE_LS_UNITS) && (dreg != ppc_r11) && (sreg != ppc_r11)) { + if ((cpu_hw_caps & PPC_MULTIPLE_LS_UNITS) && (dreg != ppc_r11) && (sreg != ppc_r11)) { while (size >= 8) { ppc_lwz (code, ppc_r0, soffset, sreg); ppc_lwz (code, ppc_r11, soffset+4, sreg); @@ -182,7 +182,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse ppc_stw (code, ppc_r11, doffset+4, dreg); size -= 8; soffset += 8; - doffset += 8; + doffset += 8; } } #endif @@ -217,7 +217,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the activation frame. */ @@ -232,7 +232,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit int size, align, pad; int offset = 8; - if (MONO_TYPE_ISSTRUCT (csig->ret)) { + if (MONO_TYPE_ISSTRUCT (csig->ret)) { frame_size += sizeof (target_mgreg_t); offset += 4; } @@ -247,8 +247,8 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit arg_info [0].size = frame_size; for (k = 0; k < param_count; k++) { - - if (csig->pinvoke) + + if (csig->pinvoke && !csig->marshalling_disabled) size = mono_type_native_stack_size (csig->params [k], (guint32*)&align); else size = mini_type_stack_size (csig->params [k], &align); @@ -256,7 +256,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit /* ignore alignment for now */ align = 1; - frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); + frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); arg_info [k].pad = pad; frame_size += size; arg_info [k + 1].pad = 0; @@ -483,7 +483,7 @@ typedef struct { } AuxVec; #define MAX_AUX_ENTRIES 128 -/* +/* * PPC_FEATURE_POWER4, PPC_FEATURE_POWER5, PPC_FEATURE_POWER5_PLUS, PPC_FEATURE_CELL, * PPC_FEATURE_PA6T, PPC_FEATURE_ARCH_2_05 are considered supporting 2X ISA features */ @@ -709,7 +709,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -862,7 +862,7 @@ struct CallInfo { static gboolean is_float_struct_returnable_via_regs (MonoType *type, int* member_cnt, int* member_size) { - int local_member_cnt, local_member_size; + int local_member_cnt, local_member_size; if (!member_cnt) { member_cnt = &local_member_cnt; } @@ -1109,7 +1109,7 @@ get_call_info (MonoMethodSignature *sig) MonoClass *klass = mono_class_from_mono_type_internal (sig->params [i]); if (simpletype->type == MONO_TYPE_TYPEDBYREF) size = MONO_ABI_SIZEOF (MonoTypedRef); - else if (is_pinvoke) + else if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size (klass, NULL); else size = mono_class_value_size (klass, NULL); @@ -1375,7 +1375,7 @@ mono_arch_allocate_vars (MonoCompile *m) m->flags |= MONO_CFG_HAS_SPILLUP; - /* this is bug #60332: remove when #59509 is fixed, so no weird vararg + /* this is bug #60332: remove when #59509 is fixed, so no weird vararg * call convs needs to be handled this way. */ if (m->flags & MONO_CFG_HAS_VARARGS) @@ -1389,7 +1389,7 @@ mono_arch_allocate_vars (MonoCompile *m) header = m->header; - /* + /* * We use the frame register also for any method that has * exception clauses. This way, when the handlers are called, * the code will reference local variables using the frame reg instead of @@ -1397,7 +1397,7 @@ mono_arch_allocate_vars (MonoCompile *m) * corrupt the method frames that are already on the stack (since * filters get called before stack unwinding happens) when the filter * code would call any method (this also applies to finally etc.). - */ + */ if ((m->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses) frame_reg = ppc_r31; m->frame_reg = frame_reg; @@ -1406,7 +1406,7 @@ mono_arch_allocate_vars (MonoCompile *m) } sig = mono_method_signature_internal (m->method); - + offset = 0; curinst = 0; if (MONO_TYPE_ISSTRUCT (sig->ret)) { @@ -1429,7 +1429,7 @@ mono_arch_allocate_vars (MonoCompile *m) } } /* local vars are at a positive offset from the stack pointer */ - /* + /* * also note that if the function uses alloca, we use ppc_r31 * to point at the local variables. */ @@ -1498,7 +1498,7 @@ mono_arch_allocate_vars (MonoCompile *m) if (inst->opcode != OP_REGVAR) { inst->opcode = OP_REGOFFSET; inst->inst_basereg = frame_reg; - if (sig->pinvoke) { + if (sig->pinvoke && !sig->marshalling_disabled) { size = mono_type_native_stack_size (sig->params [i], (guint32*)&align); inst->backend.is_pinvoke = 1; } else { @@ -1506,7 +1506,7 @@ mono_arch_allocate_vars (MonoCompile *m) } if (MONO_TYPE_ISSTRUCT (sig->params [i]) && size < sizeof (target_mgreg_t)) size = align = sizeof (target_mgreg_t); - /* + /* * Use at least 4/8 byte alignment, since these might be passed in registers, and * they are saved using std in the prolog. */ @@ -1552,7 +1552,7 @@ mono_arch_create_vars (MonoCompile *cfg) } /* Fixme: we need an alignment solution for enter_method and mono_arch_call_opcode, - * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info + * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info */ static void @@ -1578,7 +1578,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) sig = call->signature; n = sig->param_count + sig->hasthis; - + cinfo = get_call_info (sig); for (i = 0; i < n; ++i) { @@ -1739,7 +1739,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) * and 2 byte arguments */ g_assert (ins->klass); - if (call->signature->pinvoke) + if (call->signature->pinvoke && !call->signature->marshalling_disabled) size = mono_class_native_size (ins->klass, NULL); if (size == 2 || size == 1) { int tmpr = mono_alloc_ireg (cfg); @@ -1801,7 +1801,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) guint32 size; /* FIXME: alignment? */ - if (call->signature->pinvoke) { + if (call->signature->pinvoke && !call->signature->marshalling_disabled) { size = mono_type_native_stack_size (m_class_get_byval_arg (src->klass), NULL); vtcopy->backend.is_pinvoke = 1; } else { @@ -1913,7 +1913,7 @@ if (0 && ins->inst_true_bb->native_offset) { \ MONO_PATCH_INFO_EXC, exc_name); \ ppc_bcl (code, (b0), (b1), 0); \ } \ - } while (0); + } while (0); #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) EMIT_COND_SYSTEM_EXCEPTION_FLAGS(branch_b0_table [(cond)], branch_b1_table [(cond)], (exc_name)) @@ -1954,7 +1954,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) { switch (normalize_opcode (ins->opcode)) { - case OP_MUL_IMM: + case OP_MUL_IMM: /* remove unnecessary multiplication with 1 */ if (ins->inst_imm == 1) { if (ins->dreg != ins->sreg1) { @@ -1972,8 +1972,8 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_LOAD_MEMBASE: - /* - * OP_STORE_MEMBASE_REG reg, offset(basereg) + /* + * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg */ if (last_ins && normalize_opcode (last_ins->opcode) == OP_STORE_MEMBASE_REG && @@ -1988,7 +1988,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->sreg1 = last_ins->sreg1; } - /* + /* * Note: reg1 must be different from the basereg in the second load * OP_LOAD_MEMBASE offset(basereg), reg1 * OP_LOAD_MEMBASE offset(basereg), reg2 @@ -2012,11 +2012,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) //g_assert_not_reached (); #if 0 - /* - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + /* + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg * --> - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_ICONST reg, imm */ } else if (last_ins && normalize_opcode (last_ins->opcode) == OP_STORE_MEMBASE_IMM && @@ -2035,7 +2035,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_ICONV_TO_I1 : OP_ICONV_TO_U1; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; case OP_LOADU2_MEMBASE: @@ -2044,7 +2044,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_ICONV_TO_I2 : OP_ICONV_TO_U2; - ins->sreg1 = last_ins->sreg1; + ins->sreg1 = last_ins->sreg1; } break; #ifdef __mono_ppc64__ @@ -2060,15 +2060,15 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) #endif case OP_MOVE: ins->opcode = OP_MOVE; - /* - * OP_MOVE reg, reg + /* + * OP_MOVE reg, reg */ if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); continue; } - /* - * OP_MOVE sreg, dreg + /* + * OP_MOVE sreg, dreg * OP_MOVE dreg, sreg */ if (last_ins && last_ins->opcode == OP_MOVE && @@ -2232,7 +2232,7 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins) } } -/* +/* * the branch_b0_table should maintain the order of these * opcodes. case CEE_BEQ: @@ -2246,34 +2246,34 @@ case CEE_BGT_UN: case CEE_BLE_UN: case CEE_BLT_UN: */ -static const guchar +static const guchar branch_b0_table [] = { - PPC_BR_TRUE, - PPC_BR_FALSE, - PPC_BR_TRUE, - PPC_BR_FALSE, - PPC_BR_TRUE, - - PPC_BR_FALSE, - PPC_BR_FALSE, - PPC_BR_TRUE, + PPC_BR_TRUE, + PPC_BR_FALSE, + PPC_BR_TRUE, + PPC_BR_FALSE, + PPC_BR_TRUE, + + PPC_BR_FALSE, + PPC_BR_FALSE, + PPC_BR_TRUE, PPC_BR_FALSE, PPC_BR_TRUE }; -static const guchar +static const guchar branch_b1_table [] = { - PPC_BR_EQ, - PPC_BR_LT, - PPC_BR_GT, + PPC_BR_EQ, + PPC_BR_LT, PPC_BR_GT, - PPC_BR_LT, - - PPC_BR_EQ, - PPC_BR_LT, - PPC_BR_GT, PPC_BR_GT, - PPC_BR_LT + PPC_BR_LT, + + PPC_BR_EQ, + PPC_BR_LT, + PPC_BR_GT, + PPC_BR_GT, + PPC_BR_LT }; #define NEW_INS(cfg,dest,op) do { \ @@ -2621,7 +2621,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) last_ins = ins; } bb->last_ins = last_ins; - bb->max_vreg = cfg->next_vreg; + bb->max_vreg = cfg->next_vreg; } static guchar* @@ -2814,7 +2814,7 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i return; } } - + if ((glong)target >= 0){ if ((glong)target <= 33554431){ ins = (18 << 26) | ((gulong) target) | (ins & 1) | 2; @@ -2834,8 +2834,8 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i g_assert_not_reached (); } - - + + if (prim == 16) { g_assert (!is_fd); // absolute address @@ -3054,7 +3054,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (cfg->compile_aot) NOT_IMPLEMENTED; - /* + /* * Read from the single stepping trigger page. This will cause a * SIGSEGV when single stepping is enabled. * We do this _before_ the breakpoint, so single stepping after @@ -3067,7 +3067,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_seq_point (cfg, bb, ins, code - cfg->native_code); - /* + /* * A placeholder for a possible breakpoint inserted by * mono_arch_set_breakpoint (). */ @@ -3313,8 +3313,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BREAK: /* - * gdb does not like encountering a trap in the debugged code. So - * instead of emitting a trap, we emit a call a C function and place a + * gdb does not like encountering a trap in the debugged code. So + * instead of emitting a trap, we emit a call a C function and place a * breakpoint there. */ //ppc_break (code); @@ -3590,7 +3590,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_IMUL_OVF: CASE_PPC64 (OP_LMUL_OVF) - /* we annot use mcrxr, since it's not implemented on some processors + /* we annot use mcrxr, since it's not implemented on some processors * XER format: SO, OV, CA, reserved [21 bits], count [8 bits] */ if (ins->opcode == OP_IMUL_OVF) @@ -3606,7 +3606,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IMUL_OVF_UN: CASE_PPC64 (OP_LMUL_OVF_UN) /* we first multiply to get the high word and compare to 0 - * to set the flags, then the result is discarded and then + * to set the flags, then the result is discarded and then * we multiply to get the lower * bits result */ if (ins->opcode == OP_IMUL_OVF_UN) @@ -3958,7 +3958,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_blr (code); break; } - case OP_CALL_HANDLER: + case OP_CALL_HANDLER: mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb); ppc_bl (code, 0); for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev) @@ -3970,7 +3970,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_BR: /*if (ins->inst_target_bb->native_offset) { ppc_b (code, 0); - //x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); + //x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); } else*/ { mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); ppc_b (code, 0); @@ -4193,7 +4193,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) msword_negative_branch = code; ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0); ppc_patch (msword_negative_branch, ovf_ex_target); - + ppc_patch (msword_positive_branch, code); if (ins->dreg != ins->sreg1) ppc_mr (code, ins->dreg, ins->sreg1); @@ -4226,16 +4226,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: ppc_fsub (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FMUL: ppc_fmul (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FDIV: ppc_fdiv (code, ins->dreg, ins->sreg1, ins->sreg2); - break; + break; case OP_FNEG: ppc_fneg (code, ins->dreg, ins->sreg1); - break; + break; case OP_FREM: /* emulated */ g_assert_not_reached (); @@ -4562,7 +4562,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_inst_name (ins->opcode), max_len, (glong)(code - cfg->native_code - offset)); g_assert_not_reached (); } - + cpos += max_len; last_ins = ins; @@ -4710,7 +4710,7 @@ save_registers (MonoCompile *cfg, guint8* code, int pos, int base_reg, gboolean /* * Stack frame layout: - * + * * ------------------- sp * MonoLMF structure or saved registers * ------------------- @@ -4806,7 +4806,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* compute max_offset in order to use short forward jumps * we always do it on ppc because the immediate displacement - * for jumps is too small + * for jumps is too small */ max_offset = 0; for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { @@ -4840,7 +4840,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = cinfo->args + i; inst = cfg->args [pos]; - + if (cfg->verbose_level > 2) g_print ("Saving argument %d (type: %d)\n", i, ainfo->regtype); if (inst->opcode == OP_REGVAR) { @@ -5036,7 +5036,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) g_assert (ppc_is_imm16 (inst->inst_offset)); g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->vtregs * sizeof (target_mgreg_t))); /* FIXME: what if there is no class? */ - if (sig->pinvoke && mono_class_from_mono_type_internal (inst->inst_vtype)) + if (sig->pinvoke && !sig->marshalling_disabled && mono_class_from_mono_type_internal (inst->inst_vtype)) size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), NULL); for (cur_reg = 0; cur_reg < ainfo->vtregs; ++cur_reg) { if (ainfo->size == 4) { @@ -5055,7 +5055,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) g_assert (ppc_is_imm16 (inst->inst_offset)); g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->vtregs * sizeof (target_mgreg_t))); /* FIXME: what if there is no class? */ - if (sig->pinvoke && mono_class_from_mono_type_internal (inst->inst_vtype)) + if (sig->pinvoke && !sig->marshalling_disabled && mono_class_from_mono_type_internal (inst->inst_vtype)) size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), NULL); for (cur_reg = 0; cur_reg < ainfo->vtregs; ++cur_reg) { #if __APPLE__ @@ -5204,7 +5204,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) if (cfg->method->save_lmf) max_epilog_size += 128; - + code = realloc_code (cfg, max_epilog_size); pos = 0; @@ -5332,8 +5332,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg) } /* count the number of exception infos */ - - /* + + /* * make sure we have enough space for exceptions */ for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { @@ -5801,7 +5801,7 @@ mono_arch_emit_load_got_addr (guint8 *start, guint8 *code, MonoCompile *cfg, Mon * * Emit code to load the contents of the GOT slot identified by TRAMP_TYPE and * TARGET from the mscorlib GOT in full-aot code. - * On PPC, the GOT address is assumed to be in r30, and the result is placed into + * On PPC, the GOT address is assumed to be in r30, and the result is placed into * r12. */ guint8* @@ -5891,7 +5891,7 @@ mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) /* * SINGLE STEPPING */ - + /* * mono_arch_start_single_stepping: * @@ -5902,7 +5902,7 @@ mono_arch_start_single_stepping (void) { mono_mprotect (ss_trigger_page, mono_pagesize (), 0); } - + /* * mono_arch_stop_single_stepping: * diff --git a/src/mono/mono/mini/mini-ppc.h b/src/mono/mono/mini/mini-ppc.h index 6f1ce5ff2e9a1..88a5415c5a925 100644 --- a/src/mono/mono/mini/mini-ppc.h +++ b/src/mono/mono/mini/mini-ppc.h @@ -28,7 +28,7 @@ #define MONO_ARCH_FRAME_ALIGNMENT 16 -/* fixme: align to 16byte instead of 32byte (we align to 32byte to get +/* fixme: align to 16byte instead of 32byte (we align to 32byte to get * reproduceable results for benchmarks */ #define MONO_ARCH_CODE_ALIGNMENT 32 @@ -71,9 +71,9 @@ typedef struct MonoCompileArch { * - for variables which contain values of registers, use host_mgreg_t or target_mgreg_t. * - for loading/saving pointers/ints, use the normal ppc_load_reg/ppc_save_reg () * macros. - * - for loading/saving register sized quantities, use the ppc_ldr/ppc_str + * - for loading/saving register sized quantities, use the ppc_ldr/ppc_str * macros. - * - make sure to not mix the two kinds of macros for the same memory location, + * - make sure to not mix the two kinds of macros for the same memory location, * since ppc is big endian, so a 8 byte store followed by a 4 byte load will * load the upper 32 bit of the value. * - use OP_LOADR_MEMBASE/OP_STORER_MEMBASE to load/store register sized diff --git a/src/mono/mono/mini/mini-profiler.c b/src/mono/mono/mini/mini-profiler.c index cc20f01d4a2ad..c3a78238e4d31 100644 --- a/src/mono/mono/mini/mini-profiler.c +++ b/src/mono/mono/mini/mini-profiler.c @@ -149,7 +149,7 @@ mini_profiler_emit_tail_call (MonoCompile *cfg, MonoMethod *target) EMIT_NEW_PCONST (cfg, iargs [1], NULL); if (target) - EMIT_NEW_METHODCONST (cfg, iargs [2], target); + EMIT_NEW_METHODCONST (cfg, iargs [2], target); else EMIT_NEW_PCONST (cfg, iargs [2], NULL); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 78d588f38a435..a52e6cb1a7628 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -126,7 +126,7 @@ gboolean mono_use_llvm = FALSE; gboolean mono_use_fast_math = FALSE; -// Lists of allowlisted and blocklisted CPU features +// Lists of allowlisted and blocklisted CPU features MonoCPUFeatures mono_cpu_features_enabled = (MonoCPUFeatures)0; #ifdef DISABLE_SIMD @@ -2021,7 +2021,7 @@ mono_enable_jit_dump (void) { if (perf_dump_pid == 0) perf_dump_pid = getpid(); - + if (!perf_dump_file) { char name [64]; FileHeader header; @@ -2029,18 +2029,18 @@ mono_enable_jit_dump (void) mono_os_mutex_init (&perf_dump_mutex); mono_os_mutex_lock (&perf_dump_mutex); - + g_snprintf (name, sizeof (name), "/tmp/jit-%d.dump", perf_dump_pid); unlink (name); perf_dump_file = fopen (name, "w"); - + add_file_header_info (&header); if (perf_dump_file) { fwrite (&header, sizeof (header), 1, perf_dump_file); //This informs perf of the presence of the jitdump file and support for the feature. perf_dump_mmap_addr = mmap (NULL, sizeof (header), PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno (perf_dump_file), 0); } - + mono_os_mutex_unlock (&perf_dump_mutex); } } @@ -2062,12 +2062,12 @@ void mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code) { static uint64_t code_index; - + if (perf_dump_file) { JitCodeLoadRecord record; size_t nameLen = strlen (jinfo->d.method->name); memset (&record, 0, sizeof (record)); - + add_basic_JitCodeLoadRecord_info (&record); record.header.total_size = sizeof (record) + nameLen + 1 + jinfo->code_size; record.vma = (guint64)jinfo->code_start; @@ -2075,13 +2075,13 @@ mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code) record.code_size = (guint64)jinfo->code_size; mono_os_mutex_lock (&perf_dump_mutex); - + record.code_index = ++code_index; - + // TODO: write debugInfo and unwindInfo immediately before the JitCodeLoadRecord (while lock is held). - + record.header.timestamp = mono_clock_get_time_ns (clock_id); - + fwrite (&record, sizeof (record), 1, perf_dump_file); fwrite (jinfo->d.method->name, nameLen + 1, 1, perf_dump_file); fwrite (code, jinfo->code_size, 1, perf_dump_file); @@ -2812,7 +2812,7 @@ mono_jit_free_method (MonoMethod *method) mono_debug_remove_method (method, NULL); mono_lldb_remove_method (method, ji); - + //seq_points are always on get_default_jit_mm jit_mm = get_default_jit_mm (); jit_mm_lock (jit_mm); @@ -4402,7 +4402,7 @@ mini_init (const char *filename, const char *runtime_version) mono_ee_interp_init (mono_interp_opts_string); #endif mono_components_init (); - + mono_component_debugger ()->parse_options (mono_debugger_agent_get_sdb_options ()); mono_os_mutex_init_recursive (&jit_mutex); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index d1e822a35e7a2..4f348797326d3 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -159,14 +159,14 @@ struct MonoJitTlsData { /* context to be used by the guard trampoline when resuming interruption.*/ MonoContext handler_block_context; - /* + /* * Stores the state at the exception throw site to be used by mono_stack_walk () * when it is called from profiler functions during exception handling. */ MonoContext orig_ex_ctx; gboolean orig_ex_ctx_set; - /* + /* * The current exception in flight */ MonoGCHandle thrown_exc; diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index b3fb3de3ab061..3cc263ec280da 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -62,7 +62,7 @@ if (ins->inst_target_bb->native_offset) { \ mono_add_patch_info (cfg, code - cfg->native_code, \ MONO_PATCH_INFO_EXC, exc_name); \ s390_jcl (code, cond, 0); \ - } while (0); + } while (0); #define EMIT_COMP_AND_BRANCH(ins, cab, cmp) \ { \ @@ -213,7 +213,7 @@ if (ins->inst_true_bb->native_offset) { \ } \ s390_ ## op (code, ins->dreg, ins->sreg2, m, s390_f14); \ } \ - s390_ldgr (code, s390_f14, s390_r1); + s390_ldgr (code, s390_f14, s390_r1); #undef DEBUG #define DEBUG(a) if (cfg->verbose_level > 1) a @@ -279,7 +279,7 @@ typedef struct { code_size, parm_size, retStruct; -} size_data; +} size_data; /** * ABI - register use in calls etc. @@ -390,7 +390,7 @@ static const char * fpNames[] = { * Constants used in debugging - map vector register names */ static const char * vrNames[] = { - "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", + "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31" @@ -400,7 +400,7 @@ static const char * vrNames[] = { /** * Constants used in debugging - ABI register types */ -static const char *typeParm[] = { "General", "Base", "FPR8", "FPR4", "StructByVal", +static const char *typeParm[] = { "General", "Base", "FPR8", "FPR4", "StructByVal", "StructByValInFP", "ByAddr"}; #endif @@ -410,9 +410,9 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (math, "System", "Math") static GENERATE_TRY_GET_CLASS_WITH_CACHE (mathf, "System", "MathF") /** - * + * * @brief Return general register name - * + * * @param[in] register number * @returns Name of register * @@ -420,7 +420,7 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (mathf, "System", "MathF") */ const char* -mono_arch_regname (int reg) +mono_arch_regname (int reg) { if (reg >= 0 && reg < 16) return grNames [reg]; @@ -431,9 +431,9 @@ mono_arch_regname (int reg) /*========================= End of Function ========================*/ /** - * + * * @brief Return floating point register name - * + * * @param[in] register number * @returns Name of register * @@ -441,7 +441,7 @@ mono_arch_regname (int reg) */ const char* -mono_arch_fregname (int reg) +mono_arch_fregname (int reg) { if (reg >= 0 && reg < 16) return fpNames [reg]; @@ -452,9 +452,9 @@ mono_arch_fregname (int reg) /*========================= End of Function ========================*/ /** - * + * * @brief Return vector register name - * + * * @param[in] register number * @returns Name of register * @@ -473,28 +473,28 @@ mono_arch_xregname (int reg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific return argument information - * + * * @param[in] @csig - Method signature * @param[in] @param_count - Number of parameters to consider * @param[out] @arg_info - An array in which to store results * @returns Size of the activation frame * - * Gathers information on parameters such as size, alignment, and padding. - * arg_info should be large * enough to hold param_count + 1 entries. + * Gathers information on parameters such as size, alignment, and padding. + * arg_info should be large * enough to hold param_count + 1 entries. */ int -mono_arch_get_argument_info (MonoMethodSignature *csig, - int param_count, +mono_arch_get_argument_info (MonoMethodSignature *csig, + int param_count, MonoJitArgumentInfo *arg_info) { int k, frame_size = 0; int size, align, pad; int offset = 8; - if (MONO_TYPE_ISSTRUCT (csig->ret)) { + if (MONO_TYPE_ISSTRUCT (csig->ret)) { frame_size += sizeof (target_mgreg_t); offset += 8; } @@ -509,13 +509,13 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, arg_info [0].size = frame_size; for (k = 0; k < param_count; k++) { - - if (csig->pinvoke) + + if (csig->pinvoke && !csig->marshalling_disabled) size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align); else size = mini_type_stack_size (csig->params [k], &align); - frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); + frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); arg_info [k].pad = pad; frame_size += size; arg_info [k + 1].pad = 0; @@ -535,9 +535,9 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, /*========================= End of Function ========================*/ /** - * + * * @brief Emit an s390x move operation - * + * * @param[in] @cfg - MonoCompile control block * @param[in] @dr - Destination register * @param[in] @ins - Current instruction @@ -553,10 +553,10 @@ emit_new_move(MonoCompile *cfg, int dr, MonoInst *ins, MonoInst *src) ArgInfo *ainfo = (ArgInfo *) ins->inst_p1; MonoInst *vtcopy = mono_compile_create_var (cfg, m_class_get_byval_arg (src->klass), OP_LOCAL); MonoInst *load; - MonoInst *move; + MonoInst *move; int size; - - if (call->signature->pinvoke) { + + if (call->signature->pinvoke && !call->signature->marshalling_disabled) { size = mono_type_native_stack_size (m_class_get_byval_arg (src->klass), NULL); vtcopy->backend.is_pinvoke = 1; } else { @@ -570,26 +570,26 @@ emit_new_move(MonoCompile *cfg, int dr, MonoInst *ins, MonoInst *src) move->inst_offset = 0; move->sreg1 = src->dreg; move->inst_imm = 0; - move->backend.size = size; - MONO_ADD_INS (cfg->cbb, move); + move->backend.size = size; + MONO_ADD_INS (cfg->cbb, move); if (dr != 0) MONO_EMIT_NEW_UNALU(cfg, OP_MOVE, dr, load->dreg); else MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, ainfo->reg, ainfo->offset, load->dreg); -} +} /*========================= End of Function ========================*/ /** - * + * * @brief Generate output sequence for VT register parameters - * + * * @param[in] @cfg - MonoCompile control block * @param[in] @dr - Destination register * @param[in] @ins - Current instruction - * @param[in] @src - Instruction representing the source - * + * @param[in] @src - Instruction representing the source + * * Emit the output of structures for calls whose address is placed in a register. */ @@ -620,7 +620,7 @@ emit_outarg_vtr(MonoCompile *cfg, MonoInst *ins, MonoInst *src) MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, reg, src->dreg, 0); break; - default: + default: emit_new_move (cfg, reg, ins, src); } mono_call_inst_add_outarg_reg(cfg, call, reg, ainfo->reg, FALSE); @@ -629,14 +629,14 @@ emit_outarg_vtr(MonoCompile *cfg, MonoInst *ins, MonoInst *src) /*========================= End of Function ========================*/ /** - * + * * @brief Generate output sequence for VT stack parameters - * + * * @param[in] @cfg - MonoCompile control block * @param[in] @dr - Destination register * @param[in] @ins - Current instruction - * @param[in] @src - Instruction representing the source - * + * @param[in] @src - Instruction representing the source + * * Emit the output of structures for calls whose address is placed on the stack */ @@ -644,12 +644,12 @@ static void __inline__ emit_outarg_vts(MonoCompile *cfg, MonoInst *ins, MonoInst *src) { ArgInfo *ainfo = (ArgInfo *) ins->inst_p1; - int tmpr = mono_alloc_preg (cfg); + int tmpr = mono_alloc_preg (cfg); switch (ins->backend.size) { case 0: MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); - MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, + MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, ainfo->reg, ainfo->offset, tmpr); break; case 1: @@ -685,15 +685,15 @@ emit_outarg_vts(MonoCompile *cfg, MonoInst *ins, MonoInst *src) /*========================= End of Function ========================*/ /** - * + * * @brief Generate unwind information for range of registers - * + * * @param[in] @cfg - MonoCompile control block * @param[in] @code - Location of code * @param[in] @start - Starting register * @param[in] @end - Ending register * @param[in] @offset - Offset in stack - * + * * Emit unwind information for a range of registers. */ @@ -712,13 +712,13 @@ emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset /*========================= End of Function ========================*/ /** - * + * * @brief Get previous stack frame pointer - * + * * @param[in] @cfg - MonoCompile control block * @param[in] @code - Location of code * @returns Previous stack pointer - * + * * Retrieve the stack pointer of the previous frame */ @@ -751,9 +751,9 @@ backUpStackPtr(MonoCompile *cfg, guint8 *code) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific CPU initialization - * + * * Perform CPU specific initialization to execute managed code. */ @@ -765,10 +765,10 @@ mono_arch_cpu_init (void) /*========================= End of Function ========================*/ /** - * + * * @brief Archictecture specific initialization - * - * + * + * * Initialize architecture specific code: * - Define trigger pages for debugger * - Generate breakpoint code stub @@ -786,10 +786,10 @@ mono_arch_init (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific cleaup code - * - * + * + * * Clean up before termination: * - Free the trigger pages */ @@ -802,12 +802,12 @@ mono_arch_cleanup (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific check for fast TLS access - * + * * @returns True - * - * Returns whether we use fast inlined thread local storage managed access, + * + * Returns whether we use fast inlined thread local storage managed access, * instead of falling back to native code. */ @@ -820,12 +820,12 @@ mono_arch_have_fast_tls (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific check of mono optimizations - * + * * @param[out] @exclude_mask - Optimization exclusion mask * @returns Optimizations supported on this CPU - * + * * Returns the optimizations supported on this CPU */ @@ -844,12 +844,12 @@ mono_arch_cpu_optimizations (guint32 *exclude_mask) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific allocation of integer variables - * + * * @param[in] @cfg - MonoCompile control block * @returns A list of integer variables - * + * * Returns a list of allocatable integer variables */ @@ -867,7 +867,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; - if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || + if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) continue; @@ -885,12 +885,12 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific determination of usable integer registers - * + * * @param[in] @cfg - MonoCompile control block * @returns A list of allocatable registers - * + * * Returns a list of usable integer registers */ @@ -909,7 +909,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */ top = 12; for (i = 8; i < top; ++i) { - if ((cfg->frame_reg != i) && + if ((cfg->frame_reg != i) && //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG))) (i != MONO_ARCH_IMT_REG)) regs = g_list_prepend (regs, GUINT_TO_POINTER (i)); @@ -921,12 +921,12 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific flush of instruction cache - * + * * @param[in] @code - Start of code * @param[in] @size - Amount to be flushed - * + * * Flush the CPU icache. */ @@ -938,13 +938,13 @@ mono_arch_flush_icache (guint8 *code, gint size) /*========================= End of Function ========================*/ /** - * - * @brief Add an integer register parameter - * + * + * @brief Add an integer register parameter + * * @param[in] @gr - Address of current register number * @param[in] @sz - Stack size data * @param[in] @ainfo - Parameter information - * + * * Assign a parameter to a general register or spill it onto the stack */ @@ -957,11 +957,11 @@ add_general (guint *gr, size_data *sz, ArgInfo *ainfo) ainfo->reg = STK_BASE; ainfo->regtype = RegTypeBase; sz->stack_size += sizeof(long); - sz->code_size += 12; + sz->code_size += 12; } else { ainfo->reg = *gr; ainfo->regtype = RegTypeGeneral; - sz->code_size += 8; + sz->code_size += 8; } (*gr) ++; } @@ -969,15 +969,15 @@ add_general (guint *gr, size_data *sz, ArgInfo *ainfo) /*========================= End of Function ========================*/ /** - * + * * @brief Add a structure variable to parameter list - * + * * @param[in] @gr - Address of current register number * @param[in] @sz - Stack size data * @param[in] @ainfo - Parameter information * @param[in] @size - Size of parameter * @param[in] @type - Type of stack parameter (reference or value) - * + * * Assign a structure address to a register or spill it onto the stack */ @@ -1003,14 +1003,14 @@ add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size, ArgStorage t /*========================= End of Function ========================*/ /** - * + * * @brief Add a floating point register parameter - * + * * @param[in] @fr - Address of current register number * @param[in] @sz - Stack size data * @param[in] @ainfo - Parameter information * @param[in] @isDouble - Precision of parameter - * + * * Assign a parameter to a FP register or spill it onto the stack */ @@ -1038,15 +1038,15 @@ add_float (guint *fr, size_data *sz, ArgInfo *ainfo, gboolean isDouble) /*========================= End of Function ========================*/ /** - * + * * @brief Extract information about call parameters and stack use - * + * * @param[in] @mp - Mono Memory Pool * @param[in] @sig - Mono Method Signature * @returns Information about the parameters and stack usage for a call - * - * Determine the amount of space required for code and stack. In addition - * determine starting points for stack-based parameters, and area for + * + * Determine the amount of space required for code and stack. In addition + * determine starting points for stack-based parameters, and area for * structures being returned on the stack. */ @@ -1130,8 +1130,8 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) simpleType = mono_class_enum_basetype_internal (klass)->type; goto enum_retvalue; } - size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke); - + size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke && !sig->marshalling_disabled); + cinfo->struct_ret = 1; cinfo->ret.size = size; cinfo->ret.vtsize = size; @@ -1139,8 +1139,8 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) } case MONO_TYPE_TYPEDBYREF: { MonoClass *klass = mono_class_from_mono_type_internal (sig->ret); - size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke); - + size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke && !sig->marshalling_disabled); + cinfo->struct_ret = 1; cinfo->ret.size = size; cinfo->ret.vtsize = size; @@ -1161,9 +1161,9 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) * are sometimes made using calli without sig->hasthis set, like in the delegate * invoke wrappers. */ - if (cinfo->struct_ret && !is_pinvoke && - (sig->hasthis || - (sig->param_count > 0 && + if (cinfo->struct_ret && !is_pinvoke && + (sig->hasthis || + (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) { if (sig->hasthis) { cinfo->args[nParm].size = sizeof (target_mgreg_t); @@ -1288,7 +1288,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) MonoMarshalType *info; MonoClass *klass = mono_class_from_mono_type_internal (ptype); - if (sig->pinvoke) + if (sig->pinvoke && !sig->marshalling_disabled) size = mono_class_native_size(klass, NULL); else size = mono_class_value_size(klass, NULL); @@ -1331,7 +1331,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) case 8: add_general(&gr, sz, cinfo->args+nParm); cinfo->args[nParm].size = size; - cinfo->args[nParm].regtype = RegTypeStructByVal; + cinfo->args[nParm].regtype = RegTypeStructByVal; nParm++; break; default: @@ -1364,7 +1364,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) /* * If we are passing a structure back then we make room at - * the end of the parameters that may have been placed on + * the end of the parameters that may have been placed on * the stack */ if (cinfo->struct_ret) { @@ -1382,13 +1382,13 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific allocation of variables - * + * * @param[in] @cfg - Compile control block - * - * Set var information according to the calling convention for s390x. - * + * + * Set var information according to the calling convention for s390x. + * */ void @@ -1406,8 +1406,8 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->flags |= MONO_CFG_HAS_SPILLUP; - /*---------------------------------------------------------*/ - /* We use the frame register also for any method that has */ + /*---------------------------------------------------------*/ + /* We use the frame register also for any method that has */ /* filter clauses. This way, when the handlers are called, */ /* the code will reference local variables using the frame */ /* reg instead of the stack pointer: if we had to restore */ @@ -1415,7 +1415,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* are already on the stack (since filters get called */ /* before stack unwinding happens) when the filter code */ /* would call any method. */ - /*---------------------------------------------------------*/ + /*---------------------------------------------------------*/ if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses) frame_reg = s390_r11; @@ -1423,11 +1423,11 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->arch.bkchain_reg = -1; - if (frame_reg != STK_BASE) - cfg->used_int_regs |= (1LL << frame_reg); + if (frame_reg != STK_BASE) + cfg->used_int_regs |= (1LL << frame_reg); sig = mono_method_signature_internal (cfg->method); - + if (!cfg->arch.cinfo) cfg->arch.cinfo = get_call_info (cfg->mempool, sig); cinfo = cfg->arch.cinfo; @@ -1525,7 +1525,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) switch(size) { case 0: case 1: case 2: case 4: case 8: offStruct = (size < 8 ? sizeof(uintptr_t) - size : 0); - default: + default: inst->opcode = OP_REGOFFSET; inst->dreg = mono_alloc_preg (cfg); inst->inst_basereg = cfg->arch.bkchain_reg; @@ -1552,9 +1552,9 @@ mono_arch_allocate_vars (MonoCompile *cfg) default : if (cinfo->args [iParm].reg == STK_BASE) { /* - * These arguments are in the previous frame, so we can't + * These arguments are in the previous frame, so we can't * compute their offset from the current frame pointer right - * now, since cfg->stack_offset is not yet known, so dedicate a + * now, since cfg->stack_offset is not yet known, so dedicate a * register holding the previous frame pointer. */ cfg->arch.bkchain_reg = s390_r12; @@ -1571,10 +1571,10 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->opcode = OP_REGOFFSET; inst->inst_basereg = frame_reg; size = (cinfo->args[iParm].size < 8 - ? sizeof(int) + ? sizeof(int) : sizeof(long)); offset = S390_ALIGN(offset, size); - if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) inst->inst_offset = offset; else inst->inst_offset = offset + (8 - size); @@ -1590,7 +1590,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) curinst = cfg->locals_start; for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) { inst = cfg->varinfo [iVar]; - if ((inst->flags & MONO_INST_IS_DEAD) || + if ((inst->flags & MONO_INST_IS_DEAD) || (inst->opcode == OP_REGVAR)) continue; @@ -1600,7 +1600,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* when they call functions returning structure */ /*--------------------------------------------------*/ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype)) - size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), + size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), (guint32 *) &align); else size = mono_type_size (inst->inst_vtype, &align); @@ -1610,7 +1610,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->opcode = OP_REGOFFSET; inst->inst_basereg = frame_reg; offset += size; - DEBUG (g_print("allocating local %d to %ld, size: %d\n", + DEBUG (g_print("allocating local %d to %ld, size: %d\n", iVar, inst->inst_offset, size)); } offset = S390_ALIGN(offset, sizeof(uintptr_t)); @@ -1644,13 +1644,13 @@ mono_arch_allocate_vars (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific creation of variables - * + * * @param[in] @cfg - Compile control block - * + * * Create variables for the method. - * + * */ void @@ -1687,15 +1687,15 @@ mono_arch_create_vars (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Add a register to the call operation - * + * * @param[in] @cfg - Compile control block * @param[in] @call - Call Instruction * @param[in] @storage - Register use type * @param[in] @reg - Register number * @param[in] @tree - Call arguments - * + * * Add register use information to the call sequence */ @@ -1734,13 +1734,13 @@ add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int r /*========================= End of Function ========================*/ /** - * + * * @brief Emit a signature cookine - * + * * @param[in] @cfg - Compile control block * @param[in] @call - Call Instruction * @param[in] @cinfo - Call Information - * + * * Emit the signature cooke as a parameter */ @@ -1749,7 +1749,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) { MonoMethodSignature *tmpSig; MonoInst *sig_arg; - + cfg->disable_aot = TRUE; /* @@ -1762,8 +1762,8 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) tmpSig->param_count -= call->signature->sentinelpos; tmpSig->sentinelpos = 0; if (tmpSig->param_count > 0) - memcpy (tmpSig->params, - call->signature->params + call->signature->sentinelpos, + memcpy (tmpSig->params, + call->signature->params + call->signature->sentinelpos, tmpSig->param_count * sizeof(MonoType *)); MONO_INST_NEW (cfg, sig_arg, OP_ICONST); @@ -1771,20 +1771,20 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) sig_arg->inst_p0 = tmpSig; MONO_ADD_INS (cfg->cbb, sig_arg); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE, + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE, cinfo->sigCookie.offset, sig_arg->dreg); } /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific emission of a call operation - * + * * @param[in] @cfg - Compile control block * @param[in] @call - Call Instruction - * - * Process all parameters for a call and generate the sequence of + * + * Process all parameters for a call and generate the sequence of * operations to perform the call according to the s390x ABI. */ @@ -1797,12 +1797,12 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) int i, n, lParamArea; CallInfo *cinfo; ArgInfo *ainfo = NULL; - int stackSize; + int stackSize; sig = call->signature; n = sig->param_count + sig->hasthis; DEBUG (g_print ("Call requires: %d parameters\n",n)); - + cinfo = get_call_info (cfg->mempool, sig); stackSize = cinfo->sz.stack_size + cinfo->sz.parm_size; @@ -1870,11 +1870,11 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } case RegTypeBase : if (!m_type_is_byref (t) && t->type == MONO_TYPE_R4) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, STK_BASE, ainfo->offset + 4, in->dreg); } else if (!m_type_is_byref (t) && (t->type == MONO_TYPE_R8)) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, STK_BASE, ainfo->offset, in->dreg); } else { @@ -1892,7 +1892,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } /* - * Handle the case where there are no implicit arguments + * Handle the case where there are no implicit arguments */ if ((sig->call_convention == MONO_CALL_VARARG) && (!sig->pinvoke) && @@ -1905,13 +1905,13 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific Value Type parameter processing - * + * * @param[in] @cfg - Compile control block * @param[in] @call - Call Instruction * @param[in] @src - Source parameter - * + * * Process value type parameters for a call operation */ @@ -1926,7 +1926,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) emit_outarg_vtr (cfg, ins, src); } else { emit_outarg_vts (cfg, ins, src); - } + } } else if (ainfo->regtype == RegTypeStructByValInFP) { int dreg = mono_alloc_freg (cfg); @@ -1950,7 +1950,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) guint32 size; /* FIXME: alignment? */ - if (call->signature->pinvoke) { + if (call->signature->pinvoke && !call->signature->marshalling_disabled) { size = mono_type_native_stack_size (m_class_get_byval_arg (src->klass), NULL); vtcopy->backend.is_pinvoke = 1; } else { @@ -1985,13 +1985,13 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific call value return processing - * + * * @param[in] @cfg - Compile control block * @param[in] @method - Method * @param[in] @val - Instruction representing the result returned to method - * + * * Create the sequence to unload the value returned from a call */ @@ -2009,21 +2009,21 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) return; } } - + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg); } /*========================= End of Function ========================*/ /** - * + * * @brief Replace compound compare/branch operations with single operation - * + * * @param[in] @bb - Basic block * @param[in] @ins - Current instruction * @param[in] @cc - Condition code of branch * @param[in] @logical - Whether comparison is signed or logical - * + * * Form a peephole pass at the code looking for simple optimizations * that will combine compare/branch instructions into a single operation. */ @@ -2078,12 +2078,12 @@ compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical) /*========================= End of Function ========================*/ /** - * + * * @brief Architecure-specific peephole pass 1 processing - * + * * @param[in] @cfg - Compile control block * @param[in] @bb - Basic block - * + * * Form a peephole pass at the code looking for compare and branch * optimizations. */ @@ -2145,12 +2145,12 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) /*========================= End of Function ========================*/ /** - * + * * @brief Architecure-specific peephole pass 2 processing - * + * * @param[in] @cfg - Compile control block * @param[in] @bb - Basic block - * + * * Form a peephole pass at the code looking for simple optimizations. */ @@ -2178,12 +2178,12 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) /*========================= End of Function ========================*/ /** - * + * * @brief Architecure-specific lowering pass processing - * + * * @param[in] @cfg - Compile control block * @param[in] @bb - Basic block - * + * * Form a lowering pass at the code looking for simple optimizations. */ @@ -2223,9 +2223,9 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) /*========================= End of Function ========================*/ /** - * + * * @brief Emit float-to-int sequence - * + * * @param[in] @cfg - Compile control block * @param[in] @code - Current instruction area * @param[in] @dreg - Destination general register @@ -2233,7 +2233,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) * @param[in] @size - Size of destination * @param[in] @is_signed - Destination is signed/unsigned * @returns Next instruction location - * + * * Emit instructions to convert a single precision floating point value to an integer */ @@ -2276,7 +2276,7 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, PTRSLOT (code, o[0]); s390_cfebr (code, dreg, 5, sreg); switch (size) { - case 1: + case 1: s390_lghi (code, s390_r0, 0xff); s390_ngr (code, dreg, s390_r0); break; @@ -2294,9 +2294,9 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, /*========================= End of Function ========================*/ /** - * + * * @brief Emit double-to-int sequence - * + * * @param[in] @cfg - Compile control block * @param[in] @code - Current instruction area * @param[in] @dreg - Destination general register @@ -2304,7 +2304,7 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, * @param[in] @size - Size of destination * @param[in] @is_signed - Destination is signed/unsigned * @returns Next instruction location - * + * * Emit instructions to convert a single precision floating point value to an integer */ @@ -2347,7 +2347,7 @@ emit_double_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size PTRSLOT (code, o[0]); s390_cfdbr (code, dreg, 5, sreg); switch (size) { - case 1: + case 1: s390_lghi (code, s390_r0, 0xff); s390_ngr (code, dreg, s390_r0); break; @@ -2365,21 +2365,21 @@ emit_double_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size /*========================= End of Function ========================*/ /** - * + * * @brief Check if branch is for unsigned comparison - * + * * @param[in] @next - Next instruction * @returns True if the branch is for an unsigned comparison - * + * * Determine if next instruction is a branch for an unsigned comparison */ -static gboolean +static gboolean is_unsigned (MonoInst *next) { - if ((next) && + if ((next) && (((next->opcode >= OP_IBNE_UN) && - (next->opcode <= OP_IBLT_UN)) || + (next->opcode <= OP_IBLT_UN)) || ((next->opcode >= OP_LBNE_UN) && (next->opcode <= OP_LBLT_UN)) || ((next->opcode >= OP_COND_EXC_NE_UN) && @@ -2402,12 +2402,12 @@ is_unsigned (MonoInst *next) /*========================= End of Function ========================*/ /** - * + * * @brief Architecutre-specific processing of a basic block - * + * * @param[in] @cfg - Compile control block * @param[in] @bb - Basic block - * + * * Process instructions within basic block emitting s390x instructions * based on the VM operation codes */ @@ -2436,47 +2436,47 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) switch (ins->opcode) { case OP_STOREI1_MEMBASE_IMM: { s390_lghi (code, s390_r0, ins->inst_imm); - S390_LONG (code, stcy, stc, s390_r0, 0, + S390_LONG (code, stcy, stc, s390_r0, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STOREI2_MEMBASE_IMM: { s390_lghi (code, s390_r0, ins->inst_imm); - S390_LONG (code, sthy, sth, s390_r0, 0, + S390_LONG (code, sthy, sth, s390_r0, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STOREI4_MEMBASE_IMM: { s390_lgfi (code, s390_r0, ins->inst_imm); - S390_LONG (code, sty, st, s390_r0, 0, + S390_LONG (code, sty, st, s390_r0, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STORE_MEMBASE_IMM: case OP_STOREI8_MEMBASE_IMM: { S390_SET (code, s390_r0, ins->inst_imm); - S390_LONG (code, stg, stg, s390_r0, 0, + S390_LONG (code, stg, stg, s390_r0, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STOREI1_MEMBASE_REG: { - S390_LONG (code, stcy, stc, ins->sreg1, 0, + S390_LONG (code, stcy, stc, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STOREI2_MEMBASE_REG: { - S390_LONG (code, sthy, sth, ins->sreg1, 0, + S390_LONG (code, sthy, sth, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STOREI4_MEMBASE_REG: { - S390_LONG (code, sty, st, ins->sreg1, 0, + S390_LONG (code, sty, st, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_STORE_MEMBASE_REG: case OP_STOREI8_MEMBASE_REG: { - S390_LONG (code, stg, stg, ins->sreg1, 0, + S390_LONG (code, stg, stg, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } break; @@ -2485,37 +2485,37 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_LOAD_MEMBASE: case OP_LOADI8_MEMBASE: { - S390_LONG (code, lg, lg, ins->dreg, 0, + S390_LONG (code, lg, lg, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADI4_MEMBASE: { - S390_LONG (code, lgf, lgf, ins->dreg, 0, + S390_LONG (code, lgf, lgf, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADU4_MEMBASE: { - S390_LONG (code, llgf, llgf, ins->dreg, 0, + S390_LONG (code, llgf, llgf, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADU1_MEMBASE: { - S390_LONG (code, llgc, llgc, ins->dreg, 0, + S390_LONG (code, llgc, llgc, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADI1_MEMBASE: { - S390_LONG (code, lgb, lgb, ins->dreg, 0, + S390_LONG (code, lgb, lgb, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADU2_MEMBASE: { - S390_LONG (code, llgh, llgh, ins->dreg, 0, + S390_LONG (code, llgh, llgh, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_LOADI2_MEMBASE: { - S390_LONG (code, lgh, lgh, ins->dreg, 0, + S390_LONG (code, lgh, lgh, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; @@ -2559,7 +2559,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lgfr (code, ins->dreg, ins->sreg1); } break; - case OP_COMPARE: + case OP_COMPARE: case OP_LCOMPARE: { if (is_unsigned (ins->next)) s390_clgr (code, ins->sreg1, ins->sreg2); @@ -2660,7 +2660,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) S390_SET (code, s390_r0, ins->inst_imm); s390_agrk (code, ins->dreg, ins->sreg1, s390_r0); } - } else { + } else { if (ins->dreg != ins->sreg1) { s390_lgr (code, ins->dreg, ins->sreg1); } @@ -2806,10 +2806,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } else { if (ins->sreg1 == ins->dreg) { s390_ngr (code, ins->dreg, ins->sreg2); - } else { - if (ins->sreg2 == ins->dreg) { + } else { + if (ins->sreg2 == ins->dreg) { s390_ngr (code, ins->dreg, ins->sreg1); - } else { + } else { s390_lgr (code, ins->dreg, ins->sreg1); s390_ngr (code, ins->dreg, ins->sreg2); } @@ -2872,10 +2872,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } else { if (ins->sreg1 == ins->dreg) { s390_ogr (code, ins->dreg, ins->sreg2); - } else { - if (ins->sreg2 == ins->dreg) { + } else { + if (ins->sreg2 == ins->dreg) { s390_ogr (code, ins->dreg, ins->sreg1); - } else { + } else { s390_lgr (code, ins->dreg, ins->sreg1); s390_ogr (code, ins->dreg, ins->sreg2); } @@ -2901,12 +2901,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } else { if (ins->sreg1 == ins->dreg) { s390_xgr (code, ins->dreg, ins->sreg2); - } - else { - if (ins->sreg2 == ins->dreg) { + } + else { + if (ins->sreg2 == ins->dreg) { s390_xgr (code, ins->dreg, ins->sreg1); } - else { + else { s390_lgr (code, ins->dreg, ins->sreg1); s390_xgr (code, ins->dreg, ins->sreg2); } @@ -2931,7 +2931,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_sllg (code, ins->dreg, ins->dreg, src2, 0); } break; - case OP_SHL_IMM: + case OP_SHL_IMM: case OP_LSHL_IMM: { if (ins->sreg1 != ins->dreg) { s390_lgr (code, ins->dreg, ins->sreg1); @@ -2952,7 +2952,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f)); } break; - case OP_SHR_UN_IMM: + case OP_SHR_UN_IMM: case OP_LSHR_UN_IMM: { if (ins->sreg1 != ins->dreg) { s390_lgr (code, ins->dreg, ins->sreg1); @@ -2982,7 +2982,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_msgr (code, ins->dreg, src2); } break; - case OP_MUL_IMM: + case OP_MUL_IMM: case OP_LMUL_IMM: { if (ins->dreg != ins->sreg1) { s390_lgr (code, ins->dreg, ins->sreg1); @@ -3020,7 +3020,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_srlg (code, s390_r0, s390_r0, 0, 63); s390_ltgr (code, s390_r0, s390_r0); EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException"); - PTRSLOT (code, o[0]); + PTRSLOT (code, o[0]); PTRSLOT (code, o[1]); s390_lgr (code, ins->dreg, s390_r1); } @@ -3066,7 +3066,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IADC_IMM: { if (ins->dreg != ins->sreg1) { s390_lgfr (code, ins->dreg, ins->sreg1); - } + } if (s390_is_imm16 (ins->inst_imm)) { s390_lghi (code, s390_r0, ins->inst_imm); s390_alcgr (code, ins->dreg, s390_r0); @@ -3080,7 +3080,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_S390_LADD_OVF: { if (mono_hwcap_s390x_has_mlt) { s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2); - } else { + } else { CHECK_SRCDST_COM; s390_agr (code, ins->dreg, src2); } @@ -3091,7 +3091,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_S390_LADD_OVF_UN: { if (mono_hwcap_s390x_has_mlt) { s390_algrk (code, ins->dreg, ins->sreg1, ins->sreg2); - } else { + } else { CHECK_SRCDST_COM; s390_algr (code, ins->dreg, src2); } @@ -3142,7 +3142,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (mono_hwcap_s390x_has_mlt) { s390_srk (code, ins->dreg, ins->sreg1, ins->sreg2); EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); - } else { + } else { CHECK_SRCDST_NCOM; s390_sr (code, ins->dreg, src2); EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); @@ -3393,19 +3393,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lgfr (code, ins->dreg, s390_r1); } break; - case OP_ICONST: + case OP_ICONST: case OP_I8CONST: { S390_SET (code, ins->dreg, ins->inst_c0); } break; case OP_AOTCONST: { - mono_add_patch_info (cfg, code - cfg->native_code, + mono_add_patch_info (cfg, code - cfg->native_code, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0); S390_LOAD_TEMPLATE (code, ins->dreg); } break; case OP_JUMP_TABLE: { - mono_add_patch_info (cfg, code - cfg->native_code, + mono_add_patch_info (cfg, code - cfg->native_code, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0); S390_LOAD_TEMPLATE (code, ins->dreg); } @@ -3460,10 +3460,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (ins->dreg != ins->sreg1) s390_ldr (code, ins->dreg, ins->sreg1); break; - case OP_MOVE_F_TO_I8: + case OP_MOVE_F_TO_I8: s390_lgdr (code, ins->dreg, ins->sreg1); break; - case OP_MOVE_I8_TO_F: + case OP_MOVE_I8_TO_F: s390_ldgr (code, ins->dreg, ins->sreg1); break; case OP_MOVE_F_TO_I4: @@ -3475,7 +3475,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } s390_srag (code, ins->dreg, ins->dreg, 0, 32); break; - case OP_MOVE_I4_TO_F: + case OP_MOVE_I4_TO_F: s390_slag (code, s390_r0, ins->sreg1, 0, 32); s390_ldgr (code, ins->dreg, s390_r0); if (!cfg->r4fp) @@ -3532,13 +3532,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* * Restore SP to caller's SP - */ + */ code = backUpStackPtr(cfg, code); /* * If the destination is specified as a register or membase then * save destination so it doesn't get overwritten by the restores - */ + */ if (ins->opcode != OP_TAILCALL) s390_lgr (code, s390_r1, ins->sreg1); @@ -3561,7 +3561,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* * Restore any FP registers that have been altered - */ + */ if (cfg->arch.fpSize != 0) { int fpOffset = -cfg->arch.fpSize; for (int i = 8; i < 16; i++) { @@ -3574,7 +3574,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (ins->opcode == OP_TAILCALL_REG) { s390_br (code, s390_r1); - } else { + } else { if (ins->opcode == OP_TAILCALL_MEMBASE) { if (mono_hwcap_s390x_has_mie2) { s390_bi (code, 0, s390_r1, ins->inst_offset); @@ -3584,7 +3584,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } } else { mono_add_patch_info_rel (cfg, code - cfg->native_code, - MONO_PATCH_INFO_METHOD_JUMP, + MONO_PATCH_INFO_METHOD_JUMP, call->method, MONO_R_S390_THUNKED); S390_BR_TEMPLATE (code, s390_r1); cfg->thunk_area += THUNK_SIZE; @@ -3692,7 +3692,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lg (code, s390_r13, 0, STK_BASE, 0); /* - * Round object size to doubleword + * Round object size to doubleword */ s390_lgr (code, s390_r1, ins->sreg1); s390_aghi (code, s390_r1, 7); @@ -3701,7 +3701,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (mono_hwcap_s390x_has_gie) { if (ins->flags & MONO_INST_INIT) - s390_lgr (code, s390_r0, s390_r1); + s390_lgr (code, s390_r0, s390_r1); s390_risbg (code, ins->dreg, s390_r1, 0, 0xb3, 0); s390_sgrk (code, ins->dreg, STK_BASE, ins->dreg); @@ -3734,7 +3734,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lghi (code, s390_r0, 0); s390_stg (code, s390_r0, 0, STK_BASE, 4088); s390_j (code, -11); /* j L0 */ - + s390_lghi (code, ins->dreg, 4095); /* L1: */ s390_ngr (code, ins->dreg, s390_r1); s390_ltgr (code, ins->dreg, ins->dreg); @@ -3744,11 +3744,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_stg (code, ins->dreg, s390_r1, STK_BASE, -8); /* L2: */ if (ins->flags & MONO_INST_INIT) - s390_lgr (code, s390_r0, s390_r1); + s390_lgr (code, s390_r0, s390_r1); } - /* - * Compute address of localloc'd object + /* + * Compute address of localloc'd object */ s390_lgr (code, s390_r1, STK_BASE); if (s390_is_imm16(area_offset)) @@ -3811,7 +3811,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region); S390_LONG (code, stg, stg, s390_r14, 0, - spvar->inst_basereg, + spvar->inst_basereg, spvar->inst_offset); } break; @@ -3821,7 +3821,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (ins->sreg1 != s390_r2) s390_lgr(code, s390_r2, ins->sreg1); S390_LONG (code, lg, lg, s390_r14, 0, - spvar->inst_basereg, + spvar->inst_basereg, spvar->inst_offset); s390_br (code, s390_r14); } @@ -3830,7 +3830,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region); S390_LONG (code, lg, lg, s390_r14, 0, - spvar->inst_basereg, + spvar->inst_basereg, spvar->inst_offset); s390_br (code, s390_r14); } @@ -3887,9 +3887,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) displace = ((uintptr_t) code - (uintptr_t) o[0]) / 2; o[0]->i2 = displace; } - - /* - * This is the address which is saved in seq points, + + /* + * This is the address which is saved in seq points, */ mono_add_seq_point (cfg, bb, ins, code - cfg->native_code); @@ -3944,14 +3944,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ins->backend.pc_offset = code - cfg->native_code; break; } - case OP_BR: + case OP_BR: EMIT_UNCOND_BRANCH(ins); break; case OP_BR_REG: { s390_br (code, ins->sreg1); } break; - case OP_CEQ: + case OP_CEQ: case OP_ICEQ: case OP_LCEQ: { s390_lghi(code, ins->dreg, 1); @@ -3959,7 +3959,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lghi(code, ins->dreg, 0); } break; - case OP_CLT: + case OP_CLT: case OP_ICLT: case OP_LCLT: { s390_lghi(code, ins->dreg, 1); @@ -3975,7 +3975,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lghi(code, ins->dreg, 0); } break; - case OP_CGT: + case OP_CGT: case OP_ICGT: case OP_LCGT: { s390_lghi(code, ins->dreg, 1); @@ -4072,29 +4072,29 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_LBEQ: case OP_IBEQ: EMIT_COND_BRANCH (ins, S390_CC_EQ); - break; + break; case OP_LBNE_UN: case OP_IBNE_UN: EMIT_COND_BRANCH (ins, S390_CC_NE); - break; + break; case OP_LBLT: case OP_LBLT_UN: case OP_IBLT: case OP_IBLT_UN: EMIT_COND_BRANCH (ins, S390_CC_LT); - break; + break; case OP_LBGT: case OP_LBGT_UN: case OP_IBGT: case OP_IBGT_UN: EMIT_COND_BRANCH (ins, S390_CC_GT); - break; + break; case OP_LBGE: case OP_LBGE_UN: case OP_IBGE: case OP_IBGE_UN: EMIT_COND_BRANCH (ins, S390_CC_GE); - break; + break; case OP_LBLE: case OP_LBLE_UN: case OP_IBLE: @@ -4170,22 +4170,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_STORER8_MEMBASE_REG: { - S390_LONG (code, stdy, std, ins->sreg1, 0, + S390_LONG (code, stdy, std, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } break; case OP_LOADR8_MEMBASE: { - S390_LONG (code, ldy, ld, ins->dreg, 0, + S390_LONG (code, ldy, ld, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } break; case OP_STORER4_MEMBASE_REG: { if (cfg->r4fp) { - S390_LONG (code, stey, ste, ins->sreg1, 0, + S390_LONG (code, stey, ste, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); } else { s390_ledbr (code, ins->sreg1, ins->sreg1); - S390_LONG (code, stey, ste, ins->sreg1, 0, + S390_LONG (code, stey, ste, ins->sreg1, 0, ins->inst_destbasereg, ins->inst_offset); s390_ldebr (code, ins->sreg1, ins->sreg1); } @@ -4193,10 +4193,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_LOADR4_MEMBASE: { if (cfg->r4fp) { - S390_LONG (code, ley, le, ins->dreg, 0, + S390_LONG (code, ley, le, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); } else { - S390_LONG (code, ley, le, ins->dreg, 0, + S390_LONG (code, ley, le, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); s390_ldebr (code, ins->dreg, ins->dreg); } @@ -4379,7 +4379,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_jz (code, 0); CODEPTR(code, o[4]); PTRSLOT(code, o[1]); PTRSLOT(code, o[2]); - mono_add_patch_info (cfg, code - cfg->native_code, + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, "OverflowException"); s390_brasl (code, s390_r14, 0); PTRSLOT(code, o[3]); @@ -4435,37 +4435,37 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FSUB: { CHECK_SRCDST_NCOM_F(sdbr); } - break; + break; case OP_RSUB: { CHECK_SRCDST_NCOM_F(sebr); } - break; + break; case OP_FMUL: { CHECK_SRCDST_COM_F; s390_mdbr (code, ins->dreg, src2); } - break; + break; case OP_RMUL: { CHECK_SRCDST_COM_F; s390_meer (code, ins->dreg, src2); } - break; + break; case OP_FDIV: { CHECK_SRCDST_NCOM_F(ddbr); } - break; + break; case OP_RDIV: { CHECK_SRCDST_NCOM_F(debr); } - break; + break; case OP_FNEG: { s390_lcdbr (code, ins->dreg, ins->sreg1); } - break; + break; case OP_RNEG: { s390_lcebr (code, ins->dreg, ins->sreg1); } - break; + break; case OP_FREM: { CHECK_SRCDST_NCOM_FR(didbr, 5); } @@ -4673,7 +4673,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lhi (code, s390_r13, 0x7f); s390_tcdb (code, ins->sreg1, 0, s390_r13, 0); s390_jz (code, 0); CODEPTR(code, o); - mono_add_patch_info (cfg, code - cfg->native_code, + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, "OverflowException"); s390_brasl (code, s390_r14,0); PTRSLOT(code, o); @@ -4682,7 +4682,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_S390_MOVE: { if (ins->backend.size > 0) { if (ins->backend.size <= 256) { - s390_mvc (code, ins->backend.size, ins->sreg2, + s390_mvc (code, ins->backend.size, ins->sreg2, ins->inst_offset, ins->sreg1, ins->inst_imm); } else { s390_lgr (code, s390_r0, ins->sreg2); @@ -4740,14 +4740,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lgr (code, ins->dreg, s390_r1); } } - break; + break; case OP_ATOMIC_EXCHANGE_I8: { s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset); s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset); s390_jnz (code, -6); s390_lgr (code, ins->dreg, s390_r0); } - break; + break; case OP_ATOMIC_ADD_I4: { if (mono_hwcap_s390x_has_ia) { s390_laa (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset); @@ -4762,14 +4762,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lgfr(code, ins->dreg, s390_r1); } } - break; + break; case OP_ATOMIC_EXCHANGE_I4: { s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset); s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset); s390_jnz (code, -4); s390_lgfr(code, ins->dreg, s390_r0); } - break; + break; case OP_S390_BKCHAIN: { s390_lgr (code, ins->dreg, ins->sreg1); if (s390_is_imm16 (cfg->stack_offset)) { @@ -4781,7 +4781,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_agr (code, ins->dreg, s390_r13); } } - break; + break; case OP_MEMORY_BARRIER: s390_mem (code); break; @@ -4826,7 +4826,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_GC_SAFE_POINT: { short *br; - s390_ltg (code, s390_r0, 0, ins->sreg1, 0); + s390_ltg (code, s390_r0, 0, ins->sreg1, 0); s390_jz (code, 0); CODEPTR(code, br); code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll)); @@ -5022,7 +5022,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PMAXD_UN: s390x_pmaxud (code, ins->sreg1, ins->sreg2); break; - + case OP_PMAXB: s390x_pmaxsb (code, ins->sreg1, ins->sreg2); break; @@ -5166,7 +5166,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PSUBW_SAT: s390x_psubsw (code, ins->sreg1, ins->sreg2); break; - + case OP_PMULW: s390x_pmullw (code, ins->sreg1, ins->sreg2); break; @@ -5231,22 +5231,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PSHRQ_REG: s390x_psrlq (code, ins->dreg, ins->sreg2); break; - + /*TODO: This is appart of the sse spec but not added case OP_PSARQ: s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm); break; case OP_PSARQ_REG: s390x_psraq (code, ins->dreg, ins->sreg2); - break; + break; */ - + case OP_PSHLQ: s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm); break; case OP_PSHLQ_REG: s390x_psllq (code, ins->dreg, ins->sreg2); - break; + break; case OP_CVTDQ2PD: s390x_cvtdq2pd (code, ins->dreg, ins->sreg1); break; @@ -5404,7 +5404,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /*FIXME the peephole pass should have killed this*/ if (ins->dreg != ins->sreg1) s390x_movaps (code, ins->dreg, ins->sreg1); - break; + break; case OP_XZERO: s390x_pxor (code, ins->dreg, ins->dreg); break; @@ -5431,7 +5431,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCONV_TO_U2: amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE); break; - } + } break; case OP_EXPAND_I2: @@ -5479,9 +5479,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific registration of lowlevel calls - * + * * Register routines to register optimized lowlevel operations */ @@ -5493,7 +5493,7 @@ mono_arch_register_lowlevel_calls (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific patching * @param[in] @cfg - Compilation control block * @param[in] @code - Start of code @@ -5544,14 +5544,14 @@ emit_patch_full (MonoCompile *cfg, MonoJumpInfo *ji, guint8 *code, /** * * @brief Architecture-specific patching of instructions and data - * + * * @param[in] @cfg - Compile control block * @param[in] @method - Current method * @param[in] @code - Current code block - * @param[in] @ji - Jump information + * @param[in] @ji - Jump information * @param[in] @target - Target of patch * - * Process the patch data created during the instruction build process. + * Process the patch data created during the instruction build process. * This resolves jumps, calls, variables etc. */ @@ -5561,8 +5561,8 @@ mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpoi switch (ji->type) { case MONO_PATCH_INFO_IP: case MONO_PATCH_INFO_LDSTR: - case MONO_PATCH_INFO_TYPE_FROM_HANDLE: - case MONO_PATCH_INFO_LDTOKEN: + case MONO_PATCH_INFO_TYPE_FROM_HANDLE: + case MONO_PATCH_INFO_LDTOKEN: case MONO_PATCH_INFO_EXC: emit_patch_full (cfg, ji, code, target, MONO_R_S390_ADDR); break; @@ -5578,7 +5578,7 @@ mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpoi case MONO_PATCH_INFO_ABS: emit_patch_full (cfg, ji, code, target, MONO_R_S390_THUNKED); break; - case MONO_PATCH_INFO_SWITCH: + case MONO_PATCH_INFO_SWITCH: emit_patch_full(cfg, ji, code, target, MONO_R_S390_SWITCH); break; case MONO_PATCH_INFO_METHODCONST: @@ -5599,9 +5599,9 @@ mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpoi /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific prolog generation - * + * * @param[in] @cfg - Compile control block * @returns Location of code code generated * @@ -5636,7 +5636,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /** * Create unwind information - */ + */ mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, S390_CFA_OFFSET); s390_stmg (code, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); emit_unwind_regs(cfg, code, s390_r6, s390_r15, S390_REG_SAVE_OFFSET - S390_CFA_OFFSET); @@ -5645,17 +5645,17 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* * If there are local allocations the R11 becomes the frame register - */ + */ if (cfg->flags & MONO_CFG_HAS_ALLOCA) { cfg->used_int_regs |= 1 << s390_r11; } /* * Check if FP registers need preserving - */ + */ if ((cfg->arch.used_fp_regs & S390_FP_SAVE_MASK) != 0) { for (int i = s390_f8; i <= s390_f15; i++) { - if (cfg->arch.used_fp_regs & (1 << i)) + if (cfg->arch.used_fp_regs & (1 << i)) fpOffset += sizeof(double); } fpOffset = S390_ALIGN(fpOffset, sizeof(double)); @@ -5664,14 +5664,14 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* * Calculate stack requirements - */ + */ alloc_size = cfg->stack_offset + fpOffset; cfg->stack_usage = cfa_offset = alloc_size; s390_lgr (code, s390_r11, STK_BASE); if (s390_is_imm16 (alloc_size)) { s390_aghi (code, STK_BASE, -alloc_size); - } else if (s390_is_imm32 (alloc_size)) { + } else if (s390_is_imm32 (alloc_size)) { s390_agfi (code, STK_BASE, -alloc_size); } else { int stackSize = alloc_size; @@ -5692,7 +5692,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) for (int i = s390_f8; i <= s390_f15; i++) { if (cfg->arch.used_fp_regs & (1 << i)) { s390_std (code, i, 0, s390_r1, stkOffset); - emit_unwind_regs(cfg, code, 16+i, 16+i, stkOffset+fpOffset - S390_CFA_OFFSET); + emit_unwind_regs(cfg, code, 16+i, 16+i, stkOffset+fpOffset - S390_CFA_OFFSET); stkOffset += sizeof(double); } } @@ -5707,8 +5707,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (cfg->rgctx_var) { g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET); - s390_stg (code, MONO_ARCH_RGCTX_REG, 0, - cfg->rgctx_var->inst_basereg, + s390_stg (code, MONO_ARCH_RGCTX_REG, 0, + cfg->rgctx_var->inst_basereg, cfg->rgctx_var->inst_offset); } @@ -5717,7 +5717,7 @@ char *methodName = getenv("MONO_TRACE_METHOD"); if (methodName != NULL) { printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,method->name);fflush(stdout); // Tests:set_ip -//if ((strcmp(method->klass->name_space,"") == 0) && +//if ((strcmp(method->klass->name_space,"") == 0) && // (strcmp(method->klass->name,"Tests") == 0) && // (strcmp(method->name, "set_ip") == 0)) { // (strcmp("CancellationToken,TaskCreationOptions,TaskContinuationOptions,TaskScheduler",mono_signature_get_desc(method->signature, FALSE)) != 0)) { @@ -5730,7 +5730,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth /* compute max_offset in order to use short forward jumps * we always do it on s390 because the immediate displacement - * for jumps is too small + * for jumps is too small */ max_offset = 0; for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { @@ -5764,7 +5764,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = cinfo->args + i; inst = cfg->args [pos]; - + if (inst->opcode == OP_VTARG_ADDR) inst = inst->inst_left; @@ -5776,7 +5776,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth s390_ldr (code, inst->dreg, ainfo->reg); } } else if (ainfo->regtype == RegTypeFPR4) { - if (!cfg->r4fp) + if (!cfg->r4fp) s390_ledbr (code, inst->dreg, ainfo->reg); } else if (ainfo->regtype == RegTypeBase) { s390_lgr (code, s390_r13, STK_BASE); @@ -5786,7 +5786,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth g_assert_not_reached (); if (cfg->verbose_level > 2) - g_print ("Argument %d assigned to register %s\n", + g_print ("Argument %d assigned to register %s\n", pos, mono_arch_regname (inst->dreg)); } else { if (ainfo->regtype == RegTypeGeneral) { @@ -5799,7 +5799,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth case 2: s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset); break; - case 4: + case 4: s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset); break; case 8: @@ -5814,7 +5814,7 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth } else if (ainfo->regtype == RegTypeStructByVal) { int doffset = inst->inst_offset; - size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE + size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && sig->pinvoke && !sig->marshalling_disabled ? mono_class_native_size(mono_class_from_mono_type_internal (inst->inst_vtype), NULL) : ainfo->size); @@ -5849,15 +5849,15 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth if (method->save_lmf) { /** - * Build the MonoLMF structure on the stack - see mini-s390x.h + * Build the MonoLMF structure on the stack - see mini-s390x.h */ - lmfOffset = alloc_size - sizeof(MonoLMF); - - s390_lgr (code, s390_r13, cfg->frame_reg); - s390_aghi (code, s390_r13, lmfOffset); - + lmfOffset = alloc_size - sizeof(MonoLMF); + + s390_lgr (code, s390_r13, cfg->frame_reg); + s390_aghi (code, s390_r13, lmfOffset); + /* - * Preserve the parameter registers while we fix up the lmf + * Preserve the parameter registers while we fix up the lmf */ s390_stmg (code, s390_r2, s390_r6, s390_r13, MONO_STRUCT_OFFSET(MonoLMF, pregs)); @@ -5874,65 +5874,65 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth /* * Set lmf.lmf_addr = jit_tls->lmf */ - s390_stg (code, s390_r2, 0, s390_r13, - MONO_STRUCT_OFFSET(MonoLMF, lmf_addr)); + s390_stg (code, s390_r2, 0, s390_r13, + MONO_STRUCT_OFFSET(MonoLMF, lmf_addr)); mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF); - + /* * Get current lmf */ - s390_lg (code, s390_r0, 0, s390_r2, 0); - + s390_lg (code, s390_r0, 0, s390_r2, 0); + /* * Set our lmf as the current lmf */ - s390_stg (code, s390_r13, 0, s390_r2, 0); - + s390_stg (code, s390_r13, 0, s390_r2, 0); + /* * Have our lmf.previous_lmf point to the last lmf */ - s390_stg (code, s390_r0, 0, s390_r13, - MONO_STRUCT_OFFSET(MonoLMF, previous_lmf)); + s390_stg (code, s390_r0, 0, s390_r13, + MONO_STRUCT_OFFSET(MonoLMF, previous_lmf)); mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF); - + /* * Save method info */ S390_SET (code, s390_r1, method); - s390_stg (code, s390_r1, 0, s390_r13, - MONO_STRUCT_OFFSET(MonoLMF, method)); + s390_stg (code, s390_r1, 0, s390_r13, + MONO_STRUCT_OFFSET(MonoLMF, method)); mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF); - + /* * Save the current IP */ s390_stg (code, STK_BASE, 0, s390_r13, MONO_STRUCT_OFFSET(MonoLMF, ebp)); s390_basr (code, s390_r1, 0); - s390_stg (code, s390_r1, 0, s390_r13, MONO_STRUCT_OFFSET(MonoLMF, eip)); + s390_stg (code, s390_r1, 0, s390_r13, MONO_STRUCT_OFFSET(MonoLMF, eip)); mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF); mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF); - + /* * Save general and floating point registers */ - s390_stmg (code, s390_r2, s390_r12, s390_r13, - MONO_STRUCT_OFFSET(MonoLMF, gregs) + 2 * sizeof(gulong)); + s390_stmg (code, s390_r2, s390_r12, s390_r13, + MONO_STRUCT_OFFSET(MonoLMF, gregs) + 2 * sizeof(gulong)); for (i = 0; i < 11; i++) mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs) + i * sizeof(gulong), SLOT_NOREF); fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs); - for (i = 0; i < 16; i++) { - s390_std (code, i, 0, s390_r13, + for (i = 0; i < 16; i++) { + s390_std (code, i, 0, s390_r13, MONO_STRUCT_OFFSET(MonoLMF, fregs) + i * sizeof(gulong)); mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF); fpOffset += sizeof(double); - } + } /* * Restore the parameter registers now that we've set up the lmf */ - s390_lmg (code, s390_r2, s390_r6, s390_r13, - MONO_STRUCT_OFFSET(MonoLMF, pregs)); + s390_lmg (code, s390_r2, s390_r6, s390_r13, + MONO_STRUCT_OFFSET(MonoLMF, pregs)); } if (cfg->method->save_lmf) @@ -5965,9 +5965,9 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth if (inst->opcode != OP_REGVAR) { switch (ainfo->regtype) { case RegTypeGeneral: { - if (((next->opcode == OP_LOAD_MEMBASE) || - (next->opcode == OP_LOADI4_MEMBASE)) && - next->inst_basereg == inst->inst_basereg && + if (((next->opcode == OP_LOAD_MEMBASE) || + (next->opcode == OP_LOADI4_MEMBASE)) && + next->inst_basereg == inst->inst_basereg && next->inst_offset == inst->inst_offset) { if (next->dreg == ainfo->reg) { NULLIFY_INS (next); @@ -5989,8 +5989,8 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth /* Argument allocated to (non-volatile) register */ switch (ainfo->regtype) { case RegTypeGeneral: - if (next->opcode == OP_MOVE && - next->sreg1 == inst->dreg && + if (next->opcode == OP_MOVE && + next->sreg1 == inst->dreg && next->dreg == ainfo->reg) { NULLIFY_INS (next); match = TRUE; @@ -6035,9 +6035,9 @@ printf("ns: %s k: %s m: %s\n",method->klass->name_space,method->klass->name,meth /*========================= End of Function ========================*/ /** - * + * * @brief Architecutre-specific epilog generation - * + * * @param[in] @cfg - Compile control block * * Create the instruction sequence for exit from a method @@ -6050,10 +6050,10 @@ mono_arch_emit_epilog (MonoCompile *cfg) guint8 *code; int max_epilog_size = 96, i; int fpOffset = 0; - + if (cfg->method->save_lmf) max_epilog_size += 128; - + code = realloc_code (cfg, max_epilog_size); cfg->has_unwind_info_for_epilog = TRUE; @@ -6064,7 +6064,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) /* Save the uwind state which is needed by the out-of-line code */ mono_emit_unwind_op_remember_state (cfg, code); - if (method->save_lmf) + if (method->save_lmf) restoreLMF(code, cfg->frame_reg, cfg->stack_usage); code = backUpStackPtr(cfg, code); @@ -6083,7 +6083,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) } s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); - for (i = s390_r6; i < s390_r15; i++) + for (i = s390_r6; i < s390_r15; i++) mono_emit_unwind_op_same_value (cfg, code, i); s390_br (code, s390_r14); @@ -6100,16 +6100,16 @@ mono_arch_emit_epilog (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific exception emission - * + * * @param[in] @cfg - Compile control block * * Create the instruction sequence for exception handling */ void -mono_arch_emit_exceptions (MonoCompile *cfg) +mono_arch_emit_exceptions (MonoCompile *cfg) { MonoJumpInfo *patch_info; guint8 *code; @@ -6120,8 +6120,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg) MonoClass *exc_classes [MAX_EXC]; guint8 *exc_throw_start [MAX_EXC]; - for (patch_info = cfg->patch_info; - patch_info; + for (patch_info = cfg->patch_info; + patch_info; patch_info = patch_info->next) { if (patch_info->type == MONO_PATCH_INFO_EXC) exc_count++; @@ -6132,7 +6132,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) code = realloc_code (cfg, code_size); /* - * Add code to raise exceptions + * Add code to raise exceptions */ for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { switch (patch_info->type) { @@ -6146,24 +6146,24 @@ mono_arch_emit_exceptions (MonoCompile *cfg) s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip)); exc_class = mono_class_load_from_name (mono_defaults.corlib, - "System", + "System", patch_info->data.name); for (iExc = 0; iExc < nThrows; ++iExc) if (exc_classes [iExc] == exc_class) break; - + if (iExc < nThrows) { - s390_jcl (code, S390_CC_UN, + s390_jcl (code, S390_CC_UN, (guint64) exc_throw_start [iExc]); patch_info->type = MONO_PATCH_INFO_NONE; } else { - + if (nThrows < MAX_EXC) { exc_classes [nThrows] = exc_class; exc_throw_start [nThrows] = code; } - + /* * Patch the parameter passed to the handler */ @@ -6200,9 +6200,9 @@ mono_arch_emit_exceptions (MonoCompile *cfg) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific finishing of initialization - * + * * Perform any architectural-specific operations at the conclusion of * the initialization phase */ @@ -6215,7 +6215,7 @@ mono_arch_finish_init (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific instruction emission for method * * @param[in] @cfg - Compile Control block @@ -6223,7 +6223,7 @@ mono_arch_finish_init (void) * @param[in] @fsig - Method signature * @param[in] @args - Arguments to method * @returns Instruction(s) required for architecture - * + * * Provide any architectural shortcuts for specific methods. */ @@ -6330,20 +6330,20 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho /*========================= End of Function ========================*/ /** - * + * * @brief Decompose opcode into a System z operation * * @param[in] @cfg - Compile Control block * @param[in] @ins - Mono Instruction - * + * * Substitute a System z instruction for a Mono operation. */ void mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) { - /* - * Have to rename these to avoid being decomposed normally, since the normal + /* + * Have to rename these to avoid being decomposed normally, since the normal * decomposition does not work on S390. */ switch (ins->opcode) { @@ -6379,15 +6379,15 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) /*========================= End of Function ========================*/ /** - * + * * @brief Determine the cost of allocation a variable * * @param[in] @cfg - Compile Control block * @param[in] @vmv - Mono Method Variable * @returns Cost (hardcoded on s390x to 2) - * - * Determine the cost, in the number of memory references, of the action - * of allocating the variable VMV into a register during global register + * + * Determine the cost, in the number of memory references, of the action + * of allocating the variable VMV into a register during global register * allocation. * */ @@ -6402,14 +6402,14 @@ mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific register window flushing * * Not applicable for s390x so we just do nothing * */ -void +void mono_arch_flush_register_windows (void) { } @@ -6417,20 +6417,20 @@ mono_arch_flush_register_windows (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific check if value may be immediate * * @param[in] @opcode - Operation code * @param[in] @imm_opcode - Immediate operation code * @param[in] @imm - Value to be examined * @returns True if it is a valid immediate value - * + * * Determine if operand qualifies as an immediate value. For s390x * this is a value in the range -2**32/2**32-1 * */ -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return s390_is_imm32 (imm); @@ -6439,12 +6439,12 @@ mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific patch offset value for AOT * * @param[in] @code - Location of code to check * @returns Offset - * + * * Dummy entry point if/when s390x supports AOT. */ @@ -6457,13 +6457,13 @@ mono_arch_get_patch_offset (guint8 *code) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific returning of register from context * * @param[in] @ctx - Mono context * @param[in] @reg - Register number to be returned * @returns Contents of the register from the context - * + * * Return a register from the context. */ @@ -6482,13 +6482,13 @@ mono_arch_context_get_int_reg_address (MonoContext *ctx, int reg) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific setting of a register in the context * * @param[in] @ctx - Mono context * @param[in] @reg - Register number to be returned * @param[in] @val - Value to be set - * + * * Set the specified register in the context with the value passed */ @@ -6501,14 +6501,14 @@ mono_arch_context_set_int_reg (MonoContext *ctx, int reg, host_mgreg_t val) /*========================= End of Function ========================*/ /** - * + * * @brief Architectural specific returning of the "this" value from context * * @param[in] @ctx - Mono context * @param[in] @code - Current location * @returns Pointer to the "this" object - * - * Extract register 2 from the context as for s390x this is where the + * + * Extract register 2 from the context as for s390x this is where the * this parameter is passed */ @@ -6519,9 +6519,9 @@ mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code) } /*========================= End of Function ========================*/ - + /** - * + * * @brief Delegation trampoline processing * * @param[in] @info - Trampoline information @@ -6529,7 +6529,7 @@ mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code) * @param[in] @param_count - Count of parameters * @param[in] @aot - AOT indicator * @returns Next instruction location - * + * * Process the delegation trampolines */ @@ -6571,7 +6571,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, MonoMethodS iReg++; break; default : - s390_mvc (code, sizeof(uintptr_t), STK_BASE, offset, STK_BASE, offset+sizeof(uintptr_t)); + s390_mvc (code, sizeof(uintptr_t), STK_BASE, offset, STK_BASE, offset+sizeof(uintptr_t)); offset += sizeof(uintptr_t); } } @@ -6599,11 +6599,11 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, MonoMethodS /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific delegation trampolines processing * * @returns List of trampolines - * + * * Return a list of MonoTrampInfo structures for the delegate invoke impl trampolines. */ @@ -6629,13 +6629,13 @@ mono_arch_get_delegate_invoke_impls (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific delegation trampoline processing * * @param[in] @sig - Method signature * @param[in] @has_target - Whether delegation contains a target * @returns Trampoline - * + * * Return a pointer to a delegation trampoline */ @@ -6702,7 +6702,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific delegation virtual trampoline processing * * @param[in] @sig - Method signature @@ -6710,12 +6710,12 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe * @param[in] @offset - Offset into vtable * @param[in] @load_imt_reg - Whether to load the LMT register * @returns Trampoline - * + * * Return a pointer to a delegation virtual trampoline */ gpointer -mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, +mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg) { guint8 *code, *start; @@ -6727,7 +6727,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod * Replace the "this" argument with the target */ s390_lgr (code, s390_r1, s390_r2); - s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target)); + s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target)); /* * Load the IMT register, if needed @@ -6755,7 +6755,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific build of IMT trampoline * * @param[in] @vtable - Mono VTable @@ -6764,7 +6764,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod * @param[in] @count - Count of items * @param[in] @fail_tramp - Pointer to a failure trampoline * @returns Trampoline - * + * * Return a pointer to an IMT trampoline */ @@ -6787,11 +6787,11 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, if (item->has_target_code) item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE; else - item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + + item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + LOAD_SIZE; } else { if (fail_tramp) { - item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + + item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + 2 * LOADCON_SIZE; if (!item->has_target_code) item->chunk_size += LOAD_SIZE; @@ -6828,7 +6828,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, } item->jmp_code = (guint8*) code; s390_jcl (code, S390_CC_NE, 0); - + if (item->has_target_code) { S390_SET (code, s390_r1, item->value.target_code); } else { @@ -6848,7 +6848,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, S390_SET (code, s390_r1, item->value.target_code); } else { g_assert (vtable); - S390_SET (code, s390_r1, + S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot]))); s390_lg (code, s390_r1, 0, s390_r1, 0); } @@ -6875,8 +6875,8 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, s390_jcl (code, S390_CC_GE, 0); } } - /* - * patch the branches to get to the target items + /* + * patch the branches to get to the target items */ for (i = 0; i < count; ++i) { MonoIMTCheckItem *item = imt_entries [i]; @@ -6893,7 +6893,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, mono_arch_flush_icache ((guint8*)start, (code - start)); MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL)); - if (!fail_tramp) + if (!fail_tramp) UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); @@ -6906,13 +6906,13 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific return of pointer to IMT method * * @param[in] @regs - Context registers * @param[in] @code - Current location * @returns Pointer to IMT method - * + * * Extract the value of the IMT register from the context */ @@ -6925,13 +6925,13 @@ mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific return of pointer static call vtable. * * @param[in] @regs - Context registers * @param[in] @code - Current location * @returns Pointer to static call vtable - * + * * Extract the value of the RGCTX register from the context which * points to the static call vtable. */ @@ -6945,7 +6945,7 @@ mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific return of unwind bytecode for DWARF CIE * * @returns Unwind byte code @@ -6968,13 +6968,13 @@ mono_arch_get_cie_program (void) #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED /** - * + * * @brief Architecture-specific setting of a breakpoint * * @param[in] @ji - Mono JIT Information * @param[in] @ip - Insruction pointer * - * Set a breakpoint at the native code corresponding to JI at NATIVE_OFFSET. + * Set a breakpoint at the native code corresponding to JI at NATIVE_OFFSET. * The location should contain code emitted by OP_SEQ_POINT. */ @@ -6993,7 +6993,7 @@ mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific clearing of a breakpoint * * @param[in] @ji - Mono JIT Information @@ -7017,7 +7017,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific check if this is a breakpoint event * * @param[in] @info - Signal information @@ -7037,7 +7037,7 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific skip of a breakpoint * * @param[in] @ctx - Mono Context @@ -7053,9 +7053,9 @@ mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) } /*========================= End of Function ========================*/ - + /** - * + * * @brief Architecture-specific start of single stepping * * Unprotect the trigger page to enable single stepping @@ -7068,9 +7068,9 @@ mono_arch_start_single_stepping (void) } /*========================= End of Function ========================*/ - + /** - * + * * @brief Architecture-specific stop of single stepping * * Write-protect the trigger page to disable single stepping @@ -7085,7 +7085,7 @@ mono_arch_stop_single_stepping (void) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific check if single stepping event * * @param[in] @info - Signal information @@ -7106,7 +7106,7 @@ mono_arch_is_single_step_event (void *info, void *sigctx) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific skip of a single stepping event * * @param[in] @ctx - Mono Context @@ -7125,14 +7125,14 @@ mono_arch_skip_single_step (MonoContext *ctx) /*========================= End of Function ========================*/ /** - * + * * @brief Architecture-specific creation of sequence point information * * @param[in] @domain - Mono Domain * @param[in] @code - Current location pointer * @returns Sequence Point Information * - * Return a pointer to a data struction which is used by the sequence + * Return a pointer to a data struction which is used by the sequence * point implementation in AOTed code. A no-op on s390x until AOT is * ever supported. */ @@ -7173,7 +7173,7 @@ mono_arch_get_seq_point_info (guint8 *code) #endif /** - * + * * @brief Architecture-specific check of supported operation codes * * @param[in] @opcode - Operation code to be checked @@ -7201,7 +7201,7 @@ mono_arch_opcode_supported (int opcode) #ifndef DISABLE_JIT /** - * + * * @brief Architecture-specific check of tailcall support * * @param[in] @cfg - Mono Compile control block @@ -7225,7 +7225,7 @@ mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, gboolean res = IS_SUPPORTED_TAILCALL (callee_info->stack_usage <= caller_info->stack_usage); - // Any call that would result in parameters being placed on the stack cannot be "tailed" as it may + // Any call that would result in parameters being placed on the stack cannot be "tailed" as it may // result in the callers parameter variables being overwritten. ArgInfo const * const ainfo = callee_info->args + callee_sig->hasthis; for (int i = 0; res && i < callee_sig->param_count; ++i) { @@ -7279,7 +7279,7 @@ mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, #endif /** - * + * * @brief Architecture-specific load function * * @param[in] @jit_call_id - JIT callee identifier diff --git a/src/mono/mono/mini/mini-s390x.h b/src/mono/mono/mini/mini-s390x.h index 9a1aee5721aca..e251b8c23b789 100644 --- a/src/mono/mono/mini/mini-s390x.h +++ b/src/mono/mono/mini/mini-s390x.h @@ -192,7 +192,7 @@ static void inline s390_patch_rel (guchar *code, guint64 target) { guint32 *offset = (guint32 *) code; - + if (target != 0) { *offset = (guint32) target; } @@ -212,7 +212,7 @@ static void inline s390_patch_addr (guchar *code, guint64 target) { guint64 *offset = (guint64 *) code; - + if (target != 0) { *offset = target; } @@ -350,4 +350,4 @@ s390_patch_addr (guchar *code, guint64 target) *(guint32 *) p = lo; \ } while (0) -#endif /* __MONO_MINI_S390X_H__ */ +#endif /* __MONO_MINI_S390X_H__ */ diff --git a/src/mono/mono/mini/mini-sparc.c b/src/mono/mono/mini/mini-sparc.c index 184477cfc5175..8a51c738ed79b 100644 --- a/src/mono/mono/mini/mini-sparc.c +++ b/src/mono/mono/mini/mini-sparc.c @@ -44,20 +44,20 @@ * - the instruction set * - the ABI * - * V9 instructions are only usable if the underlying processor is 64 bit. Most Sparc - * processors in use are 64 bit processors. The V9 ABI is only usable if the + * V9 instructions are only usable if the underlying processor is 64 bit. Most Sparc + * processors in use are 64 bit processors. The V9 ABI is only usable if the * mono executable is a 64 bit executable. So it would make sense to use the 64 bit * instructions without using the 64 bit ABI. */ /* * Register usage: - * - %i0..%i hold the incoming arguments, these are never written by JITted + * - %i0..%i hold the incoming arguments, these are never written by JITted * code. Unused input registers are used for global register allocation. * - %o0..%o5 and %l7 is used for local register allocation and passing arguments * - %l0..%l6 is used for global register allocation * - %o7 and %g1 is used as scratch registers in opcodes - * - all floating point registers are used for local register allocation except %f0. + * - all floating point registers are used for local register allocation except %f0. * Only double precision registers are used. * In 64 bit mode: * - fp registers %d0..%d30 are used for parameter passing, and %d32..%d62 are @@ -77,8 +77,8 @@ * This test casts (guint64)-1 to double and then back to guint64 again. * Under x86, it returns 0, while under sparc it returns -1. * - * In addition to this, the runtime requires the trunc function, or its - * solaris counterpart, aintl, to do some double->int conversions. If this + * In addition to this, the runtime requires the trunc function, or its + * solaris counterpart, aintl, to do some double->int conversions. If this * function is not available, it is emulated somewhat, but the results can be * strange. */ @@ -179,11 +179,11 @@ mono_arch_regname (int reg) { const char* mono_arch_fregname (int reg) { static const char *rnames [] = { - "sparc_f0", "sparc_f1", "sparc_f2", "sparc_f3", "sparc_f4", + "sparc_f0", "sparc_f1", "sparc_f2", "sparc_f3", "sparc_f4", "sparc_f5", "sparc_f6", "sparc_f7", "sparc_f8", "sparc_f9", - "sparc_f10", "sparc_f11", "sparc_f12", "sparc_f13", "sparc_f14", + "sparc_f10", "sparc_f11", "sparc_f12", "sparc_f13", "sparc_f14", "sparc_f15", "sparc_f16", "sparc_f17", "sparc_f18", "sparc_f19", - "sparc_f20", "sparc_f21", "sparc_f22", "sparc_f23", "sparc_f24", + "sparc_f20", "sparc_f21", "sparc_f22", "sparc_f23", "sparc_f24", "sparc_f25", "sparc_f26", "sparc_f27", "sparc_f28", "sparc_f29", "sparc_f30", "sparc_f31" }; @@ -331,18 +331,18 @@ mono_arch_flush_register_windows (void) mono_sparc_flushw (); } -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return sparc_is_imm13 (imm); } -gboolean +gboolean mono_sparc_is_v9 (void) { return mono_hwcap_sparc_is_v9; } -gboolean +gboolean mono_sparc_is_sparc64 (void) { return v64; } @@ -461,7 +461,7 @@ add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo, gboolean single) * get_call_info: * * Obtain information about a call according to the calling convention. - * For V8, see the "System V ABI, Sparc Processor Supplement" Sparc V8 version + * For V8, see the "System V ABI, Sparc Processor Supplement" Sparc V8 version * document for more information. * For V9, see the "Low Level System Information (64-bit psABI)" chapter in * the 'Sparc Compliance Definition 2.4' document. @@ -515,7 +515,7 @@ get_call_info (MonoCompile *cfg, MonoMethodSignature *sig, gboolean is_pinvoke) DEBUG(printf("param %d: ", i)); if (m_type_is_byref (sig->params [i])) { DEBUG(printf("byref\n")); - + add_general (&gr, &stack_size, ainfo, FALSE); continue; } @@ -699,7 +699,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) GList *vars = NULL; int i; - /* + /* * FIXME: If an argument is allocated to a register, then load it from the * stack in the prolog. */ @@ -755,7 +755,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -833,8 +833,8 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->frame_reg = sparc_fp; offset = 0; - /* - * Reserve a stack slot for holding information used during exception + /* + * Reserve a stack slot for holding information used during exception * handling. */ if (header->num_clauses) @@ -864,8 +864,8 @@ mono_arch_allocate_vars (MonoCompile *cfg) else size = mini_type_stack_size (inst->inst_vtype, &align); - /* - * This is needed since structures containing doubles must be doubleword + /* + * This is needed since structures containing doubles must be doubleword * aligned. * FIXME: Do this only if needed. */ @@ -905,7 +905,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) arg_type = sig->params [i - sig->hasthis]; #ifndef SPARCV9 - if (!m_type_is_byref (arg_type) && ((arg_type->type == MONO_TYPE_R4) + if (!m_type_is_byref (arg_type) && ((arg_type->type == MONO_TYPE_R4) || (arg_type->type == MONO_TYPE_R8))) /* * Since float arguments are passed in integer registers, we need to @@ -950,7 +950,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) break; case ArgInFloatReg: case ArgInDoubleReg: - /* + /* * Since float regs are volatile, we save the arguments to * the stack in the prolog. * FIXME: Avoid this if the method contains no calls. @@ -965,7 +965,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->inst_offset = ainfo->offset + ARGS_OFFSET; if (!m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8)) { - /* + /* * It is very hard to load doubles from non-doubleword aligned * memory locations. So if the offset is misaligned, we copy the * argument to a stack location in the prolog. @@ -1000,7 +1000,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) } } - /* + /* * spillvars are stored between the normal locals and the storage reserved * by the ABI. */ @@ -1163,7 +1163,7 @@ emit_pass_vtype (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo, ArgInfo else if (pinvoke) size = mono_type_native_stack_size (m_class_get_byval_arg (in->klass), &align); else { - /* + /* * Other backends use mono_type_stack_size (), but that * aligns the size to 8, which is larger than the size of * the source, leading to reads of invalid memory if the @@ -1182,7 +1182,7 @@ emit_pass_vtype (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo, ArgInfo cinfo->stack_usage += size; cinfo->stack_usage += pad; - /* + /* * We use OP_OUTARG_VT to copy the valuetype to a stack location, then * use the normal OUTARG opcodes to pass the address of the location to * the callee. @@ -1242,9 +1242,9 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) MonoMethodSignature *tmp_sig; /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup (call->signature); @@ -1270,7 +1270,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) sig = call->signature; n = sig->param_count + sig->hasthis; - + cinfo = get_call_info (cfg, sig, sig->pinvoke); if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) { @@ -1297,7 +1297,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) arg_type = mini_get_underlying_type (arg_type); if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis]))) - emit_pass_vtype (cfg, call, cinfo, ainfo, arg_type, in, sig->pinvoke); + emit_pass_vtype (cfg, call, cinfo, ainfo, arg_type, in, sig->pinvoke && !sig->marshalling_disabled); else if (!m_type_is_byref (arg_type) && ((arg_type->type == MONO_TYPE_I8) || (arg_type->type == MONO_TYPE_U8))) emit_pass_long (cfg, call, ainfo, in); else if (!m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8)) @@ -1483,7 +1483,7 @@ else { \ sparc_branch (code, 0, cond, 0); \ } \ if (filldelay) sparc_nop (code); \ - } while (0); + } while (0); #define EMIT_COND_SYSTEM_EXCEPTION(ins,cond,sexc_name) EMIT_COND_SYSTEM_EXCEPTION_GENERAL(ins,cond,sexc_name,TRUE,DEFAULT_ICC) @@ -1577,7 +1577,7 @@ emit_call (MonoCompile *cfg, guint32 *code, guint32 patch_type, gconstpointer da mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, patch_type, data); EMIT_CALL (); } - + return code; } @@ -1594,7 +1594,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) { switch (ins->opcode) { - case OP_MUL_IMM: + case OP_MUL_IMM: /* remove unnecessary multiplication with 1 */ if (ins->inst_imm == 1) { if (ins->dreg != ins->sreg1) { @@ -1608,11 +1608,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) #ifndef SPARCV9 case OP_LOAD_MEMBASE: case OP_LOADI4_MEMBASE: - /* - * OP_STORE_MEMBASE_REG reg, offset(basereg) + /* + * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg */ - if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG + if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG || last_ins->opcode == OP_STORE_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { @@ -1625,7 +1625,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->sreg1 = last_ins->sreg1; } - /* + /* * Note: reg1 must be different from the basereg in the second load * OP_LOAD_MEMBASE offset(basereg), reg1 * OP_LOAD_MEMBASE offset(basereg), reg2 @@ -1650,11 +1650,11 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) //g_assert_not_reached (); #if 0 - /* - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + /* + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_LOAD_MEMBASE offset(basereg), reg * --> - * OP_STORE_MEMBASE_IMM imm, offset(basereg) + * OP_STORE_MEMBASE_IMM imm, offset(basereg) * OP_ICONST reg, imm */ } else if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM @@ -1702,7 +1702,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) /* Used when initializing temporaries */ /* We know sparc_fp is dword aligned */ if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM) && - (ins->inst_destbasereg == last_ins->inst_destbasereg) && + (ins->inst_destbasereg == last_ins->inst_destbasereg) && (ins->inst_destbasereg == sparc_fp) && (ins->inst_offset < 0) && ((ins->inst_offset % 8) == 0) && @@ -1732,13 +1732,13 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) /* * Convert compare with zero+branch to BRcc */ - /* + /* * This only works in 64 bit mode, since it examines all 64 * bits of the register. * Only do this if the method is small since BPr only has a 16bit * displacement. */ - if (v64 && (cfg->header->code_size < 10000) && last_ins && + if (v64 && (cfg->header->code_size < 10000) && last_ins && (last_ins->opcode == OP_COMPARE_IMM) && (last_ins->inst_imm == 0)) { switch (ins->opcode) { @@ -1788,15 +1788,15 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_MOVE: - /* - * OP_MOVE reg, reg + /* + * OP_MOVE reg, reg */ if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); continue; } - /* - * OP_MOVE sreg, dreg + /* + * OP_MOVE sreg, dreg * OP_MOVE dreg, sreg */ if (last_ins && last_ins->opcode == OP_MOVE && @@ -1877,7 +1877,7 @@ sparc_patch (guint32 *code, const gpointer target) guint32 ins2 = code [1]; if (((ins2 >> 30) == 2) && (((ins2 >> 19) & 0x3f) == 2)) { - /* sethi followed by or */ + /* sethi followed by or */ guint32 *p = code; sparc_set (p, target8, rd); while (p <= (code + 1)) @@ -1900,7 +1900,7 @@ sparc_patch (guint32 *code, const gpointer target) *(code + 1) |= (t & 0x3ff); #endif } - else if (v64 && + else if (v64 && (sparc_inst_rd (ins) == sparc_g1) && (sparc_inst_op (c [1]) == 0) && (sparc_inst_op2 (c [1]) == 4) && (sparc_inst_op (c [2]) == 2) && (sparc_inst_op3 (c [2]) == 2) && @@ -1913,7 +1913,7 @@ sparc_patch (guint32 *code, const gpointer target) while (p < (c + 6)) sparc_nop (p); } - else if ((sparc_inst_op (ins2) == 2) && (sparc_inst_op3 (ins2) == 0x38) && + else if ((sparc_inst_op (ins2) == 2) && (sparc_inst_op3 (ins2) == 0x38) && (sparc_inst_imm (ins2))) { /* sethi followed by jmpl */ #ifndef SPARCV9 @@ -2012,11 +2012,11 @@ emit_vret_token (MonoInst *ins, guint32 *code) MonoCallInst *call = (MonoCallInst*)ins; guint32 size; - /* + /* * The sparc ABI requires that calls to functions which return a structure * contain an additional unimpl instruction which is checked by the callee. */ - if (call->signature->pinvoke && MONO_TYPE_ISSTRUCT(call->signature->ret)) { + if (call->signature->pinvoke && !call->signature->marshalling_disabled && MONO_TYPE_ISSTRUCT(call->signature->ret)) { if (call->signature->ret->type == MONO_TYPE_TYPEDBYREF) size = mini_type_stack_size (call->signature->ret, NULL); else @@ -2045,7 +2045,7 @@ emit_move_return_value (MonoInst *ins, guint32 *code) case OP_LCALL: case OP_LCALL_REG: case OP_LCALL_MEMBASE: - /* + /* * ins->dreg is the least significant reg due to the lreg: LCALL rule * in inssel-long32.brg. */ @@ -2065,7 +2065,7 @@ emit_move_return_value (MonoInst *ins, guint32 *code) } else sparc_fmovd (code, sparc_f0, ins->dreg); -#else +#else sparc_fmovs (code, sparc_f0, ins->dreg); if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) sparc_fstod (code, ins->dreg, ins->dreg); @@ -2107,7 +2107,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, guint32 *code) sig = mono_method_signature_internal (method); cinfo = get_call_info (cfg, sig, FALSE); - + /* This is the opposite of the code in emit_prolog */ for (i = 0; i < sig->param_count + sig->hasthis; ++i) { @@ -2215,7 +2215,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, guint32 *code) * * Determine whenever the instruction at CODE is a virtual call. */ -gboolean +gboolean mono_sparc_is_virtual_call (guint32 *code) { guint32 buf[1]; @@ -2225,7 +2225,7 @@ mono_sparc_is_virtual_call (guint32 *code) if ((sparc_inst_op (*code) == 0x2) && (sparc_inst_op3 (*code) == 0x38)) { /* - * Register indirect call. If it is a virtual call, then the + * Register indirect call. If it is a virtual call, then the * instruction in the delay slot is a special kind of nop. */ @@ -2540,8 +2540,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BREAK: /* - * gdb does not like encountering 'ta 1' in the debugged code. So - * instead of emitting a trap, we emit a call a C function and place a + * gdb does not like encountering 'ta 1' in the debugged code. So + * instead of emitting a trap, we emit a call a C function and place a * breakpoint there. */ //sparc_ta (code, 1); @@ -2879,7 +2879,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_save_sp_to_lmf (cfg, code); sparc_jmpl (code, ins->sreg1, sparc_g0, sparc_callsite); /* - * We emit a special kind of nop in the delay slot to tell the + * We emit a special kind of nop in the delay slot to tell the * trampoline code that this is a virtual call, thus an unbox * trampoline might need to be called. */ @@ -2989,7 +2989,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_LOCALLOC_IMM: { gint32 offset = ins->inst_imm; gint32 offset2; - + #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK /* Perform stack touching */ NOT_IMPLEMENTED; @@ -3058,11 +3058,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_START_HANDLER: { /* - * The START_HANDLER instruction marks the beginning of a handler - * block. It is called using a call instruction, so %o7 contains + * The START_HANDLER instruction marks the beginning of a handler + * block. It is called using a call instruction, so %o7 contains * the return address. Since the handler executes in the same stack - * frame as the method itself, we can't use save/restore to save - * the return address. Instead, we save it into a dedicated + * frame as the method itself, we can't use save/restore to save + * the return address. Instead, we save it into a dedicated * variable. */ MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region); @@ -3099,7 +3099,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) sparc_nop (code); break; } - case OP_CALL_HANDLER: + case OP_CALL_HANDLER: mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); /* This is a jump inside the method, so call_simple works even on V9 */ sparc_call_simple (code, 0); @@ -3444,7 +3444,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1); #endif break; - case OP_LCONV_TO_R_UN: { + case OP_LCONV_TO_R_UN: { /* Emulated */ g_assert_not_reached (); break; @@ -3453,11 +3453,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_LCONV_TO_OVF_I4_2: { guint32 *br [3], *label [1]; - /* + /* * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */ sparc_cmp_imm (code, ins->sreg1, 0); - br [0] = code; + br [0] = code; sparc_branch (code, 1, sparc_bneg, 0); sparc_nop (code); @@ -3493,13 +3493,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: sparc_fsubd (code, ins->sreg1, ins->sreg2, ins->dreg); - break; + break; case OP_FMUL: sparc_fmuld (code, ins->sreg1, ins->sreg2, ins->dreg); - break; + break; case OP_FDIV: sparc_fdivd (code, ins->sreg1, ins->sreg2, ins->dreg); - break; + break; case OP_FNEG: #ifdef SPARCV9 sparc_fnegd (code, ins->sreg1, ins->dreg); @@ -3507,7 +3507,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* FIXME: why don't use fnegd ? */ sparc_fnegs (code, ins->sreg1, ins->dreg); #endif - break; + break; case OP_FREM: sparc_fdivd (code, ins->sreg1, ins->sreg2, FP_SCRATCH_REG); sparc_fmuld (code, ins->sreg2, FP_SCRATCH_REG, FP_SCRATCH_REG); @@ -3536,7 +3536,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) default: sparc_fbranch (code, 1, opcode_to_sparc_cond (ins->opcode), 2); /* delay slot */ - sparc_set (code, 1, ins->dreg); + sparc_set (code, 1, ins->dreg); } break; case OP_FBEQ: @@ -3644,7 +3644,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_inst_name (ins->opcode), max_len, ((guint8*)code) - code_start); g_assert_not_reached (); } - + cpos += max_len; last_ins = ins; @@ -3884,7 +3884,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) offset += 6 * sizeof (target_mgreg_t); else offset += cfg->param_area; - + /* align the stack size */ offset = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT); @@ -3950,7 +3950,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* Save the argument to a dword aligned stack location */ /* * stack_offset contains the offset of the argument on the stack. - * inst->inst_offset contains the dword aligned offset where the value + * inst->inst_offset contains the dword aligned offset where the value * should be stored. */ if (ainfo->storage == ArgInIRegPair) { @@ -3999,7 +3999,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) sparc_sth_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset); else if ((stack_offset - ARGS_OFFSET) & 0x4) - sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset); + sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset); else { if (v64) sparc_stx_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset); @@ -4016,7 +4016,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (!sparc_is_imm13 (inst->inst_offset + 4)) NOT_IMPLEMENTED; sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, inst->inst_offset); - sparc_st_imm (code, sparc_i0 + ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + 4); + sparc_st_imm (code, sparc_i0 + ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + 4); } else if ((ainfo->storage == ArgInFloatReg) && (inst->opcode != OP_REGVAR)) { if (!sparc_is_imm13 (stack_offset)) @@ -4027,7 +4027,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* The offset is guaranteed to be aligned by the ABI rules */ sparc_stdf_imm (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); } - + if ((ainfo->storage == ArgInFloatReg) && (inst->opcode == OP_REGVAR)) { /* Need to move into the a double precision register */ sparc_fstod (code, ainfo->reg, ainfo->reg - 1); @@ -4080,10 +4080,10 @@ mono_arch_emit_epilog (MonoCompile *cfg) guint32 *code; int can_fold = 0; int max_epilog_size = 16 + 20 * 4; - + if (cfg->method->save_lmf) max_epilog_size += 128; - + if (mono_jit_trace_calls != NULL) max_epilog_size += 50; @@ -4099,7 +4099,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) code = mono_sparc_emit_restore_lmf (code, lmf_offset); } - /* + /* * The V8 ABI requires that calls to functions which return a structure * return to %i7+12 */ @@ -4113,8 +4113,8 @@ mono_arch_emit_epilog (MonoCompile *cfg) if (cfg->bb_exit->in_count == 1 && cfg->bb_exit->in_bb[0]->native_offset != cfg->bb_exit->native_offset) can_fold = 1; - /* - * FIXME: The last instruction might have a branch pointing into it like in + /* + * FIXME: The last instruction might have a branch pointing into it like in * int_ceq sparc_i0 <- */ can_fold = 0; @@ -4159,8 +4159,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg) if (patch_info->type == MONO_PATCH_INFO_EXC) exc_count++; } - - /* + + /* * make sure we have enough space for exceptions */ #ifdef SPARCV9 @@ -4349,7 +4349,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the activation frame. */ diff --git a/src/mono/mono/mini/mini-sparc.h b/src/mono/mono/mini/mini-sparc.h index 63be33284af89..1d96c2f0360ce 100644 --- a/src/mono/mono/mini/mini-sparc.h +++ b/src/mono/mono/mini/mini-sparc.h @@ -17,7 +17,7 @@ /* Parameters used by the register allocator */ -/* +/* * Use %o0..%o5 as local registers, plus %l7 since we need an extra register for * holding the sreg1 in call instructions. */ @@ -176,4 +176,4 @@ guint32* mono_sparc_emit_save_lmf (guint32* code, guint32 lmf_offset); guint32* mono_sparc_emit_restore_lmf (guint32 *code, guint32 lmf_offset); -#endif /* __MONO_MINI_SPARC_H__ */ +#endif /* __MONO_MINI_SPARC_H__ */ diff --git a/src/mono/mono/mini/mini-trampolines.c b/src/mono/mono/mini/mini-trampolines.c index 84aeee956586f..2b87e4bce2c55 100644 --- a/src/mono/mono/mini/mini-trampolines.c +++ b/src/mono/mono/mini/mini-trampolines.c @@ -317,7 +317,7 @@ mini_jit_info_is_gsharedvt (MonoJitInfo *ji) /** * mini_add_method_trampoline: - * @m: + * @m: * @compiled_method: * @add_static_rgctx_tramp: adds a static rgctx trampoline * @add_unbox_tramp: adds an unboxing trampoline @@ -658,7 +658,7 @@ common_call_trampoline (host_mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTa mini_patch_jump_sites (m, mono_get_addr_from_ftnptr (addr)); /* Patch the got entries pointing to this method */ - /* + /* * We do this here instead of in mono_codegen () to cover the case when m * was loaded from an aot image. */ @@ -729,7 +729,7 @@ common_call_trampoline (host_mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTa ji = mini_jit_info_table_find (code); if (ji && target_ji && generic_shared && ji->has_generic_jit_info && !target_ji->has_generic_jit_info) { - /* + /* * Can't patch the call as the caller is gshared, but the callee is not. Happens when * generic sharing fails. * FIXME: Performance problem. @@ -860,12 +860,12 @@ mono_vcall_trampoline (host_mgreg_t *regs, guint8 *code, int slot, guint8 *tramp /** * mono_aot_trampoline: * - * This trampoline handles calls made from AOT code. We try to bypass the + * This trampoline handles calls made from AOT code. We try to bypass the * normal JIT compilation logic to avoid loading the metadata for the method. */ #ifdef MONO_ARCH_AOT_SUPPORTED gpointer -mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, +mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, guint8* tramp) { MONO_REQ_GC_UNSAFE_MODE; @@ -912,7 +912,7 @@ mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, * This trampoline handles calls made from AOT code through the PLT table. */ gpointer -mono_aot_plt_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *aot_module, +mono_aot_plt_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *aot_module, guint8* tramp) { gpointer res; @@ -1002,8 +1002,8 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint method = delegate->method; /* - * delegate->method_ptr == NULL means the delegate was initialized by - * mini_delegate_ctor, while != NULL means it is initialized by + * delegate->method_ptr == NULL means the delegate was initialized by + * mini_delegate_ctor, while != NULL means it is initialized by * mono_delegate_ctor_with_method (). In both cases, we need to add wrappers * (ctor_with_method () does this, but it doesn't store the wrapper back into * delegate->method). @@ -1082,7 +1082,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint method = mono_object_get_virtual_method_internal (delegate->target, method); enable_caching = FALSE; } else if (delegate->target && - method->flags & METHOD_ATTRIBUTE_VIRTUAL && + method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->flags & METHOD_ATTRIBUTE_ABSTRACT && mono_class_is_abstract (method->klass)) { method = mono_object_get_virtual_method_internal (delegate->target, method); @@ -1098,7 +1098,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint need_rgctx_tramp = TRUE; } - /* + /* * If the called address is a trampoline, replace it with the compiled method so * further calls don't have to go through the trampoline. */ @@ -1302,7 +1302,7 @@ mono_create_jump_trampoline (MonoMethod *method, gboolean add_sync_wrapper, Mono ji->d.method = method; /* - * mono_delegate_ctor needs to find the method metadata from the + * mono_delegate_ctor needs to find the method metadata from the * trampoline address, so we save it here. */ @@ -1335,7 +1335,7 @@ mono_create_jit_trampoline (MonoMethod *method, MonoError *error) /* Avoid creating trampolines if possible */ gpointer code = mono_jit_find_compiled_method (method); - + if (code) return code; if (mono_llvm_only) { @@ -1363,7 +1363,7 @@ mono_create_jit_trampoline (MonoMethod *method, MonoError *error) jit_mm_unlock (jit_mm); return tramp; -} +} gpointer mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token) @@ -1382,7 +1382,7 @@ mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token) UnlockedIncrement (&jit_trampolines); return tramp; -} +} /* diff --git a/src/mono/mono/mini/mini-unwind.h b/src/mono/mono/mini/mini-unwind.h index ff594c49937f2..3db2f45e9cb2b 100644 --- a/src/mono/mono/mini/mini-unwind.h +++ b/src/mono/mono/mini/mini-unwind.h @@ -19,7 +19,7 @@ #endif /* - * This is a platform-independent interface for unwinding through stack frames + * This is a platform-independent interface for unwinding through stack frames * based on the Dwarf unwinding interface. * See http://dwarfstd.org/Dwarf3.pdf, section "Call Frame Information". */ @@ -89,7 +89,7 @@ typedef struct { guint32 when; /* The offset _after_ the cpu instruction this unwind op belongs to */ } MonoUnwindOp; -/* +/* * Macros for emitting MonoUnwindOp structures. * These should be called _after_ emitting the cpu instruction the unwind op * belongs to. @@ -178,7 +178,7 @@ guint8* mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len); gboolean -mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, +mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations, mono_unwind_reg_t *regs, int nregs, host_mgreg_t **save_locations, int save_locations_len, diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index 67bbdbc94af69..f341690dd7d59 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -508,31 +508,35 @@ mono_arch_context_get_int_reg_address (MonoContext *ctx, int reg) return 0; } -#ifdef HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) void -mono_runtime_setup_stat_profiler (void) +mono_runtime_install_handlers (void) { - g_error ("mono_runtime_setup_stat_profiler"); } -gboolean -MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) +void +mono_init_native_crash_info (void) { - g_error ("mono_chain_signal"); - - return FALSE; + return; } +#endif + +#ifdef HOST_BROWSER + void -mono_runtime_install_handlers (void) +mono_runtime_setup_stat_profiler (void) { + g_error ("mono_runtime_setup_stat_profiler"); } -void -mono_init_native_crash_info (void) +gboolean +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { - return; + g_error ("mono_chain_signal"); + + return FALSE; } gboolean @@ -780,7 +784,7 @@ mono_arch_load_function (MonoJitICallId jit_icall_id) return NULL; } -MONO_API void +MONO_API void mono_wasm_enable_debugging (int log_level) { mono_wasm_debug_level = log_level; diff --git a/src/mono/mono/mini/mini-wasm.h b/src/mono/mono/mini/mini-wasm.h index c98f7603828d5..d307077de1c33 100644 --- a/src/mono/mono/mini/mini-wasm.h +++ b/src/mono/mono/mini/mini-wasm.h @@ -45,7 +45,7 @@ #define MONO_ARCH_INST_SREG2_MASK(ins) 0 struct MonoLMF { - /* + /* * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and * the other fields are not valid. */ @@ -108,4 +108,4 @@ void mono_wasm_print_stack_trace (void); gboolean mini_wasm_is_scalar_vtype (MonoType *type); -#endif /* __MONO_MINI_WASM_H__ */ +#endif /* __MONO_MINI_WASM_H__ */ diff --git a/src/mono/mono/mini/mini-x86-gsharedvt.c b/src/mono/mono/mini/mini-x86-gsharedvt.c index d2d4b09d29834..93b86d8cc7afb 100644 --- a/src/mono/mono/mini/mini-x86-gsharedvt.c +++ b/src/mono/mono/mini/mini-x86-gsharedvt.c @@ -98,7 +98,7 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr * Map ret arg. * This handles the case when the method returns a normal vtype, and when it returns a type arg, and its instantiated * with a vtype. - */ + */ g_ptr_array_add (map, GUINT_TO_POINTER (caller_cinfo->vret_arg_offset / sizeof (target_mgreg_t))); g_ptr_array_add (map, GUINT_TO_POINTER (callee_cinfo->vret_arg_offset / sizeof (target_mgreg_t))); } diff --git a/src/mono/mono/mini/mini-x86.c b/src/mono/mono/mini/mini-x86.c index 52972a5e98ece..e94494327c39c 100644 --- a/src/mono/mono/mini/mini-x86.c +++ b/src/mono/mono/mini/mini-x86.c @@ -80,7 +80,7 @@ mono_arch_regname (int reg) case X86_EBX: return "%ebx"; case X86_ECX: return "%ecx"; case X86_EDX: return "%edx"; - case X86_ESP: return "%esp"; + case X86_ESP: return "%esp"; case X86_EBP: return "%ebp"; case X86_EDI: return "%edi"; case X86_ESI: return "%esi"; @@ -226,7 +226,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, MonoClass *klass; klass = mono_class_from_mono_type_internal (type); - size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke); + size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke && !sig->marshalling_disabled); #if defined(TARGET_WIN32) /* @@ -318,7 +318,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, * get_call_info: * * Obtain information about a call according to the calling convention. - * For x86 ELF, see the "System V Application Binary Interface Intel386 + * For x86 ELF, see the "System V Application Binary Interface Intel386 * Architecture Processor Supplment, Fourth Edition" document for more * information. * For x86 win32, see https://msdn.microsoft.com/en-us/library/984x0h58.aspx. @@ -435,7 +435,7 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == 0)) { fr = FLOAT_PARAM_REGS; - + /* Emit the signature cookie just before the implicit arguments */ add_general (&gr, param_regs, &stack_size, &cinfo->sig_cookie); } @@ -446,8 +446,8 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) { /* We allways pass the sig cookie on the stack for simplicity */ - /* - * Prevent implicit arguments + the sig cookie from being passed + /* + * Prevent implicit arguments + the sig cookie from being passed * in registers. */ fr = FLOAT_PARAM_REGS; @@ -524,7 +524,7 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n > 0) && (sig->sentinelpos == sig->param_count)) { fr = FLOAT_PARAM_REGS; - + /* Emit the signature cookie just before the implicit arguments */ add_general (&gr, param_regs, &stack_size, &cinfo->sig_cookie); } @@ -681,7 +681,7 @@ mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo * @arg_info: an array to store the result infos * * Gathers information on parameters such as size, alignment and - * padding. arg_info should be large enought to hold param_count + 1 entries. + * padding. arg_info should be large enought to hold param_count + 1 entries. * * Returns the size of the argument area on the stack. * This should be signal safe, since it is called from @@ -728,7 +728,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit prev_stackarg = 0; for (k = 0; k < param_count; k++) { - size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke); + size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke && !csig->marshalling_disabled); if (storage_in_ireg (cinfo->args [csig->hasthis + k].storage)) { /* not in stack, we'll give it an offset at the end */ @@ -738,7 +738,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit /* ignore alignment for now */ align = 1; - args_size += pad = (align - (args_size & (align - 1))) & (align - 1); + args_size += pad = (align - (args_size & (align - 1))) & (align - 1); arg_info [prev_stackarg].pad = pad; args_size += size; arg_info [k + 1].pad = 0; @@ -962,7 +962,7 @@ mono_arch_is_int_overflow (void *sigctx, void *info) if (reg == -1) return TRUE; } - + return FALSE; } @@ -980,11 +980,11 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; - if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || + if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) continue; - /* we dont allocate I1 to registers because there is no simply way to sign extend + /* we dont allocate I1 to registers because there is no simply way to sign extend * 8bit quantities in caller saved registers on x86 */ if (mono_is_regsize_var (ins->inst_vtype) && (ins->inst_vtype->type != MONO_TYPE_I1)) { g_assert (MONO_VARINFO (cfg, i)->reg == -1); @@ -1014,7 +1014,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /* * mono_arch_regalloc_cost: * - * Return the cost, in number of memory references, of the action of + * Return the cost, in number of memory references, of the action of * allocating the variable VMV into a register during global register * allocation. */ @@ -1219,7 +1219,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) switch (cinfo->ret.storage) { case ArgOnStack: if (cfg->vret_addr) { - /* + /* * In the new IR, the cfg->vret_addr variable represents the * vtype return value. */ @@ -1348,9 +1348,9 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) int sig_reg; /* - * mono_ArgIterator_Setup assumes the signature cookie is + * mono_ArgIterator_Setup assumes the signature cookie is * passed first and all the arguments which were before it are - * passed on the stack after the signature. So compensate by + * passed on the stack after the signature. So compensate by * passing a different signature. */ tmp_sig = mono_metadata_signature_dup (call->signature); @@ -1387,7 +1387,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) /* * LLVM always uses the native ABI while we use our own ABI, the * only difference is the handling of vtypes: - * - we only pass/receive them in registers in some cases, and only + * - we only pass/receive them in registers in some cases, and only * in 1 or 2 integer registers. */ if (cinfo->ret.storage == ArgValuetypeInReg) { @@ -1516,7 +1516,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) if (cinfo->ret.storage == ArgValuetypeInReg && cinfo->ret.pair_storage[0] != ArgNone ) { /* * Tell the JIT to use a more efficient calling convention: call using - * OP_CALL, compute the result location after the call, and save the + * OP_CALL, compute the result location after the call, and save the * result there. */ call->vret_in_reg = TRUE; @@ -1529,7 +1529,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } } - // FIXME: Emit EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF everywhere + // FIXME: Emit EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF everywhere /* Handle the case where there are no implicit arguments */ if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sentinelpos)) { @@ -1592,7 +1592,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) align = sizeof (target_mgreg_t); } else { - size = mini_type_stack_size_full (m_class_get_byval_arg (in->klass), &align, sig->pinvoke); + size = mini_type_stack_size_full (m_class_get_byval_arg (in->klass), &align, sig->pinvoke && !sig->marshalling_disabled); } if (size > 0 || ainfo->pass_empty_struct) { @@ -1683,7 +1683,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) vtarg->sreg1 = call->inst.dreg; vtarg->dreg = mono_alloc_ireg (cfg); MONO_ADD_INS (cfg->cbb, vtarg); - + mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->ret.reg, FALSE); } else if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 0) { MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, cinfo->ret.offset, call->vret_var->dreg); @@ -1768,7 +1768,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) return; } } - + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg); } @@ -1784,9 +1784,9 @@ if (ins->inst_true_bb->native_offset) { \ x86_branch32 (code, cond, 0, sign); \ } -/* +/* * Emit an exception if condition is fail and - * if possible do a directly branch to target + * if possible do a directly branch to target */ #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \ do { \ @@ -1798,12 +1798,12 @@ if (ins->inst_true_bb->native_offset) { \ } else { \ EMIT_COND_BRANCH (tins, cond, signed); \ } \ - } while (0); + } while (0); #define EMIT_FPCOMPARE(code) do { \ x86_fcompp (code); \ x86_fnstsw (code); \ -} while (0); +} while (0); static guint8* x86_align_and_patch (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer data) @@ -1862,7 +1862,7 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IADD_IMM: case OP_ADD_IMM: if ((ins->sreg1 < MONO_MAX_IREGS) && (ins->dreg >= MONO_MAX_IREGS)) { - /* + /* * X86_LEA is like ADD, but doesn't have the * sreg1==dreg restriction. */ @@ -1882,15 +1882,15 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_COMPARE_IMM: case OP_ICOMPARE_IMM: - /* OP_COMPARE_IMM (reg, 0) - * --> - * OP_X86_TEST_NULL (reg) + /* OP_COMPARE_IMM (reg, 0) + * --> + * OP_X86_TEST_NULL (reg) */ if (!ins->inst_imm) ins->opcode = OP_X86_TEST_NULL; break; case OP_X86_COMPARE_MEMBASE_IMM: - /* + /* * OP_STORE_MEMBASE_REG reg, offset(basereg) * OP_X86_COMPARE_MEMBASE_IMM offset(basereg), imm * --> @@ -1910,7 +1910,7 @@ mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb) ins->opcode = OP_X86_TEST_NULL; } - break; + break; case OP_X86_PUSH_MEMBASE: if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG || last_ins->opcode == OP_STORE_MEMBASE_REG) && @@ -1943,8 +1943,8 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) ins->sreg1 = ins->dreg; ins->sreg2 = ins->dreg; - /* - * Convert succeeding STORE_MEMBASE_IMM 0 ins to STORE_MEMBASE_REG + /* + * Convert succeeding STORE_MEMBASE_IMM 0 ins to STORE_MEMBASE_REG * since it takes 3 bytes instead of 7. */ for (ins2 = mono_inst_next (ins, FILTER_IL_SEQ_POINT); ins2; ins2 = ins2->next) { @@ -1998,7 +1998,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) MonoInst *ins, *next; /* - * FIXME: Need to add more instructions, but the current machine + * FIXME: Need to add more instructions, but the current machine * description can't model some parts of the composite instructions like * cdq. */ @@ -2008,7 +2008,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IDIV_IMM: case OP_IDIV_UN_IMM: case OP_IREM_UN_IMM: - /* + /* * Keep the cases where we could generated optimized code, otherwise convert * to the non-imm variant. */ @@ -2049,7 +2049,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) bb->max_vreg = cfg->next_vreg; } -static const int +static const int branch_cc_table [] = { X86_CC_EQ, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT, X86_CC_NE, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT, @@ -2099,7 +2099,7 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int size, gboolean x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8); x86_fist_pop_membase (code, X86_ESP, 0, TRUE); x86_pop_reg (code, dreg); - /* FIXME: need the high register + /* FIXME: need the high register * x86_pop_reg (code, dreg_high); */ } else { @@ -2151,7 +2151,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x1000); x86_test_membase_reg (code, X86_ESP, 0, X86_ESP); - /* + /* * By the end of the loop, sreg2 is smaller than 0x1000, so the init routine * that follows only initializes the last part of the area. */ @@ -2161,7 +2161,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_push_reg (code, X86_ECX); x86_push_reg (code, X86_EDI); x86_mov_reg_imm (code, X86_ECX, (0x1000 >> 2)); - x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX); + x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX); if (cfg->param_area) x86_lea_membase (code, X86_EDI, X86_ESP, 12 + ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); else @@ -2206,11 +2206,11 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_push_reg (code, X86_EDI); offset += 4; } - + x86_shift_reg_imm (code, X86_SHR, sreg, 2); x86_mov_reg_reg (code, X86_ECX, sreg); x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX); - + if (cfg->param_area) x86_lea_membase (code, X86_EDI, X86_ESP, offset + ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); else @@ -2218,7 +2218,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_cld (code); x86_prefix (code, X86_REP_PREFIX); x86_stosl (code); - + if (tree->dreg != X86_EDI && sreg != X86_EDI) x86_pop_reg (code, X86_EDI); if (tree->dreg != X86_ECX && sreg != X86_ECX) @@ -2641,7 +2641,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Have to use ecx as a temp reg since this can occur after OP_SETRET */ - /* + /* * We do this _before_ the breakpoint, so single stepping after * a breakpoint is hit will step to the next IL offset. */ @@ -2680,7 +2680,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) int size = start + OP_SEQ_POINT_BP_OFFSET - code; x86_padding (code, size); } - /* + /* * A placeholder for a possible breakpoint inserted by * mono_arch_set_breakpoint (). */ @@ -2738,7 +2738,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_IDIV: case OP_IREM: - /* + /* * The code is the same for div/rem, the allocator will allocate dreg * to RAX/RDX as appropriate. */ @@ -2747,7 +2747,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_push_reg (code, ins->sreg2); x86_cdq (code); x86_div_membase (code, X86_ESP, 0, TRUE); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); + x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); } else { x86_cdq (code); x86_div_reg (code, ins->sreg2, TRUE); @@ -2759,7 +2759,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_push_reg (code, ins->sreg2); x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EDX); x86_div_membase (code, X86_ESP, 0, FALSE); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); + x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); } else { x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EDX); x86_div_reg (code, ins->sreg2, FALSE); @@ -2781,7 +2781,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Based on http://compilers.iecc.com/comparch/article/93-04-079 */ x86_cdq (code); x86_alu_reg_imm (code, X86_AND, X86_EAX, 1); - /* + /* * If the divident is >= 0, this does not nothing. If it is positive, it * it transforms %eax=0 into %eax=0, and %eax=1 into %eax=-1. */ @@ -2854,7 +2854,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* handle shift over 32 bit */ x86_mov_reg_reg (code, ins->backend.reg3, ins->sreg1); x86_clear_reg (code, ins->sreg1); - + x86_patch (jump_to_end, code); } break; @@ -2871,7 +2871,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* handle shifts over 31 bits */ x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3); x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, 31); - + x86_patch (jump_to_end, code); } break; @@ -2888,7 +2888,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* handle shifts over 31 bits */ x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3); x86_clear_reg (code, ins->backend.reg3); - + x86_patch (jump_to_end, code); } break; @@ -3128,7 +3128,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_mov_reg_membase (code, X86_EAX, X86_ESP, i, 4); x86_mov_membase_reg (code, X86_EBP, 8 + i, X86_EAX, 4); } - + /* restore ESP/EBP */ x86_leave (code); @@ -3315,13 +3315,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_BR: if (ins->inst_target_bb->native_offset) { - x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); + x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); } else { mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); if ((cfg->opt & MONO_OPT_BRANCH) && x86_is_imm8 (ins->inst_target_bb->max_offset - cpos)) x86_jump8 (code, 0); - else + else x86_jump32 (code, 0); } break; @@ -3545,7 +3545,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_fld_membase (code, X86_ESP, 0, FALSE); x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8); break; - case OP_LCONV_TO_R_UN_2: { + case OP_LCONV_TO_R_UN_2: { static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 }; guint8 *br; @@ -3553,11 +3553,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_push_reg (code, ins->sreg2); x86_push_reg (code, ins->sreg1); x86_fild_membase (code, X86_ESP, 0, TRUE); - + /* test if lreg is negative */ x86_test_reg_reg (code, ins->sreg2, ins->sreg2); br = code; x86_branch8 (code, X86_CC_GEZ, 0, TRUE); - + /* add correction constant mn */ if (cfg->compile_aot) { x86_push_imm (code, (((guint32)mn [9]) << 24) | ((guint32)mn [8] << 16) | ((guint32)mn [7] << 8) | ((guint32)mn [6])); @@ -3585,7 +3585,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) guint8 *br [3], *label [1]; MonoInst *tins; - /* + /* * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */ x86_test_reg_reg (code, ins->sreg1, ins->sreg1); @@ -3609,12 +3609,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, "OverflowException"); x86_jump32 (code, 0); } - - + + x86_patch (br [0], code); /* our top bit is set, check that top word is 0xfffffff */ x86_alu_reg_imm (code, X86_CMP, ins->sreg2, 0xffffffff); - + x86_patch (br [1], code); /* nope, emit exception */ br [2] = code; x86_branch8 (code, X86_CC_NE, 0, TRUE); @@ -3639,23 +3639,23 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FSUB: x86_fp_op_reg (code, X86_FSUB, 1, TRUE); - break; + break; case OP_FMUL: x86_fp_op_reg (code, X86_FMUL, 1, TRUE); - break; + break; case OP_FDIV: x86_fp_op_reg (code, X86_FDIV, 1, TRUE); - break; + break; case OP_FNEG: x86_fchs (code); - break; + break; case OP_ABS: x86_fabs (code); - break; + break; case OP_TAN: { - /* + /* * it really doesn't make sense to inline all this code, - * it's here just to show that things may not be as simple + * it's here just to show that things may not be as simple * as they appear. */ guchar *check_pos, *end_tan, *pop_jump; @@ -3692,7 +3692,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_fpatan (code); x86_fldz (code); x86_fp_op_reg (code, X86_FADD, 1, TRUE); - break; + break; case OP_SQRT: x86_fsqrt (code); break; @@ -3736,7 +3736,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* we need to exchange ST(0) with ST(1) */ x86_fxch (code, 1); - /* this requires a loop, because fprem somtimes + /* this requires a loop, because fprem somtimes * returns a partial remainder */ l1 = code; /* looks like MS is using fprem instead of the IEEE compatible fprem1 */ @@ -3767,7 +3767,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCEQ: case OP_FCNEQ: if (cfg->opt & MONO_OPT_FCMOV) { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ guchar *unordered_check; @@ -3791,7 +3791,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_push_reg (code, X86_EAX); EMIT_FPCOMPARE(code); @@ -3800,13 +3800,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_set_reg (code, ins->opcode == OP_FCEQ ? X86_CC_EQ : X86_CC_NE, ins->dreg, TRUE); x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE); - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_pop_reg (code, X86_EAX); break; case OP_FCLT: case OP_FCLT_UN: if (cfg->opt & MONO_OPT_FCMOV) { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg); @@ -3827,7 +3827,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; } - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_push_reg (code, X86_EAX); EMIT_FPCOMPARE(code); @@ -3846,7 +3846,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE); x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE); - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_pop_reg (code, X86_EAX); break; case OP_FCLE: { @@ -3890,7 +3890,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCGT: case OP_FCGT_UN: if (cfg->opt & MONO_OPT_FCMOV) { - /* zeroing the register at the start results in + /* zeroing the register at the start results in * shorter and faster code (we can also remove the widening op) */ guchar *unordered_check; @@ -3907,7 +3907,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; } - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_push_reg (code, X86_EAX); EMIT_FPCOMPARE(code); @@ -3921,13 +3921,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_jump8 (code, 0); x86_patch (is_not_zero_check, code); x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_CC_MASK); - + x86_patch (end_jump, code); } x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE); x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE); - if (ins->dreg != X86_EAX) + if (ins->dreg != X86_EAX) x86_pop_reg (code, X86_EAX); break; case OP_FCGE: { @@ -4114,7 +4114,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) br1 = code; x86_branch8 (code, X86_CC_NE, 0, FALSE); - x86_fstp (code, 0); + x86_fstp (code, 0); EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException"); x86_patch (br1, code); @@ -4172,7 +4172,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, 4); /* dreg contains the old value, add with sreg2 value */ x86_alu_reg_reg (code, X86_ADD, dreg, ins->sreg2); - + if (ins->dreg != dreg) { x86_mov_reg_reg (code, ins->dreg, dreg); x86_pop_reg (code, dreg); @@ -4188,11 +4188,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (cfg->has_atomic_exchange_i4); /* cmpxchg uses eax as comperand, need to make sure we can use it - * hack to overcome limits in x86 reg allocator - * (req: dreg == eax and sreg2 != eax and breg != eax) + * hack to overcome limits in x86 reg allocator + * (req: dreg == eax and sreg2 != eax and breg != eax) */ g_assert (ins->dreg == X86_EAX); - + /* We need the EAX reg for the cmpxchg */ if (ins->sreg2 == X86_EAX) { sreg2 = (breg == X86_EDX) ? X86_EBX : X86_EDX; @@ -4417,11 +4417,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_SHUFPS: g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF); x86_sse_alu_reg_reg_imm8 (code, X86_SSE_SHUFP, ins->sreg1, ins->sreg2, ins->inst_c0); - break; + break; case OP_SHUFPD: g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3); x86_sse_alu_pd_reg_reg_imm8 (code, X86_SSE_SHUFP, ins->sreg1, ins->sreg2, ins->inst_c0); - break; + break; case OP_ADDPD: x86_sse_alu_pd_reg_reg (code, X86_SSE_ADD, ins->sreg1, ins->sreg2); @@ -4472,11 +4472,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_DUPPD: x86_sse_alu_sd_reg_reg (code, X86_SSE_MOVDDUP, ins->dreg, ins->sreg1); break; - + case OP_EXTRACT_MASK: x86_sse_alu_pd_reg_reg (code, X86_SSE_PMOVMSKB, ins->dreg, ins->sreg1); break; - + case OP_PAND: x86_sse_alu_pd_reg_reg (code, X86_SSE_PAND, ins->sreg1, ins->sreg2); break; @@ -4522,7 +4522,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PMAXD_UN: x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXUD, ins->sreg1, ins->sreg2); break; - + case OP_PMAXB: x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXSB, ins->sreg1, ins->sreg2); break; @@ -4666,7 +4666,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_PSUBW_SAT: x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBSW, ins->sreg1, ins->sreg2); break; - + case OP_PMULW: x86_sse_alu_pd_reg_reg (code, X86_SSE_PMULLW, ins->sreg1, ins->sreg2); break; @@ -4737,8 +4737,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_PSHLQ_REG: x86_sse_shift_reg_reg (code, X86_SSE_PSLLQ_REG, ins->dreg, ins->sreg2); - break; - + break; + case OP_ICONV_TO_X: x86_movd_xreg_reg (code, ins->dreg, ins->sreg1); break; @@ -4831,7 +4831,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /*FIXME the peephole pass should have killed this*/ if (ins->dreg != ins->sreg1) x86_movaps_reg_reg (code, ins->dreg, ins->sreg1); - break; + break; case OP_XZERO: x86_sse_alu_pd_reg_reg (code, X86_SSE_PXOR, ins->dreg, ins->dreg); break; @@ -4859,7 +4859,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCONV_TO_U2: x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE); break; - } + } break; case OP_EXPAND_I2: @@ -4965,7 +4965,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } - + cpos += max_len; } @@ -5275,7 +5275,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) /* the code restoring the registers must be kept in sync with OP_TAILCALL */ pos = 0; - + if (method->save_lmf) { gint32 lmf_offset = cfg->lmf_var->inst_offset; @@ -5376,7 +5376,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) exc_count++; } - /* + /* * make sure we have enough space for exceptions * 16 is the size of two push_imm instructions and a call */ @@ -5470,7 +5470,7 @@ mono_arch_flush_register_windows (void) { } -gboolean +gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm) { return TRUE; @@ -5689,7 +5689,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho } else if (strcmp (cmethod->name, "Round") == 0 && fsig->param_count == 1 && fsig->params [0]->type == MONO_TYPE_R8) { opcode = OP_ROUND; } - + if (opcode && fsig->param_count == 1) { MONO_INST_NEW (cfg, ins, opcode); ins->type = STACK_R8; @@ -5707,7 +5707,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho } else if (strcmp (cmethod->name, "Max") == 0) { if (fsig->params [0]->type == MONO_TYPE_I4) opcode = OP_IMAX; - } + } if (opcode && fsig->param_count == 2) { MONO_INST_NEW (cfg, ins, opcode); @@ -5860,7 +5860,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par * and we need: * * - * + * * without unbalancing the stack. * So move each arg up a spot in the stack (overwriting un-needed 'this' arg) * and leaving original spot of first arg as placeholder in stack so @@ -6133,12 +6133,12 @@ get_float_to_x_spill_area (MonoCompile *cfg) if (!cfg->fconv_to_r8_x_var) { cfg->fconv_to_r8_x_var = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_defaults.double_class), OP_LOCAL); cfg->fconv_to_r8_x_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/ - } + } return cfg->fconv_to_r8_x_var; } /* - * Convert all fconv opts that MONO_OPT_SSE2 would get wrong. + * Convert all fconv opts that MONO_OPT_SSE2 would get wrong. */ void mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) @@ -6203,12 +6203,12 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins) if (!(cfg->opt & MONO_OPT_SIMD)) return; - - /*TODO move this to simd-intrinsic.c once we support sse 4.1 dword extractors since we need the runtime caps info */ + + /*TODO move this to simd-intrinsic.c once we support sse 4.1 dword extractors since we need the runtime caps info */ switch (long_ins->opcode) { case OP_EXTRACT_I8: vreg = long_ins->sreg1; - + if (long_ins->inst_c0) { MONO_INST_NEW (cfg, ins, OP_PSHUFLED); ins->klass = long_ins->klass; @@ -6218,14 +6218,14 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins) ins->dreg = vreg = alloc_ireg (cfg); MONO_ADD_INS (cfg->cbb, ins); } - + MONO_INST_NEW (cfg, ins, OP_EXTRACT_I4); ins->klass = mono_defaults.int32_class; ins->sreg1 = vreg; ins->type = STACK_I4; ins->dreg = MONO_LVREG_LS (long_ins->dreg); MONO_ADD_INS (cfg->cbb, ins); - + MONO_INST_NEW (cfg, ins, OP_PSHUFLED); ins->klass = long_ins->klass; ins->sreg1 = long_ins->sreg1; @@ -6233,14 +6233,14 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins) ins->type = STACK_VTYPE; ins->dreg = vreg = alloc_ireg (cfg); MONO_ADD_INS (cfg->cbb, ins); - + MONO_INST_NEW (cfg, ins, OP_EXTRACT_I4); ins->klass = mono_defaults.int32_class; ins->sreg1 = vreg; ins->type = STACK_I4; ins->dreg = MONO_LVREG_MS (long_ins->dreg); MONO_ADD_INS (cfg->cbb, ins); - + long_ins->opcode = OP_NOP; break; case OP_INSERTX_I8_SLOW: @@ -6301,8 +6301,8 @@ guint8* mono_arch_emit_load_got_addr (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji) { x86_call_imm (code, 0); - /* - * The patch needs to point to the pop, since the GOT offset needs + /* + * The patch needs to point to the pop, since the GOT offset needs * to be added to that address. */ if (cfg) @@ -6321,7 +6321,7 @@ mono_arch_emit_load_got_addr (guint8 *start, guint8 *code, MonoCompile *cfg, Mon * * Emit code to load the contents of the GOT slot identified by TRAMP_TYPE and * TARGET from the mscorlib GOT in full-aot code. - * On x86, the GOT address is assumed to be in EBX, and the result is placed into + * On x86, the GOT address is assumed to be in EBX, and the result is placed into * EAX. */ guint8* @@ -6385,7 +6385,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) for (i = 0; i < 2; ++i) x86_nop (code); } - + /* * mono_arch_start_single_stepping: * @@ -6396,7 +6396,7 @@ mono_arch_start_single_stepping (void) { ss_trampoline = mini_get_single_step_trampoline (); } - + /* * mono_arch_stop_single_stepping: * diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 2d6e3a22930f7..bf3a2d3282295 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -123,7 +123,7 @@ mono_emit_unwind_op (MonoCompile *cfg, int when, int tag, int reg, int val) op->reg = reg; op->val = val; op->when = when; - + cfg->unwind_ops = g_slist_append_mempool (cfg->mempool, cfg->unwind_ops, op); if (cfg->verbose_level > 1) { switch (tag) { @@ -219,7 +219,7 @@ mono_find_block_region_notry (MonoCompile *cfg, int offset) if ((clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) && (offset >= clause->data.filter_offset) && (offset < (clause->handler_offset))) return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags; - + if (MONO_OFFSET_IN_HANDLER (clause, offset)) { if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags; @@ -244,13 +244,13 @@ mono_get_block_region_notry (MonoCompile *cfg, int region) { if ((region & (0xf << 4)) == MONO_REGION_TRY) { MonoMethodHeader *header = cfg->header; - + /* * This can happen if a try clause is nested inside a finally clause. */ int clause_index = (region >> 8) - 1; g_assert (clause_index >= 0 && clause_index < header->num_clauses); - + region = mono_find_block_region_notry (cfg, header->clauses [clause_index].try_offset); } @@ -302,7 +302,7 @@ mono_reverse_branch_op (guint32 opcode) OP_IBNE_UN, OP_IBLT, OP_IBLE, OP_IBGT, OP_IBGE, OP_IBEQ, OP_IBLT_UN, OP_IBLE_UN, OP_IBGT_UN, OP_IBGE_UN }; - + if (opcode >= CEE_BEQ && opcode <= CEE_BLT_UN) { opcode = reverse_map [opcode - CEE_BEQ]; } else if (opcode >= OP_FBEQ && opcode <= OP_FBLT_UN) { @@ -342,7 +342,7 @@ mono_type_to_store_membase (MonoCompile *cfg, MonoType *type) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return OP_STORE_MEMBASE_REG; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -403,7 +403,7 @@ mono_type_to_load_membase (MonoCompile *cfg, MonoType *type) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return OP_LOAD_MEMBASE; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -674,7 +674,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, if (mini_type_is_reference (type)) mono_mark_vreg_as_ref (cfg, vreg); #endif - + cfg->varinfo [num] = inst; cfg->vars [num].idx = num; @@ -698,12 +698,12 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, if (regpair) { MonoInst *tree; - /* + /* * These two cannot be allocated using create_var_for_vreg since that would * put it into the cfg->varinfo array, confusing many parts of the JIT. */ - /* + /* * Set flags to VOLATILE so SSA skips it. */ @@ -802,7 +802,7 @@ mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg) memcpy (cfg->vreg_is_ref, tmp, size * sizeof (gboolean)); } cfg->vreg_is_ref [vreg] = TRUE; -} +} void mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg) @@ -818,7 +818,7 @@ mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg) memcpy (cfg->vreg_is_mp, tmp, size * sizeof (gboolean)); } cfg->vreg_is_mp [vreg] = TRUE; -} +} static MonoType* type_from_stack_type (MonoInst *ins) @@ -829,7 +829,7 @@ type_from_stack_type (MonoInst *ins) case STACK_PTR: return mono_get_int_type (); case STACK_R8: return m_class_get_byval_arg (mono_defaults.double_class); case STACK_MP: - /* + /* * this if used to be commented without any specific reason, but * it breaks #80235 when commented */ @@ -915,7 +915,7 @@ mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst) mono_bblock_insert_before_ins (bb, bb->last_ins->prev, inst); } else { mono_bblock_insert_before_ins (bb, bb->last_ins, inst); - } + } } } else @@ -933,7 +933,7 @@ mono_create_jump_table (MonoCompile *cfg, MonoInst *label, MonoBasicBlock **bbs, table = (MonoJumpInfoBBTable *)mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable)); table->table = bbs; table->table_size = num_blocks; - + ji->ip.label = label; ji->type = MONO_PATCH_INFO_SWITCH; ji->data.table = table; @@ -958,7 +958,7 @@ typedef struct { GSList *slots; } StackSlotInfo; -static gint +static gint compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b) { MonoMethodVar *v1 = (MonoMethodVar*)a; @@ -1199,11 +1199,11 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ } } - /* + /* * This also handles the case when the variable is used in an * exception region, as liveness info is not computed there. */ - /* + /* * FIXME: All valuetypes are marked as INDIRECT because of LDADDR * opcodes. */ @@ -1438,7 +1438,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s slot = 0xffffff; if (cfg->comp_done & MONO_COMP_LIVENESS) { //printf ("START %2d %08x %08x\n", vmv->idx, vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos); - + /* expire old intervals in active */ while (slot_info->active) { MonoMethodVar *amv = (MonoMethodVar *)slot_info->active->data; @@ -1452,11 +1452,11 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s slot_info->slots = g_slist_prepend_mempool (cfg->mempool, slot_info->slots, GINT_TO_POINTER (offsets [amv->idx])); } - /* + /* * This also handles the case when the variable is used in an * exception region, as liveness info is not computed there. */ - /* + /* * FIXME: All valuetypes are marked as INDIRECT because of LDADDR * opcodes. */ @@ -1507,7 +1507,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s if (MONO_TYPE_ISSTRUCT (t)) { align = MAX (align, sizeof (target_mgreg_t)); align = MAX (align, mono_class_min_align (mono_class_from_mono_type_internal (t))); - /* + /* * Align the size too so the code generated for passing vtypes in * registers doesn't overwrite random locals. */ @@ -1746,7 +1746,7 @@ mono_verify_cfg (MonoCompile *cfg) // This will free many fields in cfg to save // memory. Note that this must be safe to call -// multiple times. It must be idempotent. +// multiple times. It must be idempotent. void mono_empty_compile (MonoCompile *cfg) { @@ -1891,7 +1891,7 @@ mono_compile_create_vars (MonoCompile *cfg) header = cfg->header; sig = mono_method_signature_internal (cfg->method); - + if (!MONO_TYPE_IS_VOID (sig->ret)) { cfg->ret = mono_compile_create_var (cfg, sig->ret, OP_ARG); /* Inhibit optimizations */ @@ -1969,7 +1969,7 @@ void mono_print_code (MonoCompile *cfg, const char* msg) { MonoBasicBlock *bb; - + for (bb = cfg->bb_entry; bb; bb = bb->next_bb) mono_print_bb (bb, msg); } @@ -2145,7 +2145,7 @@ mono_codegen (MonoCompile *cfg) g_free (cfg->native_code); cfg->native_code = code; code = cfg->native_code + cfg->code_len; - + /* g_assert (((int)cfg->native_code & (MONO_ARCH_CODE_ALIGNMENT - 1)) == 0); */ mono_postprocess_patches (cfg); @@ -2156,11 +2156,11 @@ mono_codegen (MonoCompile *cfg) g_free (nm); } #endif - + if (cfg->verbose_level > 0) { char* nm = mono_method_get_full_name (cfg->method); g_print ("Method %s emitted at %p to %p (code length %d)\n", - nm, + nm, cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len); g_free (nm); } @@ -2218,7 +2218,7 @@ mono_codegen (MonoCompile *cfg) mono_codeman_disable_write (); MONO_PROFILER_RAISE (jit_code_buffer, (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method)); - + mono_arch_flush_icache (cfg->native_code, cfg->code_len); mono_debug_close_method (cfg); @@ -2263,7 +2263,7 @@ static void mono_bb_ordering (MonoCompile *cfg) cfg->num_bblocks = dfn + 1; - /* remove unreachable code, because the code in them may be + /* remove unreachable code, because the code in them may be * inconsistent (access to dead variables for example) */ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) bb->flags &= ~BB_VISITED; @@ -3313,7 +3313,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->method_to_register = method_to_register; ERROR_DECL (err); - sig = mono_method_signature_checked (cfg->method, err); + sig = mono_method_signature_checked (cfg->method, err); if (!sig) { cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD; cfg->exception_message = g_strdup (mono_error_get_message (err)); @@ -3344,7 +3344,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts if (!inited) inited = TRUE; - /* + /* * Check for methods which cannot be compiled by LLVM early, to avoid * the extra compilation pass. */ @@ -3382,7 +3382,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts if (mini_debug_options.mdb_optimizations || MONO_CFG_PROFILE_CALL_CONTEXT (cfg)) { cfg->disable_reuse_registers = TRUE; cfg->disable_reuse_stack_slots = TRUE; - /* + /* * This decreases the change the debugger will read registers/stack slots which are * not yet initialized. */ @@ -3426,18 +3426,18 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts char *env = g_getenv ("MONO_VERBOSE_METHOD"); if (env != NULL) verbose_method_names = g_strsplit (env, ";", -1); - + verbose_method_inited = TRUE; } if (verbose_method_names) { int i; - + for (i = 0; verbose_method_names [i] != NULL; i++){ const char *name = verbose_method_names [i]; if ((strchr (name, '.') > name) || strchr (name, ':') || strchr (name, '*')) { MonoMethodDesc *desc; - + desc = mono_method_desc_new (name, TRUE); if (desc) { if (mono_method_desc_full_match (desc, cfg->method)) { @@ -3558,9 +3558,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->after_method_to_ir = TRUE; /* todo: remove code when we have verified that the liveness for try/catch blocks - * works perfectly + * works perfectly */ - /* + /* * Currently, this can't be commented out since exception blocks are not * processed during liveness analysis. * It is also needed, because otherwise the local optimization passes would @@ -3650,9 +3650,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts mono_cfg_dump_ir (cfg, "bb_ordering"); if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) { - /* + /* * we disable some optimizations if there are too many variables - * because JIT time may become too expensive. The actual number needs + * because JIT time may become too expensive. The actual number needs * to be tweaked and eventually the non-linear algorithms should be fixed. */ cfg->opt &= ~ (MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP); @@ -3696,7 +3696,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts mono_ssa_compute (cfg); #endif } -#else +#else if (cfg->opt & MONO_OPT_SSA) { if (!(cfg->comp_done & MONO_COMP_SSA) && !cfg->disable_ssa) { #ifndef DISABLE_SSA @@ -3797,11 +3797,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts g_assert (cfg->got_var_allocated); - /* + /* * Allways allocate the GOT var to a register, because keeping it * in memory will increase the number of live temporaries in some * code created by inssel.brg, leading to the well known spills+ - * branches problem. Testcase: mcs crash in + * branches problem. Testcase: mcs crash in * System.MonoCustomAttrs:GetCustomAttributes. */ #ifdef MONO_ARCH_GOT_REG @@ -3824,7 +3824,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts if (cfg->opt & MONO_OPT_LINEARS) { GList *vars, *regs, *l; - + /* fixme: maybe we can avoid to compute livenesss here if already computed ? */ cfg->comp_done &= ~MONO_COMP_LIVENESS; if (!(cfg->comp_done & MONO_COMP_LIVENESS)) @@ -3849,7 +3849,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts //mono_print_code (cfg, ""); //print_dfn (cfg); - + /* variables are allocated after decompose, since decompose could create temps */ if (!COMPILE_LLVM (cfg)) { MONO_TIME_TRACK (mono_jit_stats.jit_arch_allocate_vars, mono_arch_allocate_vars (cfg)); @@ -3917,7 +3917,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts if (cfg->verbose_level > 0 && !cfg->compile_aot) { nm = mono_method_get_full_name (cfg->method); g_print ("LLVM Method %s emitted at %p to %p (code length %d)\n", - nm, + nm, cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len); g_free (nm); } @@ -4466,7 +4466,7 @@ mini_get_cpu_features (MonoCompile* cfg) // This is a standard part of ARMv8-A; see A1.5 in "ARM // Architecture Reference Manual ARMv8, for ARMv8-A // architecture profile" - features |= MONO_CPU_ARM64_NEON; + features |= MONO_CPU_ARM64_NEON; #endif // apply parameters passed via -mattr diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 85f64cd67cc77..baa30d8bdcdb5 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -265,7 +265,7 @@ enum { NULLIFY_INS ((ins)); \ } while (0) -/* +/* * this is used to determine when some branch optimizations are possible: we exclude FP compares * because they have weird semantics with NaNs. */ @@ -454,7 +454,7 @@ typedef struct { int pc_offset; /* The basic block containing the call site */ MonoBasicBlock *bb; - /* + /* * The set of variables live at the call site. * Has length cfg->num_varinfo in bits. */ @@ -467,7 +467,7 @@ typedef struct { } GCCallSite; /* - * The IR-level extended basic block. + * The IR-level extended basic block. * * A basic block can have multiple exits just fine, as long as the point of * 'departure' is the last instruction in the basic block. Extended basic @@ -492,7 +492,7 @@ struct MonoBasicBlock { /* unique block number identification */ gint32 block_num; - + gint32 dfn; /* Basic blocks: incoming and outgoing counts and pointers */ @@ -529,13 +529,13 @@ struct MonoBasicBlock { /* fast dominator algorithm */ MonoBasicBlock *df_parent, *ancestor, *child, *label; int size, sdom, idomn; - + /* loop nesting and recognition */ GList *loop_blocks; gint8 nesting; gint8 loop_body_start; - /* + /* * Whenever the bblock is rarely executed so it should be emitted after * the function epilog. */ @@ -564,7 +564,7 @@ struct MonoBasicBlock { * call). */ guint extend_try_block : 1; - + /* use for liveness analysis */ MonoBitSet *gen_set; MonoBitSet *kill_set; @@ -583,7 +583,7 @@ struct MonoBasicBlock { // The MonoInst of the last sequence point for the current basic block. MonoInst *last_seq_point; - + // This will hold a list of last sequence points of incoming basic blocks MonoInst **pred_seq_points; guint num_pred_seq_points; @@ -609,7 +609,7 @@ struct MonoBasicBlock { * * Bits: | 0-3 | 4-7 | 8-31 * | | | - * | clause-flags | MONO_REGION | clause-index + * | clause-flags | MONO_REGION | clause-index * */ guint region; @@ -709,7 +709,7 @@ typedef struct { gboolean imt_arg; /* Whenever there is a dummy extra argument */ gboolean dummy_arg; - /* + /* * The position of the vret arg in the argument list. * Only if ret->storage == ArgVtypeRetAddr. * Should be 0 or 1. @@ -729,7 +729,7 @@ struct MonoInst { guint16 opcode; guint8 type; /* stack type */ guint8 flags; - + /* used by the register allocator */ gint32 dreg, sreg1, sreg2, sreg3; @@ -786,10 +786,10 @@ struct MonoInst { */ int memory_barrier_kind; } backend; - + MonoClass *klass; }; - + struct MonoCallInst { MonoInst inst; MonoMethodSignature *signature; @@ -845,7 +845,7 @@ struct MonoCallArgParm { gint32 offPrm; }; -/* +/* * flags for MonoInst * Note: some of the values overlap, because they can't appear * in the same MonoInst. @@ -869,7 +869,7 @@ enum { MONO_INST_NORANGECHECK = 16, /* On loads, the source address can be null */ MONO_INST_FAULT = 32, - /* + /* * On variables, identifies LMF variables. These variables have a dummy type (int), but * require stack space for a MonoLMF struct. */ @@ -957,7 +957,7 @@ typedef union { guint16 tid; /* tree number */ guint16 bid; /* block number */ } pos ; - guint32 abs_pos; + guint32 abs_pos; } MonoPosition; typedef struct { @@ -993,8 +993,8 @@ struct MonoMethodVar { char cpstate; /* used by SSA conditional constant propagation */ /* The native offsets corresponding to the live range of the variable */ gint32 live_range_start, live_range_end; - /* - * cfg->varinfo [idx]->dreg could be replaced for OP_REGVAR, this contains the + /* + * cfg->varinfo [idx]->dreg could be replaced for OP_REGVAR, this contains the * original vreg. */ gint32 vreg; @@ -1338,7 +1338,7 @@ typedef struct { MonoBackend *backend; - /* + /* * This variable represents the hidden argument holding the vtype * return address. If the method returns something other than a vtype, or * the vtype is returned in registers this is NULL. @@ -1349,7 +1349,7 @@ typedef struct { * This is used to initialize the cil_code field of MonoInst's. */ const unsigned char *ip; - + struct MonoAliasingInformation *aliasing_info; /* A hashtable of region ID-> SP var mappings */ @@ -1369,7 +1369,7 @@ typedef struct { GHashTable *exvars; GList *ldstr_list; /* used by AOT */ - + guint real_offset; GHashTable *cbb_hash; @@ -1542,7 +1542,7 @@ typedef struct { /* Size of above array */ guint32 vreg_is_mp_len; - /* + /* * The original method to compile, differs from 'method' when doing generic * sharing. */ @@ -1610,7 +1610,7 @@ typedef struct { GSList *interp_in_signatures; /* GC Maps */ - + /* The offsets of the locals area relative to the frame pointer */ gint locals_min_stack_offset, locals_max_stack_offset; @@ -1999,12 +1999,12 @@ enum { MONO_EXC_INTRINS_NUM }; - /* + /* * Information about a trampoline function. */ struct MonoTrampInfo { - /* + /* * The native code of the trampoline. Not owned by this structure. */ guint8 *code; @@ -2014,7 +2014,7 @@ struct MonoTrampInfo * structure. */ char *name; - /* + /* * Patches required by the trampoline when aot-ing. Owned by this structure. */ MonoJumpInfo *ji; @@ -2242,7 +2242,7 @@ mini_register_opcode_emulation (int opcode, MonoJitICallInfo *jit_icall_info, co void mono_trampolines_init (void); guint8 * mono_get_trampoline_code (MonoTrampolineType tramp_type); gpointer mono_create_specific_trampoline (MonoMemoryManager *mem_manager, gpointer arg1, MonoTrampolineType tramp_type, guint32 *code_len); -gpointer mono_create_jump_trampoline (MonoMethod *method, +gpointer mono_create_jump_trampoline (MonoMethod *method, gboolean add_sync_wrapper, MonoError *error); gpointer mono_create_jit_trampoline (MonoMethod *method, MonoError *error); @@ -2256,9 +2256,9 @@ gpointer mono_create_ftnptr_arg_trampoline (gpointer arg, gpointer addr guint32 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr); gpointer mono_magic_trampoline (host_mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp); gpointer mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp); -gpointer mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, +gpointer mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, guint8* tramp); -gpointer mono_aot_plt_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, +gpointer mono_aot_plt_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info, guint8* tramp); gconstpointer mono_get_trampoline_func (MonoTrampolineType tramp_type); gpointer mini_get_vtable_trampoline (MonoVTable *vt, int slot_index); @@ -2341,11 +2341,11 @@ CompRelation mono_negate_cond (CompRelation cond); int mono_op_imm_to_op (int opcode); void mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins); void mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins); -MonoUnwindOp *mono_create_unwind_op (int when, - int tag, int reg, +MonoUnwindOp *mono_create_unwind_op (int when, + int tag, int reg, int val); -void mono_emit_unwind_op (MonoCompile *cfg, int when, - int tag, int reg, +void mono_emit_unwind_op (MonoCompile *cfg, int when, + int tag, int reg, int val); MonoTrampInfo* mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops); void mono_tramp_info_free (MonoTrampInfo *info); @@ -2354,7 +2354,7 @@ void mono_tramp_info_register (MonoTrampInfo *info, MonoMemoryManag int mini_exception_id_by_name (const char *name); gboolean mini_type_is_hfa (MonoType *t, int *out_nfields, int *out_esize); -int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, +int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, MonoInst *return_var, MonoInst **inline_args, guint inline_offset, gboolean is_virtual_call); @@ -2475,7 +2475,7 @@ SeqPointInfo *mono_arch_get_seq_point_info (guint8 *code); gboolean mono_arch_unwind_frame (MonoJitTlsData *jit_tls, - MonoJitInfo *ji, MonoContext *ctx, + MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame_info); @@ -2610,8 +2610,8 @@ ICALL_EXPORT MonoArray *ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info); ICALL_EXPORT -MonoBoolean ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, - MonoReflectionMethod **method, +MonoBoolean ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, + MonoReflectionMethod **method, gint32 *iloffset, gint32 *native_offset, MonoString **file, gint32 *line, gint32 *column); void mono_set_cast_details (MonoClass *from, MonoClass *to); @@ -2644,7 +2644,7 @@ void mono_debug_free_method (MonoCompile *cfg); void mono_debug_open_block (MonoCompile *cfg, MonoBasicBlock *bb, guint32 address); void mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address); void mono_debug_serialize_debug_info (MonoCompile *cfg, guint8 **out_buf, guint32 *buf_len); -void mono_debug_add_aot_method (MonoMethod *method, guint8 *code_start, +void mono_debug_add_aot_method (MonoMethod *method, guint8 *code_start, guint8 *debug_info, guint32 debug_info_len); MONO_API void mono_debug_print_vars (gpointer ip, gboolean only_arguments); MONO_API void mono_debugger_run_finally (MonoContext *start_ctx); @@ -2886,7 +2886,7 @@ typedef enum { MONO_CPU_X86_AVX_COMBINED = MONO_CPU_X86_SSE42_COMBINED | MONO_CPU_X86_AVX, MONO_CPU_X86_AVX2_COMBINED = MONO_CPU_X86_AVX_COMBINED | MONO_CPU_X86_AVX2, MONO_CPU_X86_FMA_COMBINED = MONO_CPU_X86_AVX_COMBINED | MONO_CPU_X86_FMA, - MONO_CPU_X86_FULL_SSEAVX_COMBINED = MONO_CPU_X86_FMA_COMBINED | MONO_CPU_X86_AVX2 | MONO_CPU_X86_PCLMUL + MONO_CPU_X86_FULL_SSEAVX_COMBINED = MONO_CPU_X86_FMA_COMBINED | MONO_CPU_X86_AVX2 | MONO_CPU_X86_PCLMUL | MONO_CPU_X86_AES | MONO_CPU_X86_POPCNT | MONO_CPU_X86_FMA, #endif #ifdef TARGET_WASM diff --git a/src/mono/mono/mini/mono-private-unstable.h b/src/mono/mono/mini/mono-private-unstable.h index 03f24a08ec917..fade778a39857 100644 --- a/src/mono/mono/mini/mono-private-unstable.h +++ b/src/mono/mono/mini/mono-private-unstable.h @@ -1,6 +1,6 @@ /** * \file - * + * * Private unstable APIs. * * WARNING: The declarations and behavior of functions in this header are NOT STABLE and can be modified or removed at @@ -64,7 +64,7 @@ mono_install_load_aot_data_hook (MonoLoadAotDataFunc load_func, MonoFreeAotDataF MONO_API int monovm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues); -MONO_API int +MONO_API int monovm_runtimeconfig_initialize (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data); // The wrapper MonoCoreRuntimeProperties struct can be stack-allocated or freed, but the structs inside it _must_ be heap-allocated and never freed, as they are not copied to avoid extra allocations diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index e148596216599..a90b36ec3e3be 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -250,7 +250,7 @@ monovm_execute_assembly (int argc, const char **argv, const char *managedAssembl char **mono_argv = (char **) malloc (sizeof (char *) * (mono_argc + 1 /* null terminated */)); const char **ptr = (const char **) mono_argv; - + *ptr++ = NULL; // executable assembly @@ -280,7 +280,7 @@ monovm_shutdown (int *latchedExitCode) static int monovm_create_delegate_impl (const char* assemblyName, const char* typeName, const char *methodName, void **delegate); - + int monovm_create_delegate (const char *assemblyName, const char *typeName, const char *methodName, void **delegate) @@ -337,7 +337,7 @@ monovm_create_delegate_impl (const char* assemblyName, const char* typeName, con g_assert (t); MonoClass *klass = mono_class_from_mono_type_internal (t); - + MonoMethod *method = mono_class_get_method_from_name_checked (klass, methodName, -1, 0, error); goto_if_nok (error, fail); @@ -346,7 +346,7 @@ monovm_create_delegate_impl (const char* assemblyName, const char* typeName, con mono_error_set_not_supported (error, "MonoVM only supports UnmanagedCallersOnly implementations of hostfxr_get_runtime_delegate delegate types"); goto fail; } - + MonoClass *delegate_klass = NULL; MonoGCHandle target_handle = 0; MonoMethod *wrapper = mono_marshal_get_managed_wrapper (method, delegate_klass, target_handle, error); diff --git a/src/mono/mono/mini/regalloc.h b/src/mono/mono/mini/regalloc.h index c0aa5fdf64a8a..5ba2ee4bd0b02 100644 --- a/src/mono/mono/mini/regalloc.h +++ b/src/mono/mono/mini/regalloc.h @@ -14,7 +14,7 @@ enum { MONO_REG_SIMD }; - + #ifdef MONO_ARCH_NEED_SIMD_BANK #define MONO_NUM_REGBANKS 5 #else @@ -29,7 +29,7 @@ typedef struct { regmask_t free_mask [MONO_NUM_REGBANKS]; /* symbolic -> hard register assignment */ - /* + /* * If the register is spilled, then this contains -spill - 1, where 'spill' * is the index of the spill variable. */ diff --git a/src/mono/mono/mini/seq-points.c b/src/mono/mono/mini/seq-points.c index 257b408f192da..4a6c2dbb3710e 100644 --- a/src/mono/mono/mini/seq-points.c +++ b/src/mono/mono/mini/seq-points.c @@ -41,7 +41,7 @@ recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb) for (int i = 0; i < bb->in_count; ++i) { MonoBasicBlock *in_bb = bb->in_bb [i]; - + // This bb has the last seq point, append it and continue if (in_bb->last_seq_point != NULL) { predecessors = g_array_append_val (predecessors, in_bb->last_seq_point); @@ -54,7 +54,7 @@ recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb) continue; // Take sequence points from incoming basic blocks - + if (in_bb == cfg->bb_entry) continue; @@ -80,7 +80,7 @@ recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb) for (int newer = 0; newer < bb->num_pred_seq_points; newer++) { bb->pred_seq_points [newer] = g_array_index(predecessors, MonoInst*, newer); } - } + } g_array_free (predecessors, TRUE); } diff --git a/src/mono/mono/mini/seq-points.h b/src/mono/mono/mini/seq-points.h index a35584971c6c4..639b9ed60f09b 100644 --- a/src/mono/mono/mini/seq-points.h +++ b/src/mono/mono/mini/seq-points.h @@ -3,7 +3,7 @@ * Copyright 2014 Xamarin Inc * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ - + #ifndef __MONO_SEQ_POINTS_H__ #define __MONO_SEQ_POINTS_H__ diff --git a/src/mono/mono/mini/ssa.c b/src/mono/mono/mini/ssa.c index 47579c57e1285..df1ac7fb78ccf 100644 --- a/src/mono/mono/mini/ssa.c +++ b/src/mono/mono/mini/ssa.c @@ -38,7 +38,7 @@ typedef struct { MonoInst *inst; } MonoVarUsageInfo; -static void +static void unlink_target (MonoBasicBlock *bb, MonoBasicBlock *target) { int i; @@ -53,13 +53,13 @@ unlink_target (MonoBasicBlock *bb, MonoBasicBlock *target) if (target->in_bb [i] == bb) { target->in_bb [i] = target->in_bb [--target->in_count]; break; - + } } } static void -unlink_unused_bblocks (MonoCompile *cfg) +unlink_unused_bblocks (MonoCompile *cfg) { int i, j; MonoBasicBlock *bb; @@ -72,24 +72,24 @@ unlink_unused_bblocks (MonoCompile *cfg) for (bb = cfg->bb_entry; bb && bb->next_bb;) { if (!(bb->next_bb->flags & BB_REACHABLE)) { bb->next_bb = bb->next_bb->next_bb; - } else + } else bb = bb->next_bb; } for (i = 1; i < cfg->num_bblocks; i++) { bb = cfg->bblocks [i]; - + if (!(bb->flags & BB_REACHABLE)) { for (j = 0; j < bb->in_count; j++) { - unlink_target (bb->in_bb [j], bb); + unlink_target (bb->in_bb [j], bb); } for (j = 0; j < bb->out_count; j++) { - unlink_target (bb, bb->out_bb [j]); + unlink_target (bb, bb->out_bb [j]); } if (G_UNLIKELY (cfg->verbose_level > 1)) printf ("\tUnlinked BB%d\n", bb->block_num); } - + } } @@ -148,11 +148,11 @@ record_use (MonoCompile *cfg, MonoInst *var, MonoBasicBlock *bb, MonoInst *ins) MonoVarUsageInfo *ui = (MonoVarUsageInfo *)mono_mempool_alloc (cfg->mempool, sizeof (MonoVarUsageInfo)); info = MONO_VARINFO (cfg, var->inst_c0); - + ui->bb = bb; ui->inst = ins; info->uses = g_list_prepend_mempool (cfg->mempool, info->uses, ui); -} +} typedef struct { MonoInst *var; @@ -331,7 +331,7 @@ typedef struct { /** * mono_ssa_rename_vars: * Implement renaming of SSA variables. Also compute def-use information in parallel. - * \p stack_history points to an area of memory which can be used for storing changes + * \p stack_history points to an area of memory which can be used for storing changes * made to the stack, so they can be reverted later. */ static void @@ -476,7 +476,7 @@ mono_ssa_compute (MonoCompile *cfg) mono_blockset_print (cfg, set, "", -1); } } - + mono_bitset_foreach_bit (set, idx, cfg->num_bblocks) { MonoBasicBlock *bb = cfg->bblocks [idx]; @@ -675,7 +675,7 @@ mono_ssa_remove (MonoCompile *cfg) } /* - * Removal of SSA form introduces many copies. To avoid this, we tyry to coalesce + * Removal of SSA form introduces many copies. To avoid this, we tyry to coalesce * the variables if possible. Since the newly introduced SSA variables don't * have overlapping live ranges (because we don't do agressive optimization), we * can coalesce them into the original variable. @@ -697,14 +697,14 @@ mono_ssa_remove (MonoCompile *cfg) if (var) { MonoMethodVar *vmv = MONO_VARINFO (cfg, var->inst_c0); - - /* + + /* * The third condition avoids coalescing with variables eliminated * during deadce. */ if ((vmv->reg != -1) && (vmv->idx != vmv->reg) && (MONO_VARINFO (cfg, vmv->reg)->reg != -1)) { printf ("COALESCE: R%d -> R%d\n", ins->dreg, cfg->varinfo [vmv->reg]->dreg); - ins->dreg = cfg->varinfo [vmv->reg]->dreg; + ins->dreg = cfg->varinfo [vmv->reg]->dreg; } } } @@ -739,7 +739,7 @@ mono_ssa_remove (MonoCompile *cfg) } static void -mono_ssa_create_def_use (MonoCompile *cfg) +mono_ssa_create_def_use (MonoCompile *cfg) { MonoBasicBlock *bb; MonoInst *ins; @@ -999,7 +999,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars, change_varstate (cfg, cvars, info, 2, NULL, carray); break; } - + if (mv->cpstate == 0) continue; @@ -1007,7 +1007,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars, if (!c0) c0 = carray [var->dreg]; - + /* FIXME: */ if (c0->opcode != OP_ICONST) { change_varstate (cfg, cvars, info, 2, NULL, carray); @@ -1019,7 +1019,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars, break; } } - + if (c0 && info->cpstate < 1) { change_varstate (cfg, cvars, info, 1, c0, carray); @@ -1050,7 +1050,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars, } else if (!var && (ins->dreg != -1)) { /* - * We don't record def-use information for local vregs since it would be + * We don't record def-use information for local vregs since it would be * expensive. Instead, we depend on the fact that all uses of the vreg are in * the same bblock, so they will be examined after the definition. * FIXME: This isn't true if the ins is visited through an SSA edge. @@ -1059,7 +1059,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars, carray [ins->dreg] = c0; } else { if (carray [ins->dreg]) { - /* + /* * The state of the vreg changed from constant to non-constant * -> need to rescan the whole bblock. */ @@ -1255,7 +1255,7 @@ fold_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst **carray NULLIFY_INS (ins->next->next); } } - } + } else if (MONO_IS_COND_BRANCH_OP (ins)) { if (ins->flags & MONO_INST_CFOLD_TAKEN) { remove_bb_from_phis (cfg, bb, ins->inst_false_bb); @@ -1272,7 +1272,7 @@ fold_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst **carray } void -mono_ssa_cprop (MonoCompile *cfg) +mono_ssa_cprop (MonoCompile *cfg) { MonoInst **carray; MonoBasicBlock *bb; @@ -1317,7 +1317,7 @@ mono_ssa_cprop (MonoCompile *cfg) g_assert (bb->flags & BB_REACHABLE); - /* + /* * Some bblocks are linked to 2 others even through they fall through to the * next bblock. */ @@ -1334,7 +1334,7 @@ mono_ssa_cprop (MonoCompile *cfg) } while (cvars) { - MonoMethodVar *info = (MonoMethodVar *)cvars->data; + MonoMethodVar *info = (MonoMethodVar *)cvars->data; cvars = g_list_delete_link (cvars, cvars); for (tmp = info->uses; tmp; tmp = tmp->next) { @@ -1380,11 +1380,11 @@ add_to_dce_worklist (MonoCompile *cfg, MonoMethodVar *var, MonoMethodVar *use, G use->uses = g_list_remove_link (use->uses, tmp); break; } - } + } } void -mono_ssa_deadce (MonoCompile *cfg) +mono_ssa_deadce (MonoCompile *cfg) { int i; GList *work_list; @@ -1408,7 +1408,7 @@ mono_ssa_deadce (MonoCompile *cfg) MonoMethodVar *info = (MonoMethodVar *)work_list->data; work_list = g_list_remove_link (work_list, work_list); - /* + /* * The second part of the condition happens often when PHI nodes have their dreg * as one of their arguments due to the fact that we use the original vars. */ @@ -1466,7 +1466,7 @@ mono_ssa_strength_reduction (MonoCompile *cfg) for (i = 0; i < cfg->num_varinfo; i++) { MonoMethodVar *info = MONO_VARINFO (cfg, i); - + if (info->def && info->def->ssa_op == MONO_SSA_STORE && info->def->inst_i0->opcode == OP_LOCAL && g_list_find (lp, info->def_bb)) { MonoInst *v = info->def->inst_i1; diff --git a/src/mono/mono/mini/trace.h b/src/mono/mono/mini/trace.h index f973d10fbd1fa..a286e574e1f4b 100644 --- a/src/mono/mono/mini/trace.h +++ b/src/mono/mono/mini/trace.h @@ -13,11 +13,11 @@ void mono_trace_enter_method (MonoMethod *method, MonoJitInfo *ji, MonoProfilerCallContext *ctx); ICALL_EXPORT -void +void mono_trace_leave_method (MonoMethod *method, MonoJitInfo *ji, MonoProfilerCallContext *ctx); ICALL_EXPORT -void +void mono_trace_tail_method (MonoMethod *method, MonoJitInfo *ji, MonoMethod *target); void mono_trace_enable (gboolean enable); diff --git a/src/mono/mono/mini/tramp-amd64-gsharedvt.c b/src/mono/mono/mini/tramp-amd64-gsharedvt.c index 0d564fbeefe45..b8f45e7afe907 100644 --- a/src/mono/mono/mini/tramp-amd64-gsharedvt.c +++ b/src/mono/mono/mini/tramp-amd64-gsharedvt.c @@ -252,7 +252,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) /* setup the frame */ amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize); - + /* save stuff */ /* save info */ @@ -294,7 +294,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) /* arg1 == info */ amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RAX, sizeof (target_mgreg_t)); /* arg2 = caller stack area */ - amd64_lea_membase (code, MONO_AMD64_ARG_REG2, AMD64_RBP, -(framesize - caller_reg_area_offset)); + amd64_lea_membase (code, MONO_AMD64_ARG_REG2, AMD64_RBP, -(framesize - caller_reg_area_offset)); /* arg3 == callee stack area */ amd64_lea_membase (code, MONO_AMD64_ARG_REG3, AMD64_RSP, callee_reg_area_offset); diff --git a/src/mono/mono/mini/tramp-amd64.c b/src/mono/mono/mini/tramp-amd64.c index ad749405c1511..6c4557a4da971 100644 --- a/src/mono/mono/mini/tramp-amd64.c +++ b/src/mono/mono/mini/tramp-amd64.c @@ -159,7 +159,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) gboolean disp_32bit = ((((gint64)addr - (gint64)orig_code)) < (1 << 30)) && ((((gint64)addr - (gint64)orig_code)) > -(1 << 30)); if ((((guint64)(addr)) >> 32) != 0 && !disp_32bit) { - /* + /* * This might happen with LLVM or when calling AOTed code. Create a thunk. */ guint8 *thunk_start, *thunk_code; @@ -290,7 +290,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf cfa_offset -= sizeof (target_mgreg_t); mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset); - /* + /* * Allocate a new stack frame */ amd64_push_reg (code, AMD64_RBP); @@ -473,7 +473,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), sizeof (target_mgreg_t)); amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof (target_mgreg_t)); - /* + /* * Save rax to the stack, after the leave instruction, this will become part of * the red zone. */ @@ -482,7 +482,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Check for thread interruption */ /* This is not perf critical code so no need to check the interrupt flag */ - /* + /* * Have to call the _force_ variant, since there could be a protected wrapper on the top of the stack. */ if (aot) { @@ -626,7 +626,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type))); return buf; -} +} gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) @@ -966,7 +966,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo amd64_mov_reg_imm (code, AMD64_R11, mono_component_debugger ()->single_step_from_context); else amd64_mov_reg_imm (code, AMD64_R11, mono_component_debugger ()->breakpoint_from_context); - } + } amd64_call_reg (code, AMD64_R11); /* Restore registers from ctx */ diff --git a/src/mono/mono/mini/tramp-arm.c b/src/mono/mono/mini/tramp-arm.c index 0834f106505e3..4b12b2aab0bda 100644 --- a/src/mono/mono/mini/tramp-arm.c +++ b/src/mono/mono/mini/tramp-arm.c @@ -40,7 +40,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) /* This is the 'bl' or the 'mov pc' instruction */ --code; - + /* * Note that methods are called also with the bl opcode. */ @@ -70,10 +70,10 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guin if (*(guint32*)code == 0xe59fc000) { /* ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); */ guint32 offset = ((guint32*)code)[2]; - + jump_entry = code + offset + 12; } else if (*(guint16*)(code - 4) == 0xf8df) { - /* + /* * Thumb PLT entry, begins with ldr.w ip, [pc, #8], code points to entry + 4, see * mono_arm_get_thumb_plt_entry (). */ @@ -178,9 +178,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_R4 + i, -regsave_size + ((4 + i) * 4)); if (aot) { - /* + /* * For page trampolines the data is in r1, so just move it, otherwise use the got slot as below. - * The trampoline contains a pc-relative offset to the got slot + * The trampoline contains a pc-relative offset to the got slot * preceeding the got slot where the value is stored. The offset can be * found at [lr + 0]. */ @@ -209,7 +209,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf code = mono_arm_emit_load_imm (code, ARMREG_R2, STACK - MONO_ABI_SIZEOF (MonoLMF)); ARM_ADD_REG_REG (code, ARMREG_V1, ARMREG_SP, ARMREG_R2); - /* ok, now we can continue with the MonoLMF setup, mostly untouched + /* ok, now we can continue with the MonoLMF setup, mostly untouched * from emit_prolog in mini-arm.c * This is a synthetized call to mono_get_lmf_addr () */ @@ -286,7 +286,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf } else { ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_V3); } - + /* Arg 3: the specific argument, stored in v2 */ ARM_MOV_REG_REG (code, ARMREG_R2, ARMREG_V2); @@ -1146,7 +1146,7 @@ mono_arm_get_thumb_plt_entry (guint8 *code) g_assert (((guint16*)target) [0] == 0xf8df); g_assert (((guint16*)target) [1] == 0xc008); - /* + /* * The PLT info offset is at offset 16, but mono_arch_get_plt_entry_offset () returns * the 3rd word, so compensate by returning a different value. */ diff --git a/src/mono/mono/mini/tramp-arm64.c b/src/mono/mono/mini/tramp-arm64.c index e0ea4f11e787e..e437bc2480333 100644 --- a/src/mono/mono/mini/tramp-arm64.c +++ b/src/mono/mono/mini/tramp-arm64.c @@ -5,7 +5,7 @@ * Copyright 2013 Xamarin Inc * * Based on tramp-arm.c: - * + * * Authors: * Paolo Molaro (lupus@ximian.com) * @@ -43,7 +43,7 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guin guint64 slot_addr; int disp; - /* + /* * Decode the address loaded by the PLT entry emitted by arch_emit_plt_entry () in * aot-compiler.c */ diff --git a/src/mono/mono/mini/tramp-mips.c b/src/mono/mono/mini/tramp-mips.c index fdd9e546bebd8..edfdbe2b405bd 100644 --- a/src/mono/mono/mini/tramp-mips.c +++ b/src/mono/mono/mini/tramp-mips.c @@ -41,7 +41,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) { guint8 *code, *start; MonoMemoryManager *mem_manager = m_method_get_mem_manager (m); - + start = code = mono_mem_manager_code_reserve (mem_manager, 20); mips_load (code, mips_t9, addr); @@ -81,7 +81,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) On entry, 'code' points just after one of the above sequences. */ - + /* The jal case */ if ((code[-2] >> 26) == 0x03) { //g_print ("direct patching\n"); @@ -107,7 +107,7 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guin g_assert_not_reached (); } -/* Stack size for trampoline function +/* Stack size for trampoline function * MIPS_MINIMAL_STACK_SIZE + 16 (args + alignment to mips_magic_trampoline) * + MonoLMF + 14 fp regs + 13 gregs + alignment * #define STACK (MIPS_MINIMAL_STACK_SIZE + 4 * sizeof (gulong) + sizeof (MonoLMF) + 14 * sizeof (double) + 13 * (sizeof (gulong))) @@ -219,13 +219,13 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Arg 4: Trampoline */ mips_move (code, mips_a3, mips_zero); - + /* Now go to the trampoline */ tramp = (guint8*)mono_get_trampoline_func (tramp_type); mips_load (code, mips_t9, (guint32)tramp); mips_jalr (code, mips_t9, mips_ra); mips_nop (code); - + /* Code address is now in v0, move it to at */ mips_move (code, mips_at, mips_v0); @@ -290,7 +290,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty * mono_arch_create_trampoline_code() knows we're putting this in t8 */ mips_load (code, mips_t8, arg1); - + /* Now jump to the generic trampoline code */ mips_load (code, mips_at, tramp); mips_jr (code, mips_at); diff --git a/src/mono/mono/mini/tramp-ppc.c b/src/mono/mono/mini/tramp-ppc.c index 67eb7c24db3ba..7d3c286a95af7 100644 --- a/src/mono/mono/mini/tramp-ppc.c +++ b/src/mono/mono/mini/tramp-ppc.c @@ -166,7 +166,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) /* This is the 'blrl' instruction */ --code; - + /* * Note that methods are called also with the bl opcode. */ @@ -176,7 +176,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) mono_arch_flush_icache ((guint8*)code, 4); return; } - + /* Sanity check */ g_assert (mono_ppc_is_direct_call_sequence (code)); @@ -203,7 +203,7 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guin *(guint8**)((guint8*)got + offset) = addr; } -/* Stack size for trampoline function +/* Stack size for trampoline function * PPC_MINIMAL_STACK_SIZE + 16 (args + alignment to ppc_magic_trampoline) * + MonoLMF + 14 fp regs + 13 gregs + alignment */ @@ -260,7 +260,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf ppc_stfd (code, i, offset, ppc_r1); offset += sizeof (double); } - /* + /* * now the integer registers. */ offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs); @@ -291,7 +291,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf ppc_mflr (code, ppc_r0); ppc_str (code, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1); - /* ok, now we can continue with the MonoLMF setup, mostly untouched + /* ok, now we can continue with the MonoLMF setup, mostly untouched * from emit_prolog in mini-ppc.c */ if (aot) { @@ -342,7 +342,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ /* Arg 1: a pointer to the registers */ ppc_addi (code, ppc_r3, ppc_r1, GREGS_OFFSET); - + /* Arg 2: code (next address to the instruction that called us) */ if (tramp_type == MONO_TRAMPOLINE_JUMP) ppc_li (code, ppc_r4, 0); @@ -366,7 +366,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } - + /* OK, code address is now on r3, move it to r14 for now. */ if (!MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type)) { #ifdef PPC_USES_FUNCTION_DESCRIPTOR @@ -510,12 +510,12 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty /* Prepare the jump to the generic trampoline code.*/ ppc_load_ptr (code, ppc_r0, tramp); ppc_mtctr (code, ppc_r0); - + /* And finally put 'arg1' in r0 and fly! */ ppc_load_ptr (code, ppc_r0, arg1); ppc_bcctr (code, 20, 0); } - + /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (buf, code - buf); MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type))); diff --git a/src/mono/mono/mini/tramp-s390x.c b/src/mono/mono/mini/tramp-s390x.c index d301a3777eacf..64497d163baae 100644 --- a/src/mono/mono/mini/tramp-s390x.c +++ b/src/mono/mono/mini/tramp-s390x.c @@ -25,7 +25,7 @@ #define LMFReg s390_r13 /* - * Method-specific trampoline code fragment sizes + * Method-specific trampoline code fragment sizes */ #define SPECIFIC_TRAMPOLINE_SIZE 96 @@ -83,17 +83,17 @@ typedef struct { /*====================== End of Global Variables ===================*/ /** - * + * * @brief Build the unbox trampoline * * @param[in] Method pointer * @param[in] Pointer to native code for method * - * Return a pointer to a trampoline which does the unboxing before + * Return a pointer to a trampoline which does the unboxing before * calling the method. * - * When value type methods are called through the - * vtable we need to unbox the 'this' argument. + * When value type methods are called through the + * vtable we need to unbox the 'this' argument. */ gpointer @@ -125,7 +125,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) /*========================= End of Function ========================*/ /** - * + * * @brief Build the SDB trampoline * * @param[in] Type of trampoline (ss or bp) @@ -141,7 +141,7 @@ guint8 * mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot) { int tramp_size = 512; - int i, framesize, ctx_offset, + int i, framesize, ctx_offset, gr_offset, fp_offset, ip_offset, sp_offset; guint8 *code, *buf; @@ -158,7 +158,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo framesize = ALIGN_TO (framesize, MONO_ARCH_FRAME_ALIGNMENT); - /** + /** * Create unwind information - On entry s390_r1 has value of method's frame reg */ s390_stmg (code, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); @@ -168,7 +168,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo mono_add_unwind_op_offset (unwind_ops, code, buf, i, gr_offset); gr_offset += sizeof(uintptr_t); } - + s390_lgr (code, s390_r0, STK_BASE); s390_aghi (code, STK_BASE, -framesize); mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, framesize + S390_CFA_OFFSET); @@ -182,20 +182,20 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo s390_stmg (code, s390_r0, s390_r14, STK_BASE, gr_offset); s390_stg (code, s390_r1, 0, STK_BASE, sp_offset); s390_stg (code, s390_r14, 0, STK_BASE, ip_offset); - + fp_offset = ctx_offset + G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs); for (i = s390_f0; i < s390_f15; ++i) { s390_std (code, i, 0, STK_BASE, fp_offset); fp_offset += sizeof(double); } - /* + /* * Call the single step/breakpoint function in sdb using * the context address as the parameter */ s390_la (code, s390_r2, 0, STK_BASE, ctx_offset); - if (single_step) + if (single_step) ep = (mono_component_debugger ())->single_step_from_context; else ep = (mono_component_debugger ())->breakpoint_from_context; @@ -205,12 +205,12 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo /* * Restore volatiles - */ + */ s390_lmg (code, s390_r0, s390_r5, STK_BASE, gr_offset); /* * Restore FP registers - */ + */ fp_offset = ctx_offset + G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs); for (i = s390_f0; i < s390_f15; ++i) { s390_ld (code, i, 0, STK_BASE, fp_offset); @@ -219,12 +219,12 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo /* * Load the IP from the context to pick up any SET_IP command results - */ + */ s390_lg (code, s390_r14, 0, STK_BASE, ip_offset); /* * Restore everything else from the on-entry values - */ + */ s390_aghi (code, STK_BASE, framesize); mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, S390_CFA_OFFSET); mono_add_unwind_op_same_value (unwind_ops, code, buf, STK_BASE); @@ -349,10 +349,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Now we'll create in 'buf' the S/390 trampoline code. This is the trampoline code common to all methods */ - + code = buf = (guint8 *) mono_global_codeman_reserve(512); - - if (tramp_type == MONO_TRAMPOLINE_JUMP) + + if (tramp_type == MONO_TRAMPOLINE_JUMP) has_caller = 0; else has_caller = 1; @@ -361,7 +361,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf STEP 0: First create a non-standard function prologue with a stack size big enough to save our registers. -----------------------------------------------------------*/ - + mono_add_unwind_op_def_cfa (unwind_ops, buf, code, STK_BASE, S390_CFA_OFFSET); s390_stmg (buf, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); offset = S390_REG_SAVE_OFFSET - S390_CFA_OFFSET; @@ -369,7 +369,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf mono_add_unwind_op_offset (unwind_ops, buf, code, i, offset); offset += sizeof(uintptr_t); } - + s390_lgr (buf, s390_r11, s390_r15); s390_aghi (buf, STK_BASE, -sizeof(trampStack_t)); mono_add_unwind_op_def_cfa_offset (unwind_ops, buf, code, sizeof(trampStack_t) + S390_CFA_OFFSET); @@ -379,13 +379,13 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* we build the MonoLMF structure on the stack - see mini-s390.h */ /* Keep in sync with the code in mono_arch_emit_prolog */ /*---------------------------------------------------------------*/ - + s390_lgr (buf, LMFReg, STK_BASE); s390_aghi (buf, LMFReg, G_STRUCT_OFFSET(trampStack_t, LMF)); - - /*---------------------------------------------------------------*/ - /* Save general and floating point registers in LMF */ - /*---------------------------------------------------------------*/ + + /*---------------------------------------------------------------*/ + /* Save general and floating point registers in LMF */ + /*---------------------------------------------------------------*/ s390_stmg (buf, s390_r0, s390_r1, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); s390_stmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); s390_mvc (buf, 10*sizeof(gulong), LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[6]), @@ -403,63 +403,63 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf 's390_magic_trampoline' and before the call to the native method. ----------------------------------------------------------*/ - + S390_SET (buf, s390_r1, mono_get_lmf_addr); s390_basr (buf, s390_r14, s390_r1); - - /*---------------------------------------------------------------*/ - /* Set lmf.lmf_addr = jit_tls->lmf */ - /*---------------------------------------------------------------*/ - s390_stg (buf, s390_r2, 0, LMFReg, - G_STRUCT_OFFSET(MonoLMF, lmf_addr)); - - /*---------------------------------------------------------------*/ - /* Get current lmf */ - /*---------------------------------------------------------------*/ - s390_lg (buf, s390_r0, 0, s390_r2, 0); - - /*---------------------------------------------------------------*/ - /* Set our lmf as the current lmf */ - /*---------------------------------------------------------------*/ - s390_stg (buf, LMFReg, 0, s390_r2, 0); - - /*---------------------------------------------------------------*/ - /* Have our lmf.previous_lmf point to the last lmf */ - /*---------------------------------------------------------------*/ - s390_stg (buf, s390_r0, 0, LMFReg, - G_STRUCT_OFFSET(MonoLMF, previous_lmf)); - - /*---------------------------------------------------------------*/ - /* save method info */ - /*---------------------------------------------------------------*/ + + /*---------------------------------------------------------------*/ + /* Set lmf.lmf_addr = jit_tls->lmf */ + /*---------------------------------------------------------------*/ + s390_stg (buf, s390_r2, 0, LMFReg, + G_STRUCT_OFFSET(MonoLMF, lmf_addr)); + + /*---------------------------------------------------------------*/ + /* Get current lmf */ + /*---------------------------------------------------------------*/ + s390_lg (buf, s390_r0, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Set our lmf as the current lmf */ + /*---------------------------------------------------------------*/ + s390_stg (buf, LMFReg, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Have our lmf.previous_lmf point to the last lmf */ + /*---------------------------------------------------------------*/ + s390_stg (buf, s390_r0, 0, LMFReg, + G_STRUCT_OFFSET(MonoLMF, previous_lmf)); + + /*---------------------------------------------------------------*/ + /* save method info */ + /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); - s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method)); - - /*---------------------------------------------------------------*/ - /* save the current SP */ - /*---------------------------------------------------------------*/ + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method)); + + /*---------------------------------------------------------------*/ + /* save the current SP */ + /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, STK_BASE, 0); - s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, ebp)); - - /*---------------------------------------------------------------*/ - /* save the current IP */ - /*---------------------------------------------------------------*/ + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, ebp)); + + /*---------------------------------------------------------------*/ + /* save the current IP */ + /*---------------------------------------------------------------*/ if (has_caller) { s390_lg (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); } else { s390_lghi (buf, s390_r1, 0); } - s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, eip)); - + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, eip)); + /*---------------------------------------------------------------*/ /* STEP 2: call the C trampoline function */ /*---------------------------------------------------------------*/ - + /* Set arguments */ /* Arg 1: host_mgreg_t *regs */ s390_la (buf, s390_r2, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); - + /* Arg 2: code (next address to the instruction that called us) */ if (has_caller) { s390_lg (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET); @@ -472,12 +472,12 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Arg 4: trampoline address. */ S390_SET (buf, s390_r5, buf); - + /* Calculate call address and call the C trampoline. Return value will be in r2 */ tramp = (guint8*)mono_get_trampoline_func (tramp_type); S390_SET (buf, s390_r1, tramp); s390_basr (buf, s390_r14, s390_r1); - + /* OK, code address is now on r2. Save it, so that we can restore r2 and use it later */ s390_stg (buf, s390_r2, 0, STK_BASE, G_STRUCT_OFFSET(trampStack_t, saveFn)); @@ -486,7 +486,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf STEP 3: Restore the LMF ----------------------------------------------------------*/ restoreLMF(buf, STK_BASE, sizeof(trampStack_t)); - + /* Check for thread interruption */ S390_SET (buf, s390_r1, (guint8 *)mono_thread_force_interruption_checkpoint_noraise); s390_basr (buf, s390_r14, s390_r1); @@ -496,11 +496,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* * Exception case: * We have an exception we want to throw in the caller's frame, so pop - * the trampoline frame and throw from the caller. + * the trampoline frame and throw from the caller. */ S390_SET (buf, s390_r1, (guint *)mono_get_rethrow_preserve_exception_addr ()); s390_aghi (buf, STK_BASE, sizeof(trampStack_t)); - s390_lg (buf, s390_r1, 0, s390_r1, 0); + s390_lg (buf, s390_r1, 0, s390_r1, 0); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (buf, s390_r1); PTRSLOT (buf, o[0]); @@ -511,10 +511,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /*---------------------------------------------------------- STEP 4: call the compiled method ----------------------------------------------------------*/ - + /* Restore parameter registers */ s390_lmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); - + /* Restore the FP registers */ offset = G_STRUCT_OFFSET(MonoLMF, fregs[0]); for (i = s390_f0; i <= s390_f15; ++i) { @@ -523,7 +523,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf } /* Restore stack pointer and jump to the code - - * R14 contains the return address to our caller + * R14 contains the return address to our caller */ s390_lgr (buf, STK_BASE, s390_r11); mono_add_unwind_op_def_cfa_offset (unwind_ops, buf, code, S390_CFA_OFFSET); @@ -542,7 +542,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (code, buf - code); MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL)); - + g_assert (info); tramp_name = mono_get_generic_trampoline_name (tramp_type); *info = mono_tramp_info_create (tramp_name, code, buf - code, ji, unwind_ops); @@ -628,9 +628,9 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty if (code_len) *code_len = buf - code; - + return code; -} +} /*========================= End of Function ========================*/ @@ -654,8 +654,8 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info guint8 **rgctx_null_jumps; gint64 displace; int tramp_size, - depth, - index, + depth, + index, iPatch = 0, i; gboolean mrgctx; @@ -757,7 +757,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info g_free (name); return(buf); -} +} /*========================= End of Function ========================*/ @@ -799,6 +799,6 @@ mono_arch_get_static_rgctx_trampoline (MonoMemoryManager *mem_manager, gpointer mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), mem_manager); return(start); -} +} /*========================= End of Function ========================*/ diff --git a/src/mono/mono/mini/tramp-sparc.c b/src/mono/mono/mini/tramp-sparc.c index 47b8010ce7d15..230198cb5b0b0 100644 --- a/src/mono/mono/mini/tramp-sparc.c +++ b/src/mono/mono/mini/tramp-sparc.c @@ -104,7 +104,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Save r1 needed by the IMT code */ sparc_sti_imm (code, sparc_g1, sparc_sp, regs_offset + (sparc_g1 * sizeof (target_mgreg_t))); - /* + /* * sparc_g5 contains the return address, the trampoline argument is stored in the * instruction stream after the call. */ @@ -114,7 +114,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Save fp regs since they are not preserved by calls */ for (i = 0; i < 16; i ++) sparc_stdf_imm (code, sparc_f0 + (i * 2), sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8)); -#endif +#endif /* We receive the method address in %r1, so save it here */ sparc_sti_imm (code, method_reg, sparc_sp, MONO_SPARC_STACK_BIAS + 200); @@ -186,7 +186,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Reload fp regs */ for (i = 0; i < 16; i ++) sparc_lddf_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8), sparc_f0 + (i * 2)); -#endif +#endif sparc_jmpl (code, sparc_o0, sparc_g0, sparc_g0); @@ -253,7 +253,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type))); return buf; -} +} gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) diff --git a/src/mono/mono/mini/tramp-x86-gsharedvt.c b/src/mono/mono/mini/tramp-x86-gsharedvt.c index 83f55eb11586c..58eb280388ae1 100644 --- a/src/mono/mono/mini/tramp-x86-gsharedvt.c +++ b/src/mono/mono/mini/tramp-x86-gsharedvt.c @@ -177,7 +177,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) x86_mov_reg_membase (code, X86_ECX, X86_EBP, info_offset, 4); /* Branch to the in/out handling code */ - x86_alu_membase_imm (code, X86_CMP, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in), 1); + x86_alu_membase_imm (code, X86_CMP, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in), 1); br_out = code; x86_branch32 (code, X86_CC_NE, 0, TRUE); diff --git a/src/mono/mono/mini/tramp-x86.c b/src/mono/mono/mini/tramp-x86.c index 582628105b1d5..b109c4f09bbf1 100644 --- a/src/mono/mono/mini/tramp-x86.c +++ b/src/mono/mono/mini/tramp-x86.c @@ -397,7 +397,7 @@ gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len) { guint8 *code, *buf, *tramp; - + tramp = mono_get_trampoline_code (tramp_type); const int size = TRAMPOLINE_SIZE; @@ -538,7 +538,7 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo code = buf = mono_global_codeman_reserve (tramp_size); // FIXME: Currently, we always go to the slow path. - + /* Load trampoline addr */ x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_RGCTX_REG, 4, 4); /* Load mrgctx/vtable */ diff --git a/src/mono/mono/mini/type-checking.c b/src/mono/mono/mini/type-checking.c index b623c603741af..1d279e86b8d22 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -169,7 +169,7 @@ mini_emit_interface_bitmap_check (MonoCompile *cfg, int intf_bit_reg, int base_r #endif } -/* +/* * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoClass * stored in "klass_reg" implements the interface "klass". */ @@ -179,7 +179,7 @@ mini_emit_load_intf_bit_reg_class (MonoCompile *cfg, int intf_bit_reg, int klass mini_emit_interface_bitmap_check (cfg, intf_bit_reg, klass_reg, m_class_offsetof_interface_bitmap (), klass); } -/* +/* * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoVTable * stored in "vtable_reg" implements the interface "klass". */ @@ -189,7 +189,7 @@ mini_emit_load_intf_bit_reg_vtable (MonoCompile *cfg, int intf_bit_reg, int vtab mini_emit_interface_bitmap_check (cfg, intf_bit_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, interface_bitmap), klass); } -/* +/* * Emit code which checks whenever the interface id of @klass is smaller than * than the value given by max_iid_reg. */ @@ -216,7 +216,7 @@ mini_emit_max_iid_check_vtable (MonoCompile *cfg, int vtable_reg, MonoClass *kla MonoBasicBlock *false_target) { int max_iid_reg = alloc_preg (cfg); - + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, max_iid_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id)); mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target); } @@ -263,7 +263,7 @@ mini_emit_iface_cast (MonoCompile *cfg, int vtable_reg, MonoClass *klass, MonoBa if (true_target) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, true_target); else - MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); } /* @@ -286,7 +286,7 @@ mini_emit_iface_class_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, M static void mini_emit_castclass (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoBasicBlock *object_is_null); - + static void mini_emit_castclass_inst (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoInst *klass_inst, MonoBasicBlock *object_is_null) { @@ -564,7 +564,7 @@ handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_us MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb); } else if (m_class_get_cast_class (klass) == m_class_get_parent (mono_defaults.enum_class)) { mini_emit_class_check_branch (cfg, eclass_reg, m_class_get_parent (mono_defaults.enum_class), OP_PBEQ, is_null_bb); - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); + mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb); } else if (m_class_get_cast_class (klass) == mono_defaults.enum_class) { mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); @@ -665,7 +665,7 @@ mono_decompose_typechecks (MonoCompile *cfg) } if ((cfg->verbose_level > 2) && found_typetest) mono_print_code (cfg, "AFTER DECOMPOSE TYPE_CHECKS"); - + } diff --git a/src/mono/mono/mini/unwind.c b/src/mono/mono/mini/unwind.c index bdcfe78604b7c..5b78f6ea25a54 100644 --- a/src/mono/mono/mini/unwind.c +++ b/src/mono/mono/mini/unwind.c @@ -97,7 +97,7 @@ static int map_hw_reg_to_dwarf_reg [ppc_lr + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, * 0-15 = GR0-15 * 16-31 = FP0-15 (f0, f2, f4, f6, f1, f3, f5, f7, f8, f10, f12, f14, f9, f11, f13, f15) */ -static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, +static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 17, 21, 18, 22, 19, 23, 24, 28, 25, 29, 26, 30, 27, 31}; @@ -449,7 +449,7 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab *p ++ = DW_CFA_advance_loc | (30); loc += 30; } - } + } switch (op->op) { case DW_CFA_def_cfa: @@ -502,7 +502,7 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab break; } } - + g_assert (p - buf < 4096); *out_len = p - buf; res = (guint8 *)g_malloc (p - buf); @@ -540,8 +540,8 @@ typedef struct { } UnwindState; /* - * Given the state of the current frame as stored in REGS, execute the unwind - * operations in unwind_info until the location counter reaches POS. The result is + * Given the state of the current frame as stored in REGS, execute the unwind + * operations in unwind_info until the location counter reaches POS. The result is * stored back into REGS. OUT_CFA will receive the value of the CFA. * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN. * On return, the nth entry will point to the address of the stack slot where register @@ -552,7 +552,7 @@ typedef struct { * It returns FALSE on failure */ gboolean -mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, +mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations, mono_unwind_reg_t *regs, int nregs, host_mgreg_t **save_locations, int save_locations_len, @@ -1037,7 +1037,7 @@ mono_unwind_decode_fde (guint8 *fde, guint32 *out_len, guint32 *code_len, MonoJi guint8 *buf; gboolean has_fde_augmentation = FALSE; - /* + /* * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html */ @@ -1105,7 +1105,7 @@ mono_unwind_decode_fde (guint8 *fde, guint32 *out_len, guint32 *code_len, MonoJi break; } } - + p = cie_aug; p += cie_aug_len; } diff --git a/src/mono/mono/profiler/CMakeLists.txt b/src/mono/mono/profiler/CMakeLists.txt index 74ebd6ba30706..b8092fe882578 100644 --- a/src/mono/mono/profiler/CMakeLists.txt +++ b/src/mono/mono/profiler/CMakeLists.txt @@ -28,7 +28,9 @@ if(NOT DISABLE_LIBS) endif() endif() - add_library(mono-profiler-aot-static STATIC aot.c helper.c) - set_target_properties(mono-profiler-aot-static PROPERTIES OUTPUT_NAME mono-profiler-aot) - install(TARGETS mono-profiler-aot-static LIBRARY) + if(NOT HOST_WASI) + add_library(mono-profiler-aot-static STATIC aot.c helper.c) + set_target_properties(mono-profiler-aot-static PROPERTIES OUTPUT_NAME mono-profiler-aot) + install(TARGETS mono-profiler-aot-static LIBRARY) + endif() endif() diff --git a/src/mono/mono/sgen/sgen-alloc.c b/src/mono/mono/sgen/sgen-alloc.c index 3e7959b85c563..6638a943341a6 100644 --- a/src/mono/mono/sgen/sgen-alloc.c +++ b/src/mono/mono/sgen/sgen-alloc.c @@ -52,7 +52,7 @@ static guint64 stat_bytes_alloced_los = 0; * This is not constantly syncrhonized, but only updated on each GC. */ static guint64 bytes_allocated_attached = 0; -/* Total bytes allocated so far in program execution by detached threads */ +/* Total bytes allocated so far in program execution by detached threads */ static guint64 bytes_allocated_detached = 0; /* @@ -532,7 +532,7 @@ sgen_clear_tlabs (void) } FOREACH_THREAD_END sgen_set_bytes_allocated_attached (total_bytes_allocated_globally); -} +} void sgen_update_allocation_count (void) { @@ -553,7 +553,7 @@ sgen_set_bytes_allocated_attached (guint64 bytes) } void -sgen_increment_bytes_allocated_detached (guint64 bytes) +sgen_increment_bytes_allocated_detached (guint64 bytes) { bytes_allocated_detached += bytes; } @@ -561,16 +561,16 @@ sgen_increment_bytes_allocated_detached (guint64 bytes) guint64 sgen_get_total_allocated_bytes (MonoBoolean precise) { - if (precise) { + if (precise) { LOCK_GC; sgen_stop_world (0, FALSE); sgen_update_allocation_count (); - + sgen_restart_world (0, FALSE); UNLOCK_GC; } - + return bytes_allocated_attached + bytes_allocated_detached; } diff --git a/src/mono/mono/sgen/sgen-cardtable.c b/src/mono/mono/sgen/sgen-cardtable.c index 31a25f47fd8fd..a79924fa8eeca 100644 --- a/src/mono/mono/sgen/sgen-cardtable.c +++ b/src/mono/mono/sgen/sgen-cardtable.c @@ -95,7 +95,7 @@ sgen_card_table_wbarrier_arrayref_copy (gpointer dest_ptr, gconstpointer src_ptr sgen_card_table_mark_address ((mword)dest); sgen_dummy_use (value); } - } + } } static void @@ -130,7 +130,7 @@ sgen_card_table_wbarrier_object_copy (GCObject* obj, GCObject *src) static void sgen_card_table_wbarrier_generic_nostore (gpointer ptr) { - sgen_card_table_mark_address ((mword)ptr); + sgen_card_table_mark_address ((mword)ptr); } static void diff --git a/src/mono/mono/sgen/sgen-conf.h b/src/mono/mono/sgen/sgen-conf.h index fc6ee088dbf5e..9962dffb34c93 100644 --- a/src/mono/mono/sgen/sgen-conf.h +++ b/src/mono/mono/sgen/sgen-conf.h @@ -175,7 +175,7 @@ typedef target_mword SgenDescriptor; * * Increasing this value speeds up allocation but will cause more frequent nursery collections as less space will be used. * Descreasing this value will cause allocation to be slower since we'll have to cycle thru more fragments. - * 512 annedoctally keeps wastage under control and doesn't impact allocation performance too much. + * 512 annedoctally keeps wastage under control and doesn't impact allocation performance too much. */ #define SGEN_MAX_NURSERY_WASTE 512 diff --git a/src/mono/mono/sgen/sgen-descriptor.c b/src/mono/mono/sgen/sgen-descriptor.c index df72b4e692ed2..195b13349bf52 100644 --- a/src/mono/mono/sgen/sgen-descriptor.c +++ b/src/mono/mono/sgen/sgen-descriptor.c @@ -213,7 +213,7 @@ mono_gc_get_bitmap_for_descr (SgenDescriptor descr, int *numbits) gsize *bitmap; switch (d & DESC_TYPE_MASK) { - case DESC_TYPE_RUN_LENGTH: { + case DESC_TYPE_RUN_LENGTH: { int first_set = (d >> 16) & 0xff; int num_set = (d >> 24) & 0xff; int i; @@ -295,7 +295,7 @@ mono_gc_make_root_descr_all_refs (int numbits) gc_bitmap = (gsize *)g_malloc0 (ALIGN_TO (ALIGN_TO (numbits, 8) + 1, sizeof (gsize))); memset (gc_bitmap, 0xff, num_bytes); - if (numbits < ((sizeof (*gc_bitmap) * 8) - ROOT_DESC_TYPE_SHIFT)) + if (numbits < ((sizeof (*gc_bitmap) * 8) - ROOT_DESC_TYPE_SHIFT)) gc_bitmap[0] = GUINT64_TO_LE(gc_bitmap[0]); else if (numbits && num_bytes % (sizeof (*gc_bitmap))) gc_bitmap[num_bytes / 8] = GUINT64_TO_LE(gc_bitmap [num_bytes / 8]); diff --git a/src/mono/mono/sgen/sgen-descriptor.h b/src/mono/mono/sgen/sgen-descriptor.h index f10ebf6a5104a..faa9abb8a1dd1 100644 --- a/src/mono/mono/sgen/sgen-descriptor.h +++ b/src/mono/mono/sgen/sgen-descriptor.h @@ -113,7 +113,7 @@ enum { enum { ROOT_DESC_CONSERVATIVE, /* 0, so matches NULL value */ ROOT_DESC_BITMAP, - ROOT_DESC_RUN_LEN, + ROOT_DESC_RUN_LEN, ROOT_DESC_COMPLEX, ROOT_DESC_VECTOR, ROOT_DESC_USER, diff --git a/src/mono/mono/sgen/sgen-fin-weak-hash.c b/src/mono/mono/sgen/sgen-fin-weak-hash.c index 055963affe70d..e1a85926950c1 100644 --- a/src/mono/mono/sgen/sgen-fin-weak-hash.c +++ b/src/mono/mono/sgen/sgen-fin-weak-hash.c @@ -34,7 +34,7 @@ typedef SgenGrayQueue GrayQueue; static int no_finalize = 0; /* - * The finalizable hash has the object as the key, the + * The finalizable hash has the object as the key, the * disappearing_link hash, has the link address as key. * * Copyright 2011 Xamarin Inc. @@ -136,7 +136,7 @@ sgen_collect_bridge_objects (int generation, ScanCopyContext ctx) copy_func (©, queue); sgen_client_bridge_register_finalized_object (copy); - + if (hash_table == &minor_finalizable_hash && !ptr_in_nursery (copy)) { /* remove from the list */ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); @@ -623,7 +623,7 @@ sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, i SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); continue; } - } SGEN_HASH_TABLE_FOREACH_END; + } SGEN_HASH_TABLE_FOREACH_END; } void diff --git a/src/mono/mono/sgen/sgen-gc.c b/src/mono/mono/sgen/sgen-gc.c index b91cef311aeb1..8ae0ded31a080 100644 --- a/src/mono/mono/sgen/sgen-gc.c +++ b/src/mono/mono/sgen/sgen-gc.c @@ -397,7 +397,7 @@ static SgenPointerQueue fin_ready_queue = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_ static SgenPointerQueue critical_fin_queue = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_FINALIZE_READY); /* registered roots: the key to the hash is the root start address */ -/* +/* * Different kinds of roots are kept separate to speed up pin_from_roots () for example. */ SgenHashTable sgen_roots_hash [ROOT_TYPE_NUM] = { @@ -408,7 +408,7 @@ SgenHashTable sgen_roots_hash [ROOT_TYPE_NUM] = { static mword roots_size = 0; /* amount of memory in the root set */ /* The size of a TLAB */ -/* The bigger the value, the less often we have to go to the slow path to allocate a new +/* The bigger the value, the less often we have to go to the slow path to allocate a new * one, but the more space is wasted by threads not allocating much memory. * FIXME: Tune this. * FIXME: Make this self-tuning for each thread. @@ -829,7 +829,7 @@ sgen_sort_addresses (void **array, size_t size) } } -/* +/* * Scan the memory between start and end and queue values which could be pointers * to the area between start_nursery and end_nursery for later consideration. * Typically used for thread stacks. @@ -1134,7 +1134,7 @@ finish_gray_stack (int generation, ScanCopyContext ctx) * We need to walk the LO list as well in search of marked big objects * (use a flag since this is needed only on major collections). We need to loop * here as well, so keep a counter of marked LO (increasing it in copy_object). - * To achieve better cache locality and cache usage, we drain the gray stack + * To achieve better cache locality and cache usage, we drain the gray stack * frequently, after each object is copied, and just finish the work here. */ sgen_drain_gray_stack (ctx); @@ -1231,7 +1231,7 @@ finish_gray_stack (int generation, ScanCopyContext ctx) sgen_client_clear_unreachable_ephemerons (ctx); /* - * We clear togglerefs only after all possible chances of revival are done. + * We clear togglerefs only after all possible chances of revival are done. * This is semantically more inline with what users expect and it allows for * user finalizers to correctly interact with TR objects. */ @@ -2606,7 +2606,7 @@ sgen_ensure_free_space (size_t size, int generation) generation_to_collect = GENERATION_OLD; } else { generation_to_collect = GENERATION_NURSERY; - reason = "Nursery full"; + reason = "Nursery full"; } } @@ -2643,7 +2643,7 @@ sgen_perform_collection_inner (size_t requested_size, int generation_to_collect, sgen_stop_world (generation_to_collect, forced_serial || !sgen_major_collector.is_concurrent); else SGEN_ASSERT (0, sgen_is_world_stopped (), "We can only collect if the world is stopped"); - + TV_GETTIME (gc_total_start); diff --git a/src/mono/mono/sgen/sgen-gc.h b/src/mono/mono/sgen/sgen-gc.h index b5b91c9a2eec7..ef7569f4fe980 100644 --- a/src/mono/mono/sgen/sgen-gc.h +++ b/src/mono/mono/sgen/sgen-gc.h @@ -293,7 +293,7 @@ sgen_get_nursery_end (void) #define SGEN_LOAD_VTABLE(obj) ((GCVTable)(SGEN_POINTER_UNTAG_ALL (SGEN_LOAD_VTABLE_UNCHECKED ((GCObject *)(obj))))) /* -List of what each bit on of the vtable gc bits means. +List of what each bit on of the vtable gc bits means. */ enum { // When the Java bridge has determined an object is "bridged", it uses these two bits to cache that information. @@ -1038,7 +1038,7 @@ sgen_major_is_object_alive (GCObject *object) /* - * If the object has been forwarded it means it's still referenced from a root. + * If the object has been forwarded it means it's still referenced from a root. * If it is pinned it's still alive as well. * A LOS object is only alive if we have pinned it. * Return TRUE if @obj is ready to be finalized. @@ -1190,7 +1190,7 @@ gint64 sgen_timestamp (void); * - CANARY_SIZE must be multiple of word size in bytes * - Canary space is not included on checks against SGEN_MAX_SMALL_OBJ_SIZE */ - + gboolean sgen_nursery_canaries_enabled (void); #define CANARY_SIZE 8 diff --git a/src/mono/mono/sgen/sgen-gray.h b/src/mono/mono/sgen/sgen-gray.h index 7da84ba07359a..19e9b90f3bf4b 100644 --- a/src/mono/mono/sgen/sgen-gray.h +++ b/src/mono/mono/sgen/sgen-gray.h @@ -16,24 +16,24 @@ * This gray queue has to be as optimized as possible, because it is in the core of * the mark/copy phase of the garbage collector. The memory access has then to be as * cache friendly as possible. That's why we use a cursor based implementation. - * + * * This simply consist in maintaining a pointer to the current element in the * queue. In addition to using this cursor, we use a simple linked list of arrays, * called sections, so that we have the cache friendliness of arrays without having * the cost of memory reallocation of a dynaic array, not the cost of memory * indirection of a linked list. - * + * * This implementation also allows the dequeuing of a whole section at a time. This is - * for example used in the parallel GC because it would be too costly to take one element + * for example used in the parallel GC because it would be too costly to take one element * at a time. This imply the main constraint that, because we don't carry the cursor - * with the section, we still have to store the index of the last element. This is done + * with the section, we still have to store the index of the last element. This is done * through the 'size' field on the section, which default value is it's maximum value * SGEN_GRAY_QUEUE_SECTION_SIZE. This field is updated in multiple cases : * - section allocation : default value * - object push : default value if we fill the current queue first * - section dequeue : position of the cursor in the dequeued section * - section enqueue : position of the cursor in the previously first section in the queue - * + * * The previous implementation was an index based access where we would store the index * of the last element in the section. This was less efficient because we would have * to make 1 memory access for the index value, 1 for the base address of the objects diff --git a/src/mono/mono/sgen/sgen-hash-table.c b/src/mono/mono/sgen/sgen-hash-table.c index e9c921588a4d5..01a45ed3d8154 100644 --- a/src/mono/mono/sgen/sgen-hash-table.c +++ b/src/mono/mono/sgen/sgen-hash-table.c @@ -8,10 +8,10 @@ * 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 diff --git a/src/mono/mono/sgen/sgen-marksweep-drain-gray-stack.h b/src/mono/mono/sgen/sgen-marksweep-drain-gray-stack.h index 889fa6077f141..6bf3dc0a9ae3c 100644 --- a/src/mono/mono/sgen/sgen-marksweep-drain-gray-stack.h +++ b/src/mono/mono/sgen/sgen-marksweep-drain-gray-stack.h @@ -285,7 +285,7 @@ SCAN_OBJECT_FUNCTION_NAME (GCObject *full_object, SgenDescriptor desc, SgenGrayQ #include "sgen-scan-object.h" } -#ifdef SCAN_VTYPE_FUNCTION_NAME +#ifdef SCAN_VTYPE_FUNCTION_NAME static void SCAN_VTYPE_FUNCTION_NAME (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue *queue BINARY_PROTOCOL_ARG (size_t size)) { diff --git a/src/mono/mono/sgen/sgen-marksweep.c b/src/mono/mono/sgen/sgen-marksweep.c index f767431c1699e..24eaf1fd9ad9b 100644 --- a/src/mono/mono/sgen/sgen-marksweep.c +++ b/src/mono/mono/sgen/sgen-marksweep.c @@ -712,7 +712,7 @@ alloc_obj (GCVTable vtable, size_t size, gboolean pinned, gboolean has_reference /* FIXME: assumes object layout */ *(GCVTable*)obj = vtable; - sgen_total_allocated_major += block_obj_sizes [size_index]; + sgen_total_allocated_major += block_obj_sizes [size_index]; return (GCObject *)obj; } @@ -767,7 +767,7 @@ major_alloc_object_par (GCVTable vtable, size_t size, gboolean has_references) *(GCVTable*)obj = vtable; /* FIXME is it worth CAS-ing here */ - sgen_total_allocated_major += block_obj_sizes [size_index]; + sgen_total_allocated_major += block_obj_sizes [size_index]; return (GCObject *)obj; } diff --git a/src/mono/mono/sgen/sgen-memory-governor.c b/src/mono/mono/sgen/sgen-memory-governor.c index ac801a24a92f0..a2eb08ae7f288 100644 --- a/src/mono/mono/sgen/sgen-memory-governor.c +++ b/src/mono/mono/sgen/sgen-memory-governor.c @@ -165,7 +165,7 @@ sgen_need_major_collection (mword space_needed, gboolean *forced) heap_size = get_heap_size (); if (heap_size <= major_collection_trigger_size) - return FALSE; + return FALSE; /* * The more the heap grows, the more we need to decrease the allowance above, diff --git a/src/mono/mono/sgen/sgen-minor-copy-object.h b/src/mono/mono/sgen/sgen-minor-copy-object.h index 5597ab41bb06c..7e498482f50b8 100644 --- a/src/mono/mono/sgen/sgen-minor-copy-object.h +++ b/src/mono/mono/sgen/sgen-minor-copy-object.h @@ -74,7 +74,7 @@ extern guint64 stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */ */ static MONO_ALWAYS_INLINE void -SERIAL_COPY_OBJECT (GCObject **obj_slot, SgenGrayQueue *queue) +SERIAL_COPY_OBJECT (GCObject **obj_slot, SgenGrayQueue *queue) { GCObject *forwarded; GCObject *copy; @@ -115,7 +115,7 @@ SERIAL_COPY_OBJECT (GCObject **obj_slot, SgenGrayQueue *queue) if (sgen_nursery_is_to_space (obj)) { SGEN_ASSERT (9, sgen_vtable_get_descriptor (SGEN_LOAD_VTABLE(obj)), "to space object %p has no gc descriptor", obj); SGEN_LOG (9, " (tospace, no change)"); - HEAVY_STAT (++stat_nursery_copy_object_failed_to_space); + HEAVY_STAT (++stat_nursery_copy_object_failed_to_space); return; } #endif @@ -188,7 +188,7 @@ SERIAL_COPY_OBJECT_FROM_OBJ (GCObject **obj_slot, SgenGrayQueue *queue) /* FIXME: all of these could just use `sgen_obj_get_descriptor_safe()` */ SGEN_ASSERT (9, sgen_vtable_get_descriptor (SGEN_LOAD_VTABLE(obj)), "to space object %p has no gc descriptor", obj); SGEN_LOG (9, " (tospace, no change)"); - HEAVY_STAT (++stat_nursery_copy_object_failed_to_space); + HEAVY_STAT (++stat_nursery_copy_object_failed_to_space); /* * FIXME: diff --git a/src/mono/mono/sgen/sgen-nursery-allocator.c b/src/mono/mono/sgen/sgen-nursery-allocator.c index c4ac6b2c67381..731dfcccbd1d4 100644 --- a/src/mono/mono/sgen/sgen-nursery-allocator.c +++ b/src/mono/mono/sgen/sgen-nursery-allocator.c @@ -4,7 +4,7 @@ * * Copyright 2009-2010 Novell, Inc. * 2011 Rodrigo Kumpera - * + * * Copyright 2011 Xamarin Inc (http://www.xamarin.com) * Copyright (C) 2012 Xamarin Inc * @@ -23,7 +23,7 @@ * We should start assigning threads very small fragments: if there are many * threads the nursery will be full of reserved space that the threads may not * use at all, slowing down allocation speed. - * Thread local allocation is done from areas of memory Hotspot calls Thread Local + * Thread local allocation is done from areas of memory Hotspot calls Thread Local * Allocation Buffers (TLABs). */ #include "config.h" @@ -360,7 +360,7 @@ par_alloc_from_fragment (SgenFragmentAllocator *allocator, SgenFragment *frag, s if (frag->fragment_end - end < SGEN_MAX_NURSERY_WASTE) { SgenFragment *next, **prev_ptr; - + /* * Before we clean the remaining nursery, we must claim the remaining space * as it could end up been used by the range allocator since it can end up @@ -422,7 +422,7 @@ serial_alloc_from_fragment (SgenFragment **previous, SgenFragment *frag, size_t if (frag->fragment_end - end < SGEN_MAX_NURSERY_WASTE) { *previous = frag->next; - + /* Clear the remaining space, pinning depends on this. FIXME move this to use phony arrays */ memset (end, 0, frag->fragment_end - end); @@ -598,7 +598,7 @@ sgen_clear_allocator_fragments (SgenFragmentAllocator *allocator) #ifdef NALLOC_DEBUG add_alloc_record (frag->fragment_next, frag->fragment_end - frag->fragment_next, CLEAR_NURSERY_FRAGS); #endif - } + } } /* Clear all remaining nursery fragments */ diff --git a/src/mono/mono/sgen/sgen-pinning-stats.c b/src/mono/mono/sgen/sgen-pinning-stats.c index c8f0e0e22c29d..34fea4f836e22 100644 --- a/src/mono/mono/sgen/sgen-pinning-stats.c +++ b/src/mono/mono/sgen/sgen-pinning-stats.c @@ -3,7 +3,7 @@ * Copyright 2001-2003 Ximian, Inc * Copyright 2003-2010 Novell, Inc. * Copyright 2011 Xamarin Inc (http://www.xamarin.com) - * + * * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ diff --git a/src/mono/mono/sgen/sgen-pinning.c b/src/mono/mono/sgen/sgen-pinning.c index 6776c576372e1..9c53416e82498 100644 --- a/src/mono/mono/sgen/sgen-pinning.c +++ b/src/mono/mono/sgen/sgen-pinning.c @@ -89,7 +89,7 @@ sgen_scan_pin_queue_objects (ScanCopyContext ctx) void sgen_pin_stage_ptr (void *ptr) { - /*very simple multiplicative hash function, tons better than simple and'ng */ + /*very simple multiplicative hash function, tons better than simple and'ng */ int hash_idx = ((mword)ptr * 1737350767) & (PIN_HASH_SIZE - 1); if (pin_hash_filter [hash_idx] == ptr) return; diff --git a/src/mono/mono/sgen/sgen-simple-nursery.c b/src/mono/mono/sgen/sgen-simple-nursery.c index 1db3b081f1952..18a771d0abafc 100644 --- a/src/mono/mono/sgen/sgen-simple-nursery.c +++ b/src/mono/mono/sgen/sgen-simple-nursery.c @@ -66,7 +66,7 @@ prepare_to_space (char *to_space_bitmap, size_t space_bitmap_size) static void clear_fragments (void) -{ +{ } static void @@ -154,7 +154,7 @@ sgen_simple_nursery_init (SgenMinorCollector *collector, gboolean parallel) #ifdef DISABLE_SGEN_MAJOR_MARKSWEEP_CONC g_assert (parallel == FALSE); #endif - + collector->is_split = FALSE; collector->is_parallel = parallel; diff --git a/src/mono/mono/sgen/sgen-split-nursery.c b/src/mono/mono/sgen/sgen-split-nursery.c index 4afd1ff8d246c..5c73a1ced752e 100644 --- a/src/mono/mono/sgen/sgen-split-nursery.c +++ b/src/mono/mono/sgen/sgen-split-nursery.c @@ -46,7 +46,7 @@ The Allocator Space takes the botton part of the nursery. The Survivor spaces are intermingled in the top part of the nursery. It's done this way since the required size for the To Space depends on the survivor rate -of objects from the Allocator Space. +of objects from the Allocator Space. During a collection when the object scan function see a nursery object it must determine if the object needs to be evacuated or left in place. Originally, this diff --git a/src/mono/mono/tests/bug-gh-9507.cs b/src/mono/mono/tests/bug-gh-9507.cs index 9a6b60e85693f..6291e1ca2e9af 100644 --- a/src/mono/mono/tests/bug-gh-9507.cs +++ b/src/mono/mono/tests/bug-gh-9507.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using type_with_special_array_cast = System.UInt64; // MonoClass::cast_class = long using other_type = System.Double; @@ -9,7 +10,7 @@ public TestIsInst() { array = new T[16]; if (array is other_type[]) // should not crash or throw NullReferenceException - throw new System.Exception("Unreachable"); + throw new System.UnreachableException(); } } diff --git a/src/mono/mono/tests/metadata-verifier/gen-md-tests.c b/src/mono/mono/tests/metadata-verifier/gen-md-tests.c index 869ac8b60ea8f..0f1efd15849b5 100644 --- a/src/mono/mono/tests/metadata-verifier/gen-md-tests.c +++ b/src/mono/mono/tests/metadata-verifier/gen-md-tests.c @@ -29,7 +29,7 @@ tokens: comment ::= '#.* - identifier ::= ([a-z] | [A-Z]) ([a-z] | [A-Z] | [0-9] | [_-.])* + identifier ::= ([a-z] | [A-Z]) ([a-z] | [A-Z] | [0-9] | [_-.])* hexa_digit = [0-9] | [a-f] | [A-F] number ::= hexadecimal | decimal hexadecimal ::= (+-)?('0' [xX])? hexa_digit+ @@ -44,7 +44,7 @@ identifier '{' assembly_directive test_entry* '}' assembly_directive: - 'assembly' identifier + 'assembly' identifier test_entry: validity patch (',' patch)* @@ -277,7 +277,7 @@ init_test_set (test_set_t *test_set) printf ("Could not parse image %s\n", test_set->assembly); exit (INVALID_BAD_FILE); } - + test_set->init = 1; } @@ -293,7 +293,7 @@ make_test_name (test_entry_t *entry, test_set_t *test_set) #define READ_BIT(PTR,OFF) ((((guint8*)(PTR))[(OFF / 8)] & (1 << ((OFF) % 8))) != 0) #define SET_BIT(PTR,OFF) do { ((guint8*)(PTR))[(OFF / 8)] |= (1 << ((OFF) % 8)); } while (0) -static guint32 +static guint32 get_pe_header (test_entry_t *entry) { return READ_VAR (guint32, entry->data + 0x3c) + 4; @@ -363,7 +363,7 @@ get_metadata_stream_header (test_entry_t *entry, guint32 idx) } offset = pad4 (offset); } - return offset; + return offset; } static guint32 @@ -374,14 +374,14 @@ lookup_var (test_entry_t *entry, const char *name) if (!strcmp ("pe-signature", name)) return get_pe_header (entry) - 4; if (!strcmp ("pe-header", name)) - return get_pe_header (entry); + return get_pe_header (entry); if (!strcmp ("pe-optional-header", name)) - return get_pe_header (entry) + 20; + return get_pe_header (entry) + 20; if (!strcmp ("section-table", name)) - return get_pe_header (entry) + 244; + return get_pe_header (entry) + 244; if (!strcmp ("cli-header", name)) return get_cli_header (entry); - if (!strcmp ("cli-metadata", name)) + if (!strcmp ("cli-metadata", name)) return get_cli_metadata_root (entry); if (!strcmp ("tables-header", name)) { guint32 metadata_root = get_cli_metadata_root (entry); @@ -597,7 +597,7 @@ process_test_entry (test_set_t *test_set, test_entry_t *entry) fclose (f); g_free (file_name); -} +} /*******************************************************************************************************/ @@ -685,7 +685,7 @@ static char* token_text_dup (scanner_t *scanner, token_t *token) { int len = token->end - token->start; - + char *str = g_memdup (scanner->input + token->start, len + 1); str [len] = 0; return str; @@ -696,7 +696,7 @@ static void dump_token (scanner_t *scanner, token_t *token) { char *str = token_text_dup (scanner, token); - + printf ("token '%s' of type '%s' at line %d\n", str, token_type_name (token->type), token->line); free (str); } @@ -965,13 +965,13 @@ parse_effect (scanner_t *scanner) CONSUME_IDENTIFIER(name); if (!strcmp ("set-byte", name)) - type = EFFECT_SET_BYTE; + type = EFFECT_SET_BYTE; else if (!strcmp ("set-ushort", name)) - type = EFFECT_SET_USHORT; + type = EFFECT_SET_USHORT; else if (!strcmp ("set-uint", name)) - type = EFFECT_SET_UINT; + type = EFFECT_SET_UINT; else if (!strcmp ("set-bit", name)) - type = EFFECT_SET_BIT; + type = EFFECT_SET_BIT; else if (!strcmp ("truncate", name)) type = EFFECT_SET_TRUNC; else if (!strcmp ("or-byte", name)) @@ -980,7 +980,7 @@ parse_effect (scanner_t *scanner) type = EFFECT_OR_USHORT; else if (!strcmp ("or-uint", name)) type = EFFECT_OR_UINT; - else + else FAIL(g_strdup_printf ("Invalid effect kind, expected one of: (set-byte set-ushort set-uint set-bit or-byte or-ushort or-uint truncate) but got %s",name), INVALID_ID_TEXT); effect = g_new0 (patch_effect_t, 1); @@ -1027,7 +1027,7 @@ static void parse_test_entry (scanner_t *scanner, test_set_t *test_set) { test_entry_t entry = { 0 }; - + entry.validity = parse_validity (scanner); do { @@ -1073,7 +1073,7 @@ parse_program (scanner_t *scanner) static void digest_file (const char *file) { - scanner_t *scanner = scanner_new (file); + scanner_t *scanner = scanner_new (file); parse_program (scanner); scanner_free (scanner); } diff --git a/src/mono/mono/utils/atomic.c b/src/mono/mono/utils/atomic.c index eac6be32557ec..215fe6ccce73f 100644 --- a/src/mono/mono/utils/atomic.c +++ b/src/mono/mono/utils/atomic.c @@ -34,20 +34,20 @@ gint32 mono_atomic_cas_i32(volatile gint32 *dest, gint32 exch, { gint32 old; int ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); ret = pthread_mutex_lock(&spin); g_assert (ret == 0); - + old= *dest; if(old==comp) { *dest=exch; } - + ret = pthread_mutex_unlock(&spin); g_assert (ret == 0); - + pthread_cleanup_pop (0); return(old); @@ -58,20 +58,20 @@ gpointer mono_atomic_cas_ptr(volatile gpointer *dest, { gpointer old; int ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); ret = pthread_mutex_lock(&spin); g_assert (ret == 0); - + old= *dest; if(old==comp) { *dest=exch; } - + ret = pthread_mutex_unlock(&spin); g_assert (ret == 0); - + pthread_cleanup_pop (0); return(old); @@ -123,7 +123,7 @@ gint32 mono_atomic_inc_i32(volatile gint32 *dest) { gint32 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -131,12 +131,12 @@ gint32 mono_atomic_inc_i32(volatile gint32 *dest) (*dest)++; ret= *dest; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); - + return(ret); } @@ -165,20 +165,20 @@ gint32 mono_atomic_dec_i32(volatile gint32 *dest) { gint32 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); - + (*dest)--; ret= *dest; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); - + return(ret); } @@ -207,7 +207,7 @@ gint32 mono_atomic_xchg_i32(volatile gint32 *dest, gint32 exch) { gint32 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -215,12 +215,12 @@ gint32 mono_atomic_xchg_i32(volatile gint32 *dest, gint32 exch) ret=*dest; *dest=exch; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); - + return(ret); } @@ -249,20 +249,20 @@ gpointer mono_atomic_xchg_ptr(volatile gpointer *dest, gpointer exch) { gpointer ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); - + ret=*dest; *dest=exch; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); - + return(ret); } @@ -270,7 +270,7 @@ gint32 mono_atomic_fetch_add_i32(volatile gint32 *dest, gint32 add) { gint32 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -278,7 +278,7 @@ gint32 mono_atomic_fetch_add_i32(volatile gint32 *dest, gint32 add) ret= *dest; *dest+=add; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -291,7 +291,7 @@ gint64 mono_atomic_fetch_add_i64(volatile gint64 *dest, gint64 add) { gint64 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -299,7 +299,7 @@ gint64 mono_atomic_fetch_add_i64(volatile gint64 *dest, gint64 add) ret= *dest; *dest+=add; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -312,14 +312,14 @@ gint8 mono_atomic_load_i8(volatile gint8 *src) { gint8 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); ret= *src; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -332,14 +332,14 @@ gint16 mono_atomic_load_i16(volatile gint16 *src) { gint16 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); ret= *src; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -352,14 +352,14 @@ gint32 mono_atomic_load_i32(volatile gint32 *src) { gint32 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); ret= *src; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -372,14 +372,14 @@ gint64 mono_atomic_load_i64(volatile gint64 *src) { gint64 ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); ret= *src; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -392,14 +392,14 @@ gpointer mono_atomic_load_ptr(volatile gpointer *src) { gpointer ret; int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); ret= *src; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); @@ -411,85 +411,85 @@ gpointer mono_atomic_load_ptr(volatile gpointer *src) void mono_atomic_store_i8(volatile gint8 *dst, gint8 val) { int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); *dst=val; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); } void mono_atomic_store_i16(volatile gint16 *dst, gint16 val) { int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); *dst=val; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); } void mono_atomic_store_i32(volatile gint32 *dst, gint32 val) { int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); *dst=val; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); } void mono_atomic_store_i64(volatile gint64 *dst, gint64 val) { int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); *dst=val; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); } void mono_atomic_store_ptr(volatile gpointer *dst, gpointer val) { int thr_ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); g_assert (thr_ret == 0); *dst=val; - + thr_ret = pthread_mutex_unlock(&spin); g_assert (thr_ret == 0); - + pthread_cleanup_pop (0); } @@ -578,20 +578,20 @@ mono_atomic_cas_i64(volatile gint64 *dest, gint64 exch, gint64 comp) { gint64 old; int ret; - + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); ret = pthread_mutex_lock(&spin); g_assert (ret == 0); - + old= *dest; if(old==comp) { *dest=exch; } - + ret = pthread_mutex_unlock(&spin); g_assert (ret == 0); - + pthread_cleanup_pop (0); return(old); diff --git a/src/mono/mono/utils/dlmalloc.c b/src/mono/mono/utils/dlmalloc.c index ed68e4103be5c..48ed19153e748 100644 --- a/src/mono/mono/utils/dlmalloc.c +++ b/src/mono/mono/utils/dlmalloc.c @@ -382,9 +382,9 @@ MALLINFO_FIELD_TYPE default: size_t size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does realloc(p, 0). LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H @@ -3485,7 +3485,7 @@ static void* sys_alloc(mstate m, size_t nb) { m->seg.sflags = mmap_flag; m->magic = mparams.magic; init_bins(m); - if (is_global(m)) + if (is_global(m)) init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); else { /* Offset top by embedded malloc_state */ @@ -3636,7 +3636,7 @@ static int sys_trim(mstate m, size_t pad) { } /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) + if (HAVE_MMAP) released += release_unused_segments(m); /* On failure, disable autotrim to avoid repeated failed future calls */ @@ -3848,7 +3848,7 @@ static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { while (a < alignment) a <<= 1; alignment = a; } - + if (bytes >= MAX_REQUEST - alignment) { if (m != 0) { /* Test isn't needed but avoids compiler warning */ MALLOC_FAILURE_ACTION; @@ -5103,5 +5103,5 @@ int mspace_mallopt(int param_number, int value) { Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) * Based loosely on libg++-1.2X malloc. (It retains some of the overall structure of old version, but most details differ.) - + */ diff --git a/src/mono/mono/utils/dlmalloc.h b/src/mono/mono/utils/dlmalloc.h index 327cc4c0c14d0..e382b994af1e7 100644 --- a/src/mono/mono/utils/dlmalloc.h +++ b/src/mono/mono/utils/dlmalloc.h @@ -1,14 +1,14 @@ /* Default header file for malloc-2.8.x, written by Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. - + http://creativecommons.org/licenses/publicdomain. + last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee) This header is for ANSI C/C++ only. You can set any of the following #defines before including: - * If USE_DL_PREFIX is defined, it is assumed that malloc.c + * If USE_DL_PREFIX is defined, it is assumed that malloc.c was also compiled with this option, so all routines have names starting with "dl". diff --git a/src/mono/mono/utils/dtrace.h b/src/mono/mono/utils/dtrace.h index 883d1affa6188..c1f1e01121173 100644 --- a/src/mono/mono/utils/dtrace.h +++ b/src/mono/mono/utils/dtrace.h @@ -1,10 +1,10 @@ /* * * \file * DTrace probes - * + * * Authors: * Andreas Faerber - * + * */ #ifndef __UTILS_DTRACE_H__ diff --git a/src/mono/mono/utils/freebsd-elf_common.h b/src/mono/mono/utils/freebsd-elf_common.h index 658119fdbc51f..b3520edda1f98 100644 --- a/src/mono/mono/utils/freebsd-elf_common.h +++ b/src/mono/mono/utils/freebsd-elf_common.h @@ -196,12 +196,12 @@ typedef struct { #define SHT_STRTAB 3 /* string table section */ #define SHT_RELA 4 /* relocation section with addends */ #define SHT_HASH 5 /* symbol hash table section */ -#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_DYNAMIC 6 /* dynamic section */ #define SHT_NOTE 7 /* note section */ #define SHT_NOBITS 8 /* no space section */ #define SHT_REL 9 /* relocation section - no addends */ #define SHT_SHLIB 10 /* reserved - purpose unknown */ -#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ #define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ #define SHT_FINI_ARRAY 15 /* Termination function pointers. */ #define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ diff --git a/src/mono/mono/utils/gc_wrapper.h b/src/mono/mono/utils/gc_wrapper.h index 00ab7fb6c5501..3881d88ef7141 100644 --- a/src/mono/mono/utils/gc_wrapper.h +++ b/src/mono/mono/utils/gc_wrapper.h @@ -28,10 +28,10 @@ */ #ifndef HOST_WIN32 // FIXME? # if defined(MONO_KEYWORD_THREAD) && !defined(__powerpc__) - + /* The local alloc stuff is in pthread_support.c, but solaris uses solaris_threads.c */ /* It is also disabled on solaris/x86 by libgc/configure.ac */ - /* + /* * ARM has no definition for some atomic functions in gc_locks.h and * support is also disabled in libgc/configure.ac. */ diff --git a/src/mono/mono/utils/lock-free-alloc.h b/src/mono/mono/utils/lock-free-alloc.h index c05610fabc154..cca1d83eb6614 100644 --- a/src/mono/mono/utils/lock-free-alloc.h +++ b/src/mono/mono/utils/lock-free-alloc.h @@ -11,10 +11,10 @@ * 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 diff --git a/src/mono/mono/utils/lock-free-queue.c b/src/mono/mono/utils/lock-free-queue.c index b1e1725cbe26b..02ce5b1745a77 100644 --- a/src/mono/mono/utils/lock-free-queue.c +++ b/src/mono/mono/utils/lock-free-queue.c @@ -11,10 +11,10 @@ * 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 diff --git a/src/mono/mono/utils/lock-free-queue.h b/src/mono/mono/utils/lock-free-queue.h index abb16d287b896..76a8e98decc2d 100644 --- a/src/mono/mono/utils/lock-free-queue.h +++ b/src/mono/mono/utils/lock-free-queue.h @@ -12,10 +12,10 @@ * 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 diff --git a/src/mono/mono/utils/mach-support-arm.c b/src/mono/mono/utils/mach-support-arm.c index 004b03cfd7c93..f877fa7050020 100644 --- a/src/mono/mono/utils/mach-support-arm.c +++ b/src/mono/mono/utils/mach-support-arm.c @@ -80,7 +80,7 @@ mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, ma { #if defined(HOST_WATCHOS) g_error ("thread_get_state() is not supported by this platform"); -#else +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; kern_return_t ret; diff --git a/src/mono/mono/utils/mach-support-x86.c b/src/mono/mono/utils/mach-support-x86.c index e28ee66f9e0fe..6dd775d2c0860 100644 --- a/src/mono/mono/utils/mach-support-x86.c +++ b/src/mono/mono/utils/mach-support-x86.c @@ -116,7 +116,7 @@ mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, ma return ret; ret = thread_set_state (thread, x86_FLOAT_STATE32, fpstate, fpcount); return ret; -#endif +#endif } #endif diff --git a/src/mono/mono/utils/memcheck.h b/src/mono/mono/utils/memcheck.h index 2740578f1dc53..960bed5f7abcb 100644 --- a/src/mono/mono/utils/memcheck.h +++ b/src/mono/mono/utils/memcheck.h @@ -22,16 +22,16 @@ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS @@ -53,7 +53,7 @@ the terms of the GNU General Public License, version 2. See the COPYING file in the source distribution for details. - ---------------------------------------------------------------- + ---------------------------------------------------------------- */ @@ -71,12 +71,12 @@ #include "valgrind.h" -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! This enum comprises an ABI exported by Valgrind to programs which use client requests. DO NOT CHANGE THE ORDER OF THESE ENTRIES, NOR DELETE ANY -- add new ones at the end. */ typedef - enum { + enum { VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'), VG_USERREQ__MAKE_MEM_UNDEFINED, VG_USERREQ__MAKE_MEM_DEFINED, @@ -100,7 +100,7 @@ typedef VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE, /* This is just for memcheck's internal use - don't use it */ - _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR + _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR = VG_USERREQ_TOOL_BASE('M','C') + 256 } Vg_MemCheckClientRequest; @@ -113,7 +113,7 @@ typedef VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ VG_USERREQ__MAKE_MEM_NOACCESS, \ (_qzz_addr), (_qzz_len), 0, 0, 0) - + /* Similarly, mark memory at _qzz_addr as addressable but undefined for _qzz_len bytes. */ #define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \ diff --git a/src/mono/mono/utils/memfuncs.c b/src/mono/mono/utils/memfuncs.c index 5ffb16b25912e..4fc78079626ab 100644 --- a/src/mono/mono/utils/memfuncs.c +++ b/src/mono/mono/utils/memfuncs.c @@ -44,7 +44,7 @@ #if defined(TARGET_WIN32) #include -#endif +#endif #include "memfuncs.h" diff --git a/src/mono/mono/utils/mono-codeman.c b/src/mono/mono/utils/mono-codeman.c index c7ff9326ed710..3d1fa4ac82325 100644 --- a/src/mono/mono/utils/mono-codeman.c +++ b/src/mono/mono/utils/mono-codeman.c @@ -36,9 +36,9 @@ static size_t dynamic_code_frees_count; static const MonoCodeManagerCallbacks *code_manager_callbacks; /* - * AMD64 processors maintain icache coherency only for pages which are + * AMD64 processors maintain icache coherency only for pages which are * marked executable. Also, windows DEP requires us to obtain executable memory from - * malloc when using dynamic code managers. The system malloc can't do this so we use a + * malloc when using dynamic code managers. The system malloc can't do this so we use a * slighly modified version of Doug Lea's Malloc package for this purpose: * http://g.oswego.edu/dl/html/malloc.html * @@ -51,7 +51,7 @@ static const MonoCodeManagerCallbacks *code_manager_callbacks; #define MIN_ALIGN MEMORY_ALLOCATION_ALIGNMENT #elif defined(__x86_64__) /* - * We require 16 byte alignment on amd64 so the fp literals embedded in the code are + * We require 16 byte alignment on amd64 so the fp literals embedded in the code are * properly aligned for SSE2. */ #define MIN_ALIGN 16 @@ -157,7 +157,7 @@ codechunk_vfree (void *ptr, guint32 size) mono_vfree (ptr, size, MONO_MEM_ACCOUNT_CODE); } mono_os_mutex_unlock (&valloc_mutex); -} +} static void codechunk_cleanup (void) @@ -303,7 +303,7 @@ mono_code_manager_new_internal (int codeman_type) * * Returns: the new code manager */ -MonoCodeManager* +MonoCodeManager* mono_code_manager_new (void) { return mono_code_manager_new_internal (MONO_CODEMAN_TYPE_JIT); @@ -318,7 +318,7 @@ mono_code_manager_new (void) * * Returns: the new code manager */ -MonoCodeManager* +MonoCodeManager* mono_code_manager_new_dynamic (void) { return mono_code_manager_new_internal (MONO_CODEMAN_TYPE_DYNAMIC); @@ -373,12 +373,12 @@ static void free_chunklist (MonoCodeManager *cman, CodeChunk *chunk) { CodeChunk *dead; - + #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined (VALGRIND_JIT_UNREGISTER_MAP) int valgrind_unregister = 0; if (RUNNING_ON_VALGRIND) valgrind_unregister = 1; -#define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0) +#define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0) #else #define valgrind_unregister(x) #endif @@ -631,8 +631,8 @@ mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) return ptr; } } - /* - * no room found, move one filled chunk to cman->full + /* + * no room found, move one filled chunk to cman->full * to keep cman->current from growing too much */ prev = NULL; diff --git a/src/mono/mono/utils/mono-conc-hashtable.c b/src/mono/mono/utils/mono-conc-hashtable.c index c7050a2a5a327..0b4bd7bb0a0c8 100644 --- a/src/mono/mono/utils/mono-conc-hashtable.c +++ b/src/mono/mono/utils/mono-conc-hashtable.c @@ -356,7 +356,7 @@ mono_conc_hashtable_insert (MonoConcurrentHashTable *hash_table, gpointer key, g if (kvs [i].key == TOMBSTONE) --hash_table->tombstone_count; else - ++hash_table->element_count; + ++hash_table->element_count; kvs [i].key = key; return NULL; } diff --git a/src/mono/mono/utils/mono-context.h b/src/mono/mono/utils/mono-context.h index bd1a3cd0104c2..57d98ee52b430 100644 --- a/src/mono/mono/utils/mono-context.h +++ b/src/mono/mono/utils/mono-context.h @@ -596,7 +596,7 @@ typedef struct { #ifdef __mono_ppc64__ typedef struct { - gulong sc_ir; // pc + gulong sc_ir; // pc gulong sc_sp; // r1 host_mgreg_t regs [32]; double fregs [32]; @@ -787,9 +787,9 @@ typedef struct MonoContext { gpointer *fp; } MonoContext; -#define MONO_CONTEXT_SET_IP(ctx,eip) do { (ctx)->ip = (gpointer)(eip); } while (0); -#define MONO_CONTEXT_SET_BP(ctx,ebp) do { (ctx)->fp = (gpointer*)(ebp); } while (0); -#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->sp = (gpointer*)(esp); } while (0); +#define MONO_CONTEXT_SET_IP(ctx,eip) do { (ctx)->ip = (gpointer)(eip); } while (0); +#define MONO_CONTEXT_SET_BP(ctx,ebp) do { (ctx)->fp = (gpointer*)(ebp); } while (0); +#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->sp = (gpointer*)(esp); } while (0); #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->ip)) #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->fp)) @@ -917,13 +917,13 @@ typedef struct ucontext MonoContext; do { \ (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \ (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \ - } while (0); + } while (0); #define MONO_CONTEXT_SET_SP(ctx,bp) MONO_CONTEXT_SET_BP((ctx),(bp)) #define MONO_CONTEXT_SET_BP(ctx,bp) \ do { \ (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \ - } while (0) + } while (0) #define MONO_CONTEXT_GET_IP(ctx) (gpointer) (ctx)->uc_mcontext.psw.addr #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15])) diff --git a/src/mono/mono/utils/mono-counters.c b/src/mono/mono/utils/mono-counters.c index 5acf772cca9c6..9e93493dec282 100644 --- a/src/mono/mono/utils/mono-counters.c +++ b/src/mono/mono/utils/mono-counters.c @@ -211,7 +211,7 @@ register_internal (const char *name, int type, void *addr, int size) * It may be a function pointer if \c MONO_COUNTER_CALLBACK is specified: * the function should return the value and take no arguments. */ -void +void mono_counters_register (const char* name, int type, void *addr) { int size; @@ -620,7 +620,7 @@ mono_counters_dump_section (int section, int variance, FILE *outfile) * mono_counters_dump: * \param section_mask The sections to dump counters for * \param outfile a FILE to dump the results to; NULL will default to g_print - * Displays the counts of all the enabled counters registered. + * Displays the counts of all the enabled counters registered. * To filter by variance, you can OR one or more variance with the specific section you want. * Use \c MONO_COUNTER_SECTION_MASK to dump all categories of a specific variance. */ @@ -799,7 +799,7 @@ mono_counters_init (void) { } -void +void mono_counters_register (const char* name, int type, void *addr) { } diff --git a/src/mono/mono/utils/mono-counters.h b/src/mono/mono/utils/mono-counters.h index 77175b35f49a8..c5da782c7faac 100644 --- a/src/mono/mono/utils/mono-counters.h +++ b/src/mono/mono/utils/mono-counters.h @@ -57,7 +57,7 @@ typedef struct _MonoCounter MonoCounter; MONO_API void mono_counters_enable (int section_mask); MONO_API void mono_counters_init (void); -/* +/* * register addr as the address of a counter of type type. * It may be a function pointer if MONO_COUNTER_CALLBACK is specified: * the function should return the value and take no arguments. @@ -68,7 +68,7 @@ MONO_API void mono_counters_register_with_size (const char *name, int type, void typedef void (*MonoCounterRegisterCallback) (MonoCounter*); MONO_API void mono_counters_on_register (MonoCounterRegisterCallback callback); -/* +/* * Create a readable dump of the counters for section_mask sections (ORed section values) */ MONO_API void mono_counters_dump (int section_mask, FILE *outfile); diff --git a/src/mono/mono/utils/mono-dl-wasm.c b/src/mono/mono/utils/mono-dl-wasm.c index 3827dcea49584..4d5529926d814 100644 --- a/src/mono/mono/utils/mono-dl-wasm.c +++ b/src/mono/mono/utils/mono-dl-wasm.c @@ -12,7 +12,10 @@ #include #include #include + +#ifndef HOST_WASI #include +#endif const char * mono_dl_get_so_prefix (void) @@ -55,6 +58,8 @@ mono_dl_convert_flags (int mono_flags, int native_flags) { int lflags = native_flags; +#ifndef HOST_WASI // On WASI, these flags are undefined and not required + // Specifying both will default to LOCAL if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL)) lflags |= RTLD_GLOBAL; @@ -66,6 +71,8 @@ mono_dl_convert_flags (int mono_flags, int native_flags) else lflags |= RTLD_NOW; +#endif + return lflags; } diff --git a/src/mono/mono/utils/mono-embed.c b/src/mono/mono/utils/mono-embed.c index 1e535cca26fd6..fa89d37166e6a 100644 --- a/src/mono/mono/utils/mono-embed.c +++ b/src/mono/mono/utils/mono-embed.c @@ -29,12 +29,12 @@ static void * dl_mapping_open (const char *file, int flags, char **err, void *user_data) { MonoDlMapping *mappings; - + if (mono_dls == NULL){ *err = g_strdup ("Library not registered"); return NULL; } - + mappings = (MonoDlMapping *) g_hash_table_lookup (mono_dls, file); *err = g_strdup (mappings == NULL ? "File not registered" : ""); return mappings; @@ -44,7 +44,7 @@ static void * dl_mapping_symbol (void *handle, const char *symbol, char **err, void *user_data) { MonoDlMapping *mappings = (MonoDlMapping *) handle; - + for (;mappings->name; mappings++){ if (strcmp (symbol, mappings->name) == 0){ *err = g_strdup (""); @@ -60,11 +60,11 @@ dl_mapping_symbol (void *handle, const char *symbol, char **err, void *user_data * \param name Library name, this is the name used by the DllImport as the external library name * \param mappings the mappings to register for P/Invoke. * - * The mappings registered using this function are used as fallbacks if the dynamic linker + * The mappings registered using this function are used as fallbacks if the dynamic linker * fails, or if the platform doesn't have a dynamic linker. * * \p mappings is a pointer to the first element of an array of - * \c MonoDlMapping values. The list must be terminated with both + * \c MonoDlMapping values. The list must be terminated with both * the \c name and \c addr fields set to NULL. * * This is typically used like this: @@ -93,7 +93,7 @@ mono_dl_register_library (const char *name, MonoDlMapping *mappings) mono_dls = g_hash_table_new (g_str_hash, g_str_equal); mono_dl_fallback_register (dl_mapping_open, dl_mapping_symbol, NULL, NULL); } - + g_hash_table_insert (mono_dls, g_strdup (name), mappings); } diff --git a/src/mono/mono/utils/mono-embed.h b/src/mono/mono/utils/mono-embed.h index 9a81e788c5982..f4934a47a2de7 100644 --- a/src/mono/mono/utils/mono-embed.h +++ b/src/mono/mono/utils/mono-embed.h @@ -7,11 +7,11 @@ #include -/* +/* * This is a fallback for platform symbol loading functionality. */ typedef struct { - const char *name; + const char *name; void *addr; } MonoDlMapping; diff --git a/src/mono/mono/utils/mono-error-internals.h b/src/mono/mono/utils/mono-error-internals.h index a26558689ae1c..6d55b5a7f81a1 100644 --- a/src/mono/mono/utils/mono-error-internals.h +++ b/src/mono/mono/utils/mono-error-internals.h @@ -164,7 +164,7 @@ void mono_error_dup_strings (MonoError *error, gboolean dup_strings); /* This function is not very useful as you can't provide any details beyond the message.*/ -MONO_COMPONENT_API +MONO_COMPONENT_API void mono_error_set_error (MonoError *error, int error_code, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4); @@ -202,6 +202,7 @@ mono_error_set_generic_error (MonoError *error, const char * name_space, const c void mono_error_set_execution_engine (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3); +MONO_COMPONENT_API void mono_error_set_not_implemented (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3); @@ -209,7 +210,7 @@ MONO_COMPONENT_API void mono_error_set_not_supported (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3); -void +void mono_error_set_ambiguous_implementation (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3); MONO_COMPONENT_API diff --git a/src/mono/mono/utils/mono-error.c b/src/mono/mono/utils/mono-error.c index 6d02df6968dc2..0f422502de118 100644 --- a/src/mono/mono/utils/mono-error.c +++ b/src/mono/mono/utils/mono-error.c @@ -311,7 +311,7 @@ mono_error_set_class (MonoError *oerror, MonoClass *klass) if (is_managed_exception (error)) return; - error->exn.klass = klass; + error->exn.klass = klass; } static void @@ -716,9 +716,9 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) case MONO_ERROR_ARGUMENT_NULL: exception = mono_exception_new_argument_null (error->first_argument, error_out); break; - - case MONO_ERROR_ARGUMENT_OUT_OF_RANGE: - exception = mono_exception_new_argument_out_of_range(error->first_argument, error->full_message, error_out); + + case MONO_ERROR_ARGUMENT_OUT_OF_RANGE: + exception = mono_exception_new_argument_out_of_range(error->first_argument, error->full_message, error_out); break; case MONO_ERROR_NOT_VERIFIABLE: @@ -852,7 +852,7 @@ mono_error_box (const MonoError *ierror, MonoImage *image) to->exn.klass = from->exn.klass; #undef DUP_STR - + return box; } @@ -896,7 +896,7 @@ mono_error_set_from_boxed (MonoError *oerror, const MonoErrorBoxed *box) DUP_STR (full_message_with_fields); DUP_STR (first_argument); to->exn.klass = from->exn.klass; - + #undef DUP_STR return (to->flags & MONO_ERROR_INCOMPLETE) == 0 ; } diff --git a/src/mono/mono/utils/mono-error.h b/src/mono/mono/utils/mono-error.h index 69bfb8a47346f..297412b3d5a15 100644 --- a/src/mono/mono/utils/mono-error.h +++ b/src/mono/mono/utils/mono-error.h @@ -40,7 +40,7 @@ enum { /* * This is a generic error mechanism is you need to raise an arbitrary corlib exception. - * You must pass the exception name otherwise prepare_exception will fail with internal execution. + * You must pass the exception name otherwise prepare_exception will fail with internal execution. */ MONO_ERROR_GENERIC = 9, /* This one encapsulates a managed exception instance */ diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index 3fe31d7776f76..0c4ac46a5b497 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -44,7 +44,7 @@ mono_file_map_open (const char* name) #endif } -guint64 +guint64 mono_file_map_size (MonoFileMap *fmap) { struct stat stat_buf; @@ -63,7 +63,7 @@ mono_file_map_fd (MonoFileMap *fmap) #endif } -int +int mono_file_map_close (MonoFileMap *fmap) { #ifdef WIN32 diff --git a/src/mono/mono/utils/mono-flight-recorder.c b/src/mono/mono/utils/mono-flight-recorder.c index 7ff4b59d737da..ab14f4fe57848 100644 --- a/src/mono/mono/utils/mono-flight-recorder.c +++ b/src/mono/mono/utils/mono-flight-recorder.c @@ -26,14 +26,14 @@ // Mutex has to be held when called void -mono_flight_recorder_iter_init (MonoFlightRecorder *recorder, MonoFlightRecorderIter *iter) +mono_flight_recorder_iter_init (MonoFlightRecorder *recorder, MonoFlightRecorderIter *iter) { // Make sure we are initialized g_assert (recorder->max_count > 0); iter->recorder = recorder; if (recorder->cursor == MONO_FLIGHT_RECORDER_SENTINEL) { - iter->lowest_index = MONO_FLIGHT_RECORDER_SENTINEL; + iter->lowest_index = MONO_FLIGHT_RECORDER_SENTINEL; iter->highest_index = MONO_FLIGHT_RECORDER_SENTINEL; } else if (recorder->cursor >= recorder->max_count) { // Ring buffer has wrapped around diff --git a/src/mono/mono/utils/mono-hwcap-arm.c b/src/mono/mono/utils/mono-hwcap-arm.c index b4de27ee1de98..c6a30854a3918 100644 --- a/src/mono/mono/utils/mono-hwcap-arm.c +++ b/src/mono/mono/utils/mono-hwcap-arm.c @@ -95,21 +95,21 @@ mono_hwcap_arch_init (void) /* TODO: Find a way to detect features like Thumb and VFP. */ #elif defined (_WIN32) - /* From MSDN: - * Windows on ARM presumes that it is running on an ARMv7 architecture at all times. + /* From MSDN: + * Windows on ARM presumes that it is running on an ARMv7 architecture at all times. * Floating-point support in the form of VFPv3-D32 or later must be present in hardware. - * The VFP must support both single-precision and double-precision floating-point in hardware. + * The VFP must support both single-precision and double-precision floating-point in hardware. * * The Windows runtime does not support emulation of floating-point to enable running on non-VFP hardware. - * Advanced SIMD Extensions (NEON) support—this includes both integer and floating-point operations—must also be present in hardware. + * Advanced SIMD Extensions (NEON) support—this includes both integer and floating-point operations—must also be present in hardware. * No run-time support for emulation is provided. * * Integer divide support (UDIV/SDIV) is strongly recommended but not required. * Platforms that lack integer divide support may incur a performance penalty because * these operations have to be trapped and possibly patched. * - * The instruction set for Windows on ARM is strictly limited to Thumb-2. - * All code executed on this platform is expected to start and remain in Thumb mode at all times. + * The instruction set for Windows on ARM is strictly limited to Thumb-2. + * All code executed on this platform is expected to start and remain in Thumb mode at all times. */ mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; diff --git a/src/mono/mono/utils/mono-jemalloc.c b/src/mono/mono/utils/mono-jemalloc.c index 4b0f5baa05c6d..16b4c1d7c6207 100644 --- a/src/mono/mono/utils/mono-jemalloc.c +++ b/src/mono/mono/utils/mono-jemalloc.c @@ -9,7 +9,7 @@ #ifdef MONO_JEMALLOC_ENABLED -void +void mono_init_jemalloc (void) { GMemVTable g_mem_vtable = { MONO_JEMALLOC_MALLOC, MONO_JEMALLOC_REALLOC, MONO_JEMALLOC_FREE, MONO_JEMALLOC_CALLOC}; diff --git a/src/mono/mono/utils/mono-jemalloc.h b/src/mono/mono/utils/mono-jemalloc.h index 6721877f51428..73d869bbb36d0 100644 --- a/src/mono/mono/utils/mono-jemalloc.h +++ b/src/mono/mono/utils/mono-jemalloc.h @@ -16,11 +16,11 @@ * 2. You can use it as a global malloc replacement * 3. You can use it with a prefix. If you use it with a prefix, you have to explicitly name the malloc function. * - * In order to make this feature able to be toggled at run-time, I chose to use a prefix of mono_je. + * In order to make this feature able to be toggled at run-time, I chose to use a prefix of mono_je. * This mapping is captured below in the header, in the spirit of "no magic constants". * * The place that configures jemalloc and sets this prefix is in the Makefile in - * mono/jemalloc/Makefile.am + * mono/jemalloc/Makefile.am * */ #define MONO_JEMALLOC_MALLOC mono_jemalloc diff --git a/src/mono/mono/utils/mono-linked-list-set.c b/src/mono/mono/utils/mono-linked-list-set.c index ee43dfdf7a3af..a3a2b7f548cad 100644 --- a/src/mono/mono/utils/mono-linked-list-set.c +++ b/src/mono/mono/utils/mono-linked-list-set.c @@ -139,7 +139,7 @@ gboolean mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value) { MonoLinkedListSetNode *cur, **prev; - /*We must do a store barrier before inserting + /*We must do a store barrier before inserting to make sure all values in @node are globally visible.*/ mono_memory_barrier (); diff --git a/src/mono/mono/utils/mono-log-android.c b/src/mono/mono/utils/mono-log-android.c index 6a86ce1c8fba6..4a4c4b1932fd5 100644 --- a/src/mono/mono/utils/mono-log-android.c +++ b/src/mono/mono/utils/mono-log-android.c @@ -20,7 +20,7 @@ * \param path Unused * \param userData Unused * Open access to Android logcat (no-op) - */ + */ void mono_log_open_logcat (const char *path, void *userData) { diff --git a/src/mono/mono/utils/mono-log-common.c b/src/mono/mono/utils/mono-log-common.c index 74cfd6adba2e6..6ad11e378cca2 100644 --- a/src/mono/mono/utils/mono-log-common.c +++ b/src/mono/mono/utils/mono-log-common.c @@ -35,7 +35,7 @@ static void *logUserData = NULL; /** * mapSyslogLevel: - * + * * @level - GLogLevelFlags value * @returns The equivalent character identifier */ @@ -80,7 +80,7 @@ mono_log_open_logfile(const char *path, void *userData) } #endif if (logFile == NULL) { - g_warning("opening of log file %s failed with %s - defaulting to stdout", + g_warning("opening of log file %s failed with %s - defaulting to stdout", path, strerror(errno)); logFile = stdout; } diff --git a/src/mono/mono/utils/mono-log-flight-recorder.c b/src/mono/mono/utils/mono-log-flight-recorder.c index ff76d6d43346e..c083391038f1b 100644 --- a/src/mono/mono/utils/mono-log-flight-recorder.c +++ b/src/mono/mono/utils/mono-log-flight-recorder.c @@ -63,7 +63,7 @@ handle_command (gpointer state, gpointer payload, gboolean at_shutdown) #if 0 // Dump all messages on each append. This is an aggressive, slow - // debugging method. + // debugging method. LogMessage messages [MAX_RECORDER_LOG_LEN]; LogQueueDumpRequest dump; @@ -100,8 +100,8 @@ static MonoUtilityThread *logger_thread; * mono_log_open_recorder: * \param path Unused * \param userData Unused - * Open access to recorder - */ + * Open access to recorder + */ void mono_log_open_recorder (const char *path, void *userData) { @@ -150,7 +150,7 @@ mono_log_write_recorder (const char *log_domain, GLogLevelFlags level, mono_bool /** * mono_log_close_recorder * - * Close access to recorder + * Close access to recorder */ void mono_log_close_recorder (void) diff --git a/src/mono/mono/utils/mono-log-posix.c b/src/mono/mono/utils/mono-log-posix.c index 6a1568d8bbb32..094a9f1a5bd25 100644 --- a/src/mono/mono/utils/mono-log-posix.c +++ b/src/mono/mono/utils/mono-log-posix.c @@ -14,7 +14,7 @@ #include #endif -#if defined(_POSIX_VERSION) +#if defined(_POSIX_VERSION) && !defined(HOST_WASI) #include #include @@ -32,12 +32,12 @@ static void *logUserData = NULL; /** * mapSyslogLevel: - * + * * @level - GLogLevelFlags value * @returns The equivalent syslog priority value */ static __inline__ int -mapSyslogLevel(GLogLevelFlags level) +mapSyslogLevel(GLogLevelFlags level) { if (level & G_LOG_LEVEL_ERROR) return (LOG_ERR); @@ -58,7 +58,7 @@ mapSyslogLevel(GLogLevelFlags level) * mono_log_open_syslog: * \param ident Identifier: ignored * \param userData Not used - * Open the syslog interface specifying that we want our PID recorded + * Open the syslog interface specifying that we want our PID recorded * and that we're using the \c LOG_USER facility. */ void diff --git a/src/mono/mono/utils/mono-log-windows.c b/src/mono/mono/utils/mono-log-windows.c index b7d328cf33e02..cd6e8922d76d5 100644 --- a/src/mono/mono/utils/mono-log-windows.c +++ b/src/mono/mono/utils/mono-log-windows.c @@ -34,7 +34,7 @@ static const wchar_t *logFileName = L".//mono.log"; // FIXME double slash /** * mapSyslogLevel: - * + * * @level - GLogLevelFlags value * @returns The equivalent character identifier */ @@ -60,7 +60,7 @@ mapLogFileLevel (GLogLevelFlags level) * mono_log_open_syslog: * \param ident Identifier: ignored * \param userData Not used - * Open the syslog file. If the open fails issue a warning and + * Open the syslog file. If the open fails issue a warning and * use stdout as the log file destination. */ void diff --git a/src/mono/mono/utils/mono-logger-internals.h b/src/mono/mono/utils/mono-logger-internals.h index bff13285fb6d9..4100ddaa105f2 100644 --- a/src/mono/mono/utils/mono-logger-internals.h +++ b/src/mono/mono/utils/mono-logger-internals.h @@ -45,16 +45,16 @@ mono_trace_init (void); MONO_API void mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args); -void +void mono_trace_set_level (GLogLevelFlags level); -void +void mono_trace_set_mask (MonoTraceMask mask); -void +void mono_trace_push (GLogLevelFlags level, MonoTraceMask mask); -void +void mono_trace_pop (void); MONO_COMPONENT_API diff --git a/src/mono/mono/utils/mono-logger.c b/src/mono/mono/utils/mono-logger.c index b5870ac3b2515..83a97b326ea14 100644 --- a/src/mono/mono/utils/mono-logger.c +++ b/src/mono/mono/utils/mono-logger.c @@ -37,7 +37,7 @@ typedef struct { * * Initializes the mono tracer. */ -void +void mono_trace_init (void) { if(level_stack == NULL) { @@ -68,7 +68,7 @@ mono_trace_init (void) * Traces a new message, depending on the current logging level * and trace mask. */ -void +void mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args) { char *log_message; @@ -93,7 +93,7 @@ mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, * \c mono_trace will check the visibility of a message against this * value. */ -void +void mono_trace_set_level (GLogLevelFlags level) { if(level_stack == NULL) @@ -109,7 +109,7 @@ mono_trace_set_level (GLogLevelFlags level) * \c mono_trace will check the visibility of a message against this * value. */ -void +void mono_trace_set_mask (MonoTraceMask mask) { if(level_stack == NULL) @@ -124,7 +124,7 @@ mono_trace_set_mask (MonoTraceMask mask) * Sets the current logging destination. This can be a file or, if supported, * syslog. */ -void +void mono_trace_set_logdest_string (const char *dest) { MonoLogCallParm logger; @@ -179,7 +179,7 @@ mono_trace_set_logdest_string (const char *dest) * \param head Whether we want pid/date/time header on log messages * Sets the current logging header option. */ -void +void mono_trace_set_logheader_string(const char *head) { if (head == NULL) { @@ -196,7 +196,7 @@ mono_trace_set_logheader_string(const char *head) * Saves the current values of level and mask then calls \c mono_trace_set * with the specified new values. */ -void +void mono_trace_push (GLogLevelFlags level, MonoTraceMask mask) { if(level_stack == NULL) @@ -220,7 +220,7 @@ mono_trace_push (GLogLevelFlags level, MonoTraceMask mask) * * Restores level and mask values saved from a previous call to mono_trace_push. */ -void +void mono_trace_pop (void) { if(level_stack == NULL) @@ -240,7 +240,7 @@ mono_trace_pop (void) } -void +void mono_trace_set_level_string (const char *value) { int i = 0; @@ -263,7 +263,7 @@ mono_trace_set_level_string (const char *value) g_print("Unknown trace loglevel: %s\n", value); } -void +void mono_trace_set_mask_string (const char *value) { int i; @@ -368,7 +368,7 @@ log_level_get_name (GLogLevelFlags log_level) /** * callback_adapter - * + * * @log_domain Message prefix * @log_level Severity * @message Message to be written @@ -415,7 +415,7 @@ legacy_closer(void) { if (logCallback.user_data != NULL) { g_free (logCallback.user_data); /* This is a UserSuppliedLoggerUserData struct */ - logCallback.opener = NULL; + logCallback.opener = NULL; logCallback.writer = NULL; logCallback.closer = NULL; logCallback.user_data = NULL; @@ -425,10 +425,10 @@ legacy_closer(void) /** * mono_trace_set_log_handler: - * + * * @callback The callback that will replace the default logging handler * @user_data Argument passed to @callback - * + * * The log handler replaces the default runtime logger. All logging requests with be routed to it. * If the fatal argument in the callback is true, the callback must abort the current process. The runtime expects that * execution will not resume after a fatal error. diff --git a/src/mono/mono/utils/mono-logger.h b/src/mono/mono/utils/mono-logger.h index a90e6c54cf365..e3ef20475485c 100644 --- a/src/mono/mono/utils/mono-logger.h +++ b/src/mono/mono/utils/mono-logger.h @@ -8,10 +8,10 @@ #include MONO_BEGIN_DECLS -MONO_API void +MONO_API void mono_trace_set_level_string (const char *value); -MONO_API void +MONO_API void mono_trace_set_mask_string (const char *value); typedef void (*MonoPrintCallback) (const char *string, mono_bool is_stdout); diff --git a/src/mono/mono/utils/mono-md5.c b/src/mono/mono/utils/mono-md5.c index 165e42a564f92..b239cd1782cef 100644 --- a/src/mono/mono/utils/mono-md5.c +++ b/src/mono/mono/utils/mono-md5.c @@ -86,7 +86,7 @@ static union _endian { gint i; gchar b[4]; } *_endian = (union _endian *)&_ie; /* * Note: this code is harmless on little-endian machines. */ -static void +static void _byte_reverse (guchar *buf, guint32 longs) { guint32 t; @@ -100,26 +100,26 @@ _byte_reverse (guchar *buf, guint32 longs) /** * mono_md5_init: Initialise an md5 context object - * @ctx: md5 context - * - * Initialise an md5 buffer. + * @ctx: md5 context + * + * Initialise an md5 buffer. * **/ -void +void mono_md5_init (MonoMD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; - + ctx->bits[0] = 0; ctx->bits[1] = 0; - - if (IS_BIG_ENDIAN()) - ctx->doByteReverse = 1; - else - ctx->doByteReverse = 0; + + if (IS_BIG_ENDIAN()) + ctx->doByteReverse = 1; + else + ctx->doByteReverse = 0; } @@ -129,29 +129,29 @@ mono_md5_init (MonoMD5Context *ctx) * @ctx: conetxt object used for md5 computaion * @buf: buffer to add * @len: buffer length - * + * * Update context to reflect the concatenation of another buffer full * of bytes. Use this to progressively construct an md5 hash. **/ -void +void mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) { guint32 t; - + /* Update bitcount */ - + t = ctx->bits[0]; if ((ctx->bits[0] = t + ((guint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; - + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - + /* Handle any leading odd-sized chunks */ - + if (t) { guchar *p = (guchar *) ctx->in + t; - + t = 64 - t; if (len < t) { memcpy (p, buf, len); @@ -165,7 +165,7 @@ mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) len -= t; } /* Process data in 64-byte chunks */ - + while (len >= 64) { memcpy (ctx->in, buf, 64); if (ctx->doByteReverse) @@ -174,9 +174,9 @@ mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) buf += 64; len -= 64; } - + /* Handle any remaining bytes of data. */ - + memcpy (ctx->in, buf, len); } @@ -185,33 +185,33 @@ mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) /* - * Final wrapup - pad to 64-byte boundary with the bit pattern + * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ /** * mono_md5_final: copy the final md5 hash to a bufer * @digest: 16 bytes buffer * @ctx: context containing the calculated md5 - * + * * copy the final md5 hash to a bufer **/ -void +void mono_md5_final (MonoMD5Context *ctx, guchar digest[16]) { guint32 count; guchar *p; - + /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; - + /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; - + /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; - + /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ @@ -219,7 +219,7 @@ mono_md5_final (MonoMD5Context *ctx, guchar digest[16]) if (ctx->doByteReverse) _byte_reverse (ctx->in, 16); md5_transform (ctx->buf, (guint32 *) ctx->in); - + /* Now fill the next block with 56 bytes */ memset (ctx->in, 0, 56); } else { @@ -228,11 +228,11 @@ mono_md5_final (MonoMD5Context *ctx, guchar digest[16]) } if (ctx->doByteReverse) _byte_reverse (ctx->in, 14); - + /* Append length in bits and transform */ ((guint32 *) ctx->in)[14] = ctx->bits[0]; ((guint32 *) ctx->in)[15] = ctx->bits[1]; - + md5_transform (ctx->buf, (guint32 *) ctx->in); if (ctx->doByteReverse) _byte_reverse ((guchar *) ctx->buf, 4); @@ -265,16 +265,16 @@ mono_md5_ctx_byte_length (MonoMD5Context *ctx) * reflect the addition of 16 longwords of new data. md5_Update blocks * the data and converts bytes into longwords for this routine. */ -static void +static void md5_transform (guint32 buf[4], const guint32 in[16]) { guint32 a, b, c, d; - + a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; - + MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17); @@ -291,7 +291,7 @@ md5_transform (guint32 buf[4], const guint32 in[16]) MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22); - + MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14); @@ -308,7 +308,7 @@ md5_transform (guint32 buf[4], const guint32 in[16]) MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - + MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16); @@ -325,7 +325,7 @@ md5_transform (guint32 buf[4], const guint32 in[16]) MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - + MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15); @@ -342,7 +342,7 @@ md5_transform (guint32 buf[4], const guint32 in[16]) MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21); - + buf[0] += a; buf[1] += b; buf[2] += c; @@ -357,19 +357,19 @@ md5_transform (guint32 buf[4], const guint32 in[16]) * \param buffer byte buffer * \param buffer_size buffer size (in bytes) * \param digest 16-byte buffer receiving the hash code. - * - * Get the MD5 hash of a buffer. The result is put in + * + * Get the MD5 hash of a buffer. The result is put in * the 16-byte buffer \p digest. */ void mono_md5_get_digest (const guchar *buffer, gint buffer_size, guchar digest[16]) -{ +{ MonoMD5Context ctx; mono_md5_init (&ctx); mono_md5_update (&ctx, buffer, buffer_size); mono_md5_final (&ctx, digest); - + } @@ -377,15 +377,15 @@ mono_md5_get_digest (const guchar *buffer, gint buffer_size, guchar digest[16]) * mono_md5_get_digest_from_file: * \param filename file name * \param digest 16-byte buffer receiving the hash code. - * - * Get the MD5 hash of a file. The result is put in + * + * Get the MD5 hash of a file. The result is put in * the 16-byte buffer \p digest. - * + * * If an IO error happens the value in \p digest is not updated. */ void mono_md5_get_digest_from_file (const gchar *filename, guchar digest[16]) -{ +{ MonoMD5Context ctx; guchar tmp_buf[1024]; gint nb_bytes_read; @@ -396,10 +396,10 @@ mono_md5_get_digest_from_file (const gchar *filename, guchar digest[16]) if (!fp) { return; } - + while ((nb_bytes_read = fread (tmp_buf, sizeof (guchar), 1024, fp)) > 0) mono_md5_update (&ctx, tmp_buf, nb_bytes_read); - + if (ferror(fp)) { fclose(fp); return; diff --git a/src/mono/mono/utils/mono-memory-model.h b/src/mono/mono/utils/mono-memory-model.h index a35433fd023dd..863ee77d61563 100644 --- a/src/mono/mono/utils/mono-memory-model.h +++ b/src/mono/mono/utils/mono-memory-model.h @@ -22,7 +22,7 @@ On the other hand, we can't use arm's weak model on targets such as x86 that hav a stronger model that requires much much less fencing. The idea of exposing each arch memory model is to avoid fencing whenever possible -but at the same time make all required ordering explicit. +but at the same time make all required ordering explicit. There are four kinds of barriers, LoadLoad, LoadStore, StoreLoad and StoreStore. Each arch must define which ones needs fencing. @@ -109,19 +109,19 @@ LDR R3, [R4, R0] #ifndef STORE_STORE_FENCE #define STORE_STORE_FENCE mono_compiler_barrier () -#endif +#endif #ifndef LOAD_LOAD_FENCE #define LOAD_LOAD_FENCE mono_compiler_barrier () -#endif +#endif #ifndef STORE_LOAD_FENCE #define STORE_LOAD_FENCE mono_compiler_barrier () -#endif +#endif #ifndef LOAD_STORE_FENCE #define LOAD_STORE_FENCE mono_compiler_barrier () -#endif +#endif #ifndef STORE_RELEASE_FENCE #define STORE_RELEASE_FENCE mono_compiler_barrier () diff --git a/src/mono/mono/utils/mono-mmap-wasm.c b/src/mono/mono/utils/mono-mmap-wasm.c index b04d69ab1b5e2..3364ec4fed939 100644 --- a/src/mono/mono/utils/mono-mmap-wasm.c +++ b/src/mono/mono/utils/mono-mmap-wasm.c @@ -64,6 +64,12 @@ mono_valloc_granule (void) static int prot_from_flags (int flags) { +#if HOST_WASI + // The mmap in wasi-sdk rejects PROT_NONE, but otherwise disregards the flags + // We just need to pass an acceptable value + return PROT_READ; +#endif + int prot = PROT_NONE; /* translate the protection bits */ if (flags & MONO_MMAP_READ) @@ -72,6 +78,7 @@ prot_from_flags (int flags) prot |= PROT_WRITE; if (flags & MONO_MMAP_EXEC) prot |= PROT_EXEC; + return prot; } diff --git a/src/mono/mono/utils/mono-networkinterfaces.c b/src/mono/mono/utils/mono-networkinterfaces.c index f86bd651ee74b..c93ce63db77cd 100644 --- a/src/mono/mono/utils/mono-networkinterfaces.c +++ b/src/mono/mono/utils/mono-networkinterfaces.c @@ -27,7 +27,7 @@ mono_networkinterface_list (int *size) char name [256]; f = fopen ("/proc/net/dev", "r"); - if (!f) + if (!f) return NULL; if (!fgets (buf, sizeof (buf) / sizeof (char), f)) @@ -86,7 +86,7 @@ mono_network_get_data (char* name, MonoNetworkData data, MonoNetworkError *error *error = MONO_NETWORK_ERROR_OTHER; f = fopen ("/proc/net/dev", "r"); - if (!f) + if (!f) return -1; if (!fgets (buf, sizeof (buf) / sizeof (char), f)) @@ -109,7 +109,7 @@ mono_network_get_data (char* name, MonoNetworkData data, MonoNetworkError *error &rx_bytes, &rx_packets, &rx_errs, &rx_drops, &rx_fifo, &rx_frame, &rx_multi, &tx_bytes, &tx_packets, &tx_errs, &tx_drops, - &tx_fifo, &tx_colls, &tx_carrier) != 14) + &tx_fifo, &tx_colls, &tx_carrier) != 14) goto out; switch (data) { diff --git a/src/mono/mono/utils/mono-path.c b/src/mono/mono/utils/mono-path.c index 2f4790666a428..5e4f117272206 100644 --- a/src/mono/mono/utils/mono-path.c +++ b/src/mono/mono/utils/mono-path.c @@ -1,7 +1,7 @@ /** * \file * Routines for handling path names. - * + * * Authors: * Gonzalo Paniagua Javier (gonzalo@novell.com) * Miguel de Icaza (miguel@novell.com) @@ -69,7 +69,7 @@ mono_path_canonicalize (const char *path) if (backc > 0) { backc--; } else { - if (dest != lastpos) + if (dest != lastpos) /* The two strings can overlap */ memmove (dest, lastpos, len + 1); dest += len + 1; @@ -86,9 +86,9 @@ mono_path_canonicalize (const char *path) if (*(lastpos-1) == G_DIR_SEPARATOR && *(lastpos-2) == G_DIR_SEPARATOR && *lastpos == 0) lastpos = lastpos-1; #endif - + if (dest != lastpos) strcpy (dest, lastpos); - + g_strreverse (abspath); /* We strip away all trailing dir separators. This is not correct for the root directory, @@ -126,7 +126,7 @@ resolve_symlink (const char *path) g_free (copy); return p; } - + buffer [n] = 0; if (!g_path_is_absolute (buffer)) { dir = g_path_get_dirname (p); diff --git a/src/mono/mono/utils/mono-poll.c b/src/mono/mono/utils/mono-poll.c index 022cabc24b4be..20091c34e6dc9 100644 --- a/src/mono/mono/utils/mono-poll.c +++ b/src/mono/mono/utils/mono-poll.c @@ -108,7 +108,7 @@ mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout) nexc++; if (fd > maxfd) maxfd = fd; - + } affected = select (maxfd + 1, &rfds, &wfds, &efds, tvptr); diff --git a/src/mono/mono/utils/mono-private-unstable.h b/src/mono/mono/utils/mono-private-unstable.h index 241a723447957..489c3451b49b0 100644 --- a/src/mono/mono/utils/mono-private-unstable.h +++ b/src/mono/mono/utils/mono-private-unstable.h @@ -1,6 +1,6 @@ /** * \file - * + * * Private unstable APIs. * * WARNING: The declarations and behavior of functions in this header are NOT STABLE and can be modified or removed at diff --git a/src/mono/mono/utils/mono-property-hash.c b/src/mono/mono/utils/mono-property-hash.c index 0703b8b977778..65b257d2e16f7 100644 --- a/src/mono/mono/utils/mono-property-hash.c +++ b/src/mono/mono/utils/mono-property-hash.c @@ -56,7 +56,7 @@ mono_property_hash_insert (MonoPropertyHash *hash, gpointer object, guint32 prop } g_hash_table_insert (prop_hash, object, value); -} +} static void remove_object (gpointer key, gpointer value, gpointer user_data) @@ -82,4 +82,4 @@ mono_property_hash_lookup (MonoPropertyHash *hash, gpointer object, guint32 prop return NULL; return g_hash_table_lookup (prop_hash, object); } - + diff --git a/src/mono/mono/utils/mono-publib.h b/src/mono/mono/utils/mono-publib.h index b01438e52cf1c..24346ccf1c578 100644 --- a/src/mono/mono/utils/mono-publib.h +++ b/src/mono/mono/utils/mono-publib.h @@ -5,7 +5,7 @@ #ifndef __MONO_PUBLIB_H__ #define __MONO_PUBLIB_H__ -/* +/* * Minimal general purpose header for use in public mono header files. * We can't include config.h, so we use compiler-specific preprocessor * directives where needed. diff --git a/src/mono/mono/utils/mono-rand.c b/src/mono/mono/utils/mono-rand.c index ae6e795169562..52b1e2807fdb8 100644 --- a/src/mono/mono/utils/mono-rand.c +++ b/src/mono/mono/utils/mono-rand.c @@ -131,7 +131,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, gssize buffer_size, Mono gint ret; guint offset = 0; int err = 0; - + socket_fd = socket (PF_UNIX, SOCK_STREAM, 0); if (socket_fd < 0) { ret = -1; @@ -325,7 +325,7 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gssize buffer_size, M error_init (error); g_static_assert (RAND_MAX >= 0xFF); - + while (buffer_size > 0) { int const i = rand (); int j; diff --git a/src/mono/mono/utils/mono-sha1.c b/src/mono/mono/utils/mono-sha1.c index bfcf6cf4031b5..7b6d6dd4d273e 100644 --- a/src/mono/mono/utils/mono-sha1.c +++ b/src/mono/mono/utils/mono-sha1.c @@ -5,7 +5,7 @@ By Steve Reid 100% Public Domain ----------------- -Modified 7/98 +Modified 7/98 By James H. Brown Still 100% Public Domain @@ -27,7 +27,7 @@ Since the file IO in main() reads 16K at a time, any file 8K or larger would be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million "a"s). -I also changed the declaration of variables i & j in mono_sha1_update to +I also changed the declaration of variables i & j in mono_sha1_update to unsigned long from unsigned int for the same reason. These changes should make no difference to any 32 bit implementations since @@ -54,7 +54,7 @@ Still 100% public domain Modified 4/01 By Saul Kravitz Still 100% PD -Modified to run on Compaq Alpha hardware. +Modified to run on Compaq Alpha hardware. */ @@ -137,7 +137,7 @@ static void SHA1Transform(guint32 state[5], const guchar buffer[64]); static void SHAPrintContext(MonoSHA1Context *context, char *msg){ printf("%s (%d,%d) %x %x %x %x %x\n", msg, - context->count[0], context->count[1], + context->count[0], context->count[1], context->state[0], context->state[1], context->state[2], @@ -287,28 +287,28 @@ unsigned char finalcount[8]; */ void mono_sha1_get_digest (const guchar *buffer, gint buffer_size, guchar digest [20]) -{ +{ MonoSHA1Context ctx; mono_sha1_init (&ctx); mono_sha1_update (&ctx, buffer, buffer_size); mono_sha1_final (&ctx, digest); - + } /** * mono_sha1_get_digest_from_file: * \param filename file name * \param digest 20-byte buffer receiving the hash code. - * - * Get the SHA-1 hash of a file. The result is put in + * + * Get the SHA-1 hash of a file. The result is put in * the 20-byte buffer \p digest. - * + * * If an IO error happens the value in \p digest is not updated. */ void mono_sha1_get_digest_from_file (const gchar *filename, guchar digest [20]) -{ +{ MonoSHA1Context ctx; guchar tmp_buf[1024]; gint nb_bytes_read; @@ -319,10 +319,10 @@ mono_sha1_get_digest_from_file (const gchar *filename, guchar digest [20]) if (!fp) { return; } - + while ((nb_bytes_read = fread (tmp_buf, sizeof (guchar), 1024, fp)) > 0) mono_sha1_update (&ctx, tmp_buf, nb_bytes_read); - + if (ferror(fp)) { fclose(fp); return; @@ -339,7 +339,7 @@ mono_sha1_get_digest_from_file (const gchar *filename, guchar digest [20]) * Get the public token from public key data. * \p token must point to at least 8 bytes of storage. */ -void +void mono_digest_get_public_token (guchar* token, const guchar *pubkey, guint32 len) { guchar digest [20]; diff --git a/src/mono/mono/utils/mono-stack-unwinding.h b/src/mono/mono/utils/mono-stack-unwinding.h index b3109a9b0e61f..66931c6defc04 100644 --- a/src/mono/mono/utils/mono-stack-unwinding.h +++ b/src/mono/mono/utils/mono-stack-unwinding.h @@ -55,7 +55,7 @@ typedef enum { typedef struct { MonoStackFrameType type; - /* + /* * For FRAME_TYPE_MANAGED, otherwise NULL. */ MonoJitInfo *ji; @@ -79,7 +79,7 @@ typedef struct { int native_offset; /* * IL offset of this frame. - * Only available if the runtime have debugging enabled (--debug switch) and + * Only available if the runtime have debugging enabled (--debug switch) and * il offset resultion was requested (MONO_UNWIND_LOOKUP_IL_OFFSET) */ int il_offset; @@ -114,7 +114,7 @@ typedef struct { enum { MONO_UNWIND_DATA_DOMAIN, MONO_UNWIND_DATA_LMF, - MONO_UNWIND_DATA_JIT_TLS, + MONO_UNWIND_DATA_JIT_TLS, }; /* diff --git a/src/mono/mono/utils/mono-stdlib.c b/src/mono/mono/utils/mono-stdlib.c index 5f679b15fafdf..3c94f06aa1d48 100644 --- a/src/mono/mono/utils/mono-stdlib.c +++ b/src/mono/mono/utils/mono-stdlib.c @@ -1,7 +1,7 @@ /** * \file * stdlib replacement functions. - * + * * Authors: * Gonzalo Paniagua Javier (gonzalo@novell.com) * diff --git a/src/mono/mono/utils/mono-stdlib.h b/src/mono/mono/utils/mono-stdlib.h index eb8531bc86a43..64793b223b846 100644 --- a/src/mono/mono/utils/mono-stdlib.h +++ b/src/mono/mono/utils/mono-stdlib.h @@ -12,5 +12,9 @@ int mono_mkstemp (char *templ); #endif +#if HOST_WASI +char *mktemp (char *); +#endif + #endif /* __MONO_FILE_H */ diff --git a/src/mono/mono/utils/mono-threads-aix.c b/src/mono/mono/utils/mono-threads-aix.c index 28cae9b44abec..5ce0e25561930 100644 --- a/src/mono/mono/utils/mono-threads-aix.c +++ b/src/mono/mono/utils/mono-threads-aix.c @@ -12,7 +12,7 @@ void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { - /* see GC_push_all_stacks in libgc/aix_irix_threads.c + /* see GC_push_all_stacks in libgc/aix_irix_threads.c for why we do this; pthread_getattr_np exists only on some versions of AIX and not on PASE, so use a legacy way to get the stack information */ diff --git a/src/mono/mono/utils/mono-threads-coop.c b/src/mono/mono/utils/mono-threads-coop.c index 970a7099e9ecf..602a607439c0f 100644 --- a/src/mono/mono/utils/mono-threads-coop.c +++ b/src/mono/mono/utils/mono-threads-coop.c @@ -41,7 +41,7 @@ #elif defined (HOST_WASM) //TODO: figure out wasm stack scanning #define SAVE_REGS_ON_STACK do {} while (0) -#else +#else #define SAVE_REGS_ON_STACK __builtin_unwind_init (); #endif diff --git a/src/mono/mono/utils/mono-threads-mach-helper.c b/src/mono/mono/utils/mono-threads-mach-helper.c index 7b4f140b619ef..498d9ff069d65 100644 --- a/src/mono/mono/utils/mono-threads-mach-helper.c +++ b/src/mono/mono/utils/mono-threads-mach-helper.c @@ -49,7 +49,7 @@ static id mono_dead_letter_key; * due to duplicate entries. * * So what do we do here? - * + * * Experimentation showns that threadDictionary is destroied after the * problematic keys, so we add our dead letter object as an aditional * way to be notified of thread death. @@ -115,7 +115,7 @@ mono_threads_init_dead_letter (void) alloc = sel_registerName ("alloc"); release = sel_registerName ("release"); dealloc = sel_registerName ("dealloc"); - + currentThread = sel_registerName ("currentThread"); threadDictionary = sel_registerName ("threadDictionary"); diff --git a/src/mono/mono/utils/mono-threads-state-machine.c b/src/mono/mono/utils/mono-threads-state-machine.c index 927d86d619f23..8b863f8371349 100644 --- a/src/mono/mono/utils/mono-threads-state-machine.c +++ b/src/mono/mono/utils/mono-threads-state-machine.c @@ -315,7 +315,7 @@ mono_threads_transition_request_suspension (MonoThreadInfo *info) goto retry_state_change; trace_state_change ("SUSPEND_INIT_REQUESTED", info, raw_state, cur_state, no_safepoints, 1); return ReqSuspendAlreadySuspendedBlocking; - + /* [1] It's questionable on what to do if we hit the beginning of a self suspend. @@ -435,7 +435,7 @@ Try to resume a suspended thread. Returns one of the following values: - Sucess: The thread was resumed. - Error: The thread was not suspended in the first place. [2] -- InitSelfResume: The thread is blocked on self suspend and should be resumed +- InitSelfResume: The thread is blocked on self suspend and should be resumed - InitAsyncResume: The thread is blocked on async suspend and should be resumed - ResumeInitBlockingResume: The thread was suspended on the exit path of blocking state and should be resumed FIXME: ResumeInitBlockingResume is just InitSelfResume by a different name. diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index fae0193050b9c..e7415532cbf09 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -37,15 +37,19 @@ wasm_get_stack_size (void) static int wasm_get_stack_base (void) { - g_assert_not_reached (); - return 0; + // TODO: For WASI, we need to ensure the stack location makes sense and won't interfere with the heap. + // Currently these hardcoded values are sufficient for a working prototype. It's an arbitrary nonzero + // value that aligns to 32 bits. + return 4; } static int wasm_get_stack_size (void) { - g_assert_not_reached (); - return 0; + // TODO: For WASI, we need to ensure the stack location makes sense and won't interfere with the heap. + // Currently these hardcoded values are sufficient for a working prototype. It's an arbitrary nonzero + // value that aligns to 32 bits. + return 4; } #endif @@ -201,8 +205,13 @@ mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) *stsize = wasm_get_stack_size (); #endif +#ifdef HOST_WASI + // TODO: For WASI, we need to ensure the stack is positioned correctly and reintroduce these assertions. + // Currently it works anyway in prototypes (except these checks would fail) +#else g_assert ((guint8*)&tmp > *staddr); g_assert ((guint8*)&tmp < (guint8*)*staddr + *stsize); +#endif } gboolean @@ -272,6 +281,8 @@ mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_d if (res != 0) g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); + return TRUE; +#elif defined(HOST_WASI) return TRUE; #else g_assert_not_reached (); diff --git a/src/mono/mono/utils/mono-threads.c b/src/mono/mono/utils/mono-threads.c index 233e89e48727f..e3a936a1abc3c 100644 --- a/src/mono/mono/utils/mono-threads.c +++ b/src/mono/mono/utils/mono-threads.c @@ -1616,8 +1616,13 @@ mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize) if (!*staddr) return; +#ifdef HOST_WASI + // TODO: Fix the stack positioning on WASI and re-enable the following check. + // Currently it works as a prototype anyway. +#else /* Sanity check the result */ g_assert ((current > *staddr) && (current < *staddr + *stsize)); +#endif #ifndef TARGET_WASM /* When running under emacs, sometimes staddr is not aligned to a page size */ diff --git a/src/mono/mono/utils/mono-threads.h b/src/mono/mono/utils/mono-threads.h index 4a29ab561e7f6..d0efd7d77c1c6 100644 --- a/src/mono/mono/utils/mono-threads.h +++ b/src/mono/mono/utils/mono-threads.h @@ -407,7 +407,7 @@ mono_thread_info_set_tid (THREAD_INFO_TYPE *info, MonoNativeThreadId tid) /* * @thread_info_size is sizeof (GcThreadInfo), a struct the GC defines to make it possible to have - * a single block with info from both camps. + * a single block with info from both camps. */ void mono_thread_info_init (size_t thread_info_size); @@ -647,8 +647,8 @@ mono_native_thread_id_main_thread_known (MonoNativeThreadId *main_thread_tid); /* * This does _not_ return the same value as mono_native_thread_id_get, except on Windows. * On POSIX, mono_native_thread_id_get returns the value from pthread_self, which is then - * passed around as an identifier to other pthread functions. However this function, where - * possible, returns the OS-unique thread id value, fetched in a platform-specific manner. + * passed around as an identifier to other pthread functions. However this function, where + * possible, returns the OS-unique thread id value, fetched in a platform-specific manner. * It will not work with the various pthread functions, should never be used as a * MonoNativeThreadId, and is intended solely to match the output of various diagonistic tools. */ diff --git a/src/mono/mono/utils/mono-uri.c b/src/mono/mono/utils/mono-uri.c index a39f6be3f0819..ed49c4c96bdb4 100644 --- a/src/mono/mono/utils/mono-uri.c +++ b/src/mono/mono/utils/mono-uri.c @@ -39,7 +39,7 @@ int main () { char *s = g_malloc (256); int i = 0; - + s [255] = 0; for (i = 1; i < 256; i++) diff --git a/src/mono/mono/utils/mono-utility-thread.c b/src/mono/mono/utils/mono-utility-thread.c index ce248018d1171..1c88040df35d3 100644 --- a/src/mono/mono/utils/mono-utility-thread.c +++ b/src/mono/mono/utils/mono-utility-thread.c @@ -22,7 +22,7 @@ typedef struct { MonoSemType *response_sem; // Variably-sized, size is thread->payload_size - gpointer payload [MONO_ZERO_LEN_ARRAY]; + gpointer payload [MONO_ZERO_LEN_ARRAY]; } UtilityThreadQueueEntry; static void @@ -38,7 +38,7 @@ utility_thread_handle_inbox (MonoUtilityThread *thread, gboolean at_shutdown) UtilityThreadQueueEntry *entry = (UtilityThreadQueueEntry *) mono_lock_free_queue_dequeue (&thread->work_queue); if (!entry) return FALSE; - + thread->callbacks.command (thread->state_ptr, &entry->payload, at_shutdown); if (entry->response_sem) { *entry->finished = TRUE; diff --git a/src/mono/mono/utils/mono-value-hash.c b/src/mono/mono/utils/mono-value-hash.c index 351df65443a69..42e2a9b6b3647 100644 --- a/src/mono/mono/utils/mono-value-hash.c +++ b/src/mono/mono/utils/mono-value-hash.c @@ -133,7 +133,7 @@ mono_value_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func, MonoV mono_value_hash_table_set_shift (hash, HASH_TABLE_MIN_SHIFT); hash->table = g_new0 (Slot, hash->table_size); - + return hash; } @@ -146,10 +146,10 @@ mono_value_hash_table_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, MonoValueHashTable *hash = mono_value_hash_table_new (hash_func, key_equal_func); if (hash == NULL) return NULL; - + hash->key_destroy_func = key_destroy_func; hash->value_destroy_func = value_destroy_func; - + return hash; } @@ -169,7 +169,7 @@ do_rehash (MonoValueHashTable *hash) /* printf ("New size: %d\n", hash->table_size); */ hash->table = g_new0 (Slot, hash->table_size); - + for (i = 0; i < old_size; i++){ Slot *s = &old_table [i]; Slot *new_s; @@ -222,7 +222,7 @@ mono_value_hash_table_insert_replace (MonoValueHashTable *hash, gpointer key, gp g_assert (value); g_assert (hash->key_extract_func (value) == key); - + g_return_if_fail (hash != NULL); hashcode = HASH (hash, key); @@ -282,7 +282,7 @@ lookup_internal (MonoValueHashTable *hash, gconstpointer key) guint hashcode; guint s_index; guint step = 0; - + hashcode = HASH (hash, key); s_index = hashcode & hash->table_mask; @@ -321,7 +321,7 @@ void mono_value_hash_table_destroy (MonoValueHashTable *hash) { int i; - + g_return_if_fail (hash != NULL); for (i = 0; i < hash->table_size; i++){ @@ -335,6 +335,6 @@ mono_value_hash_table_destroy (MonoValueHashTable *hash) } } g_free (hash->table); - + g_free (hash); } diff --git a/src/mono/mono/utils/mono-value-hash.h b/src/mono/mono/utils/mono-value-hash.h index 7702844ad9eea..27b9d95d4c262 100644 --- a/src/mono/mono/utils/mono-value-hash.h +++ b/src/mono/mono/utils/mono-value-hash.h @@ -17,7 +17,7 @@ /* * This is a hash table with the following features/restrictions: - * - Keys are not stored in the table, instead a function must be supplied which + * - Keys are not stored in the table, instead a function must be supplied which * computes them from the value. * - Values are assumed to be normal pointers, i.e. their lowest 2-3 bits should be * zero. @@ -27,7 +27,7 @@ * hash tables which store the key (or even the key hash) in the hash nodes. But * it also means that each hash node has a size of one machine word, instead of * 4 in GHashTable. - * - Removal of entries is not supported, as it is not needed by the runtime right + * - Removal of entries is not supported, as it is not needed by the runtime right * now. */ diff --git a/src/mono/mono/utils/monobitset.c b/src/mono/mono/utils/monobitset.c index ecbe76cd54f9c..db163b6a820bf 100644 --- a/src/mono/mono/utils/monobitset.c +++ b/src/mono/mono/utils/monobitset.c @@ -115,7 +115,7 @@ mono_bitset_test (const MonoBitSet *set, guint32 pos) { * mono_bitset_test_bulk: * \param set bitset ptr * \param pos test bit at this pos - * \returns 32/64 bits from the bitset, starting from \p pos, which must be + * \returns 32/64 bits from the bitset, starting from \p pos, which must be * divisible with 32/64. */ gsize @@ -190,7 +190,7 @@ mono_bitset_size (const MonoBitSet *set) { return set->size; } -/* +/* * should test wich version is faster. */ #if 1 @@ -251,7 +251,7 @@ mono_bitset_count (const MonoBitSet *set) { #endif #if 0 -const static int +const static int bitstart_mask [] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, @@ -283,7 +283,7 @@ my_g_bit_nth_lsf (gsize mask, gint nth_bit) int r; /* This depends on mask != 0 */ __asm__("bsfl %1,%0\n\t" - : "=r" (r) : "g" (mask)); + : "=r" (r) : "g" (mask)); return nth_bit + r; } #elif defined(__x86_64) && defined(__GNUC__) @@ -445,7 +445,7 @@ mono_bitset_find_last (const MonoBitSet *set, gint pos) { if (pos < 0) pos = set->size - 1; - + j = pos / BITS_PER_CHUNK; bit = pos % BITS_PER_CHUNK; @@ -656,10 +656,10 @@ mono_bitset_test_safe (const MonoBitSet *set, guint32 pos) #ifdef TEST_BITSET /* - * Compile with: + * Compile with: * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0` */ -int +int main() { MonoBitSet *set1, *set2, *set3, *set4; int error = 1; @@ -671,14 +671,14 @@ main() { if (mono_bitset_count (set1) != 0) return error; error++; - + mono_bitset_set (set1, 33); if (mono_bitset_count (set1) != 1) return error; error++; /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */ - + if (mono_bitset_find_first (set1, 0) != 33) return error; error++; @@ -804,7 +804,7 @@ main() { mono_bitset_free (set4); g_print ("total tests passed: %d\n", error - 1); - + return 0; } diff --git a/src/mono/mono/utils/monobitset.h b/src/mono/mono/utils/monobitset.h index 3e89eac3bc535..5a71dcb4a146b 100644 --- a/src/mono/mono/utils/monobitset.h +++ b/src/mono/mono/utils/monobitset.h @@ -75,7 +75,7 @@ MONO_API MonoBitSet* mono_bitset_new (guint32 max_size, guint32 flags); MONO_API MonoBitSet* mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags); -MONO_API void mono_bitset_free (MonoBitSet *set); +MONO_API void mono_bitset_free (MonoBitSet *set); MONO_API void mono_bitset_set (MonoBitSet *set, guint32 pos); diff --git a/src/mono/mono/utils/networking-fallback.c b/src/mono/mono/utils/networking-fallback.c index 1b31ae503c695..0c3b47adaf340 100644 --- a/src/mono/mono/utils/networking-fallback.c +++ b/src/mono/mono/utils/networking-fallback.c @@ -16,7 +16,7 @@ #include #endif -#if !defined (HAVE_GETADDRINFO) +#if !defined (HAVE_GETADDRINFO) #if defined (HAVE_GETHOSTBYNAME) || defined (HAVE_GETHOSTBYNAME2) @@ -71,7 +71,7 @@ mono_get_address_info (const char *hostname, int port, int flags, MonoAddressInf if (!addr_info->entries) { *result = NULL; mono_free_address_info (addr_info); - return 1; + return 1; } *result = addr_info; diff --git a/src/mono/mono/utils/networking-missing.c b/src/mono/mono/utils/networking-missing.c index 45ccf518a7db1..1f16b4121d7fe 100644 --- a/src/mono/mono/utils/networking-missing.c +++ b/src/mono/mono/utils/networking-missing.c @@ -25,17 +25,17 @@ inet_pton (int family, const char *address, void *inaddrp) if (family == AF_INET) { #ifdef HAVE_INET_ATON struct in_addr inaddr; - + if (!inet_aton (address, &inaddr)) return 0; - + memcpy (inaddrp, &inaddr, sizeof (struct in_addr)); return 1; #else /* assume the system has inet_addr(), if it doesn't have that we're pretty much screwed... */ guint32 inaddr; - + if (!strcmp (address, "255.255.255.255")) { /* special-case hack */ inaddr = 0xffffffff; @@ -47,12 +47,12 @@ inet_pton (int family, const char *address, void *inaddrp) if (inaddr == INADDR_NONE) return 0; } - + memcpy (inaddrp, &inaddr, sizeof (guint32)); return 1; #endif /* HAVE_INET_ATON */ } - + return -1; } diff --git a/src/mono/mono/utils/networking-posix.c b/src/mono/mono/utils/networking-posix.c index e307a728fa36d..64d7a5d8a8d67 100644 --- a/src/mono/mono/utils/networking-posix.c +++ b/src/mono/mono/utils/networking-posix.c @@ -112,7 +112,7 @@ mono_get_address_info (const char *hostname, int port, int flags, MonoAddressInf if (cur->family == PF_INET) { cur->address_len = sizeof (struct in_addr); cur->address.v4 = ((struct sockaddr_in*)res->ai_addr)->sin_addr; -#ifdef HAVE_STRUCT_SOCKADDR_IN6 +#ifdef HAVE_STRUCT_SOCKADDR_IN6 } else if (cur->family == PF_INET6) { cur->address_len = sizeof (struct in6_addr); cur->address.v6 = ((struct sockaddr_in6*)res->ai_addr)->sin6_addr; @@ -131,7 +131,7 @@ mono_get_address_info (const char *hostname, int port, int flags, MonoAddressInf prev->next = cur; else addr_info->entries = cur; - + prev = cur; res = res->ai_next; } @@ -174,6 +174,15 @@ fetch_protocol (const char *proto_name, int *cache, int *proto, int default_val) return *proto; } +#elif defined(HOST_WASI) + +static int +fetch_protocol (const char *proto_name, int *cache, int *proto, int default_val) +{ + g_critical("fetch_protocol is not implemented on WASI\n"); + return 0; +} + #endif int diff --git a/src/mono/mono/utils/strenc.c b/src/mono/mono/utils/strenc.c index bb383e10eca2f..f6eb0f4b898c8 100644 --- a/src/mono/mono/utils/strenc.c +++ b/src/mono/mono/utils/strenc.c @@ -50,16 +50,16 @@ gunichar2 *mono_unicode_from_external (const gchar *in, gsize *bytes) gchar *encoding_list; int i; glong lbytes; - + if(in==NULL) { return(NULL); } - + encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS"); if(encoding_list==NULL) { encoding_list = g_strdup(""); } - + encodings=g_strsplit (encoding_list, ":", 0); g_free (encoding_list); for(i=0;encodings[i]!=NULL; i++) { @@ -88,9 +88,9 @@ gunichar2 *mono_unicode_from_external (const gchar *in, gsize *bytes) return((gunichar2 *)res); } } - + g_strfreev (encodings); - + if(g_utf8_validate (in, -1, NULL)) { glong items_written; gunichar2 *unires=g_utf8_to_utf16 (in, -1, NULL, &items_written, NULL); @@ -125,20 +125,20 @@ gchar *mono_utf8_from_external (const gchar *in) gchar **encodings; gchar *encoding_list; int i; - + if(in==NULL) { return(NULL); } - + encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS"); if(encoding_list==NULL) { encoding_list = g_strdup(""); } - + encodings=g_strsplit (encoding_list, ":", 0); g_free (encoding_list); for(i=0;encodings[i]!=NULL; i++) { - + /* "default_locale" is a special case encoding */ if(!strcmp (encodings[i], "default_locale")) { res=g_locale_to_utf8 (in, -1, NULL, NULL, NULL); @@ -156,9 +156,9 @@ gchar *mono_utf8_from_external (const gchar *in) return(res); } } - + g_strfreev (encodings); - + if(g_utf8_validate (in, -1, NULL)) { return(g_strdup (in)); } @@ -184,7 +184,7 @@ gchar *mono_unicode_to_external_checked (const gunichar2 *uni, MonoError *err) gchar *utf8; gchar *encoding_list; GError *gerr = NULL; - + /* Turn the unicode into utf8 to start with, because its * easier to work with gchar * than gunichar2 * */ @@ -194,7 +194,7 @@ gchar *mono_unicode_to_external_checked (const gunichar2 *uni, MonoError *err) g_error_free (gerr); return utf8; } - + encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS"); if(encoding_list==NULL) { /* Do UTF8 */ @@ -202,7 +202,7 @@ gchar *mono_unicode_to_external_checked (const gunichar2 *uni, MonoError *err) } else { gchar *res, **encodings; int i; - + encodings=g_strsplit (encoding_list, ":", 0); g_free (encoding_list); for(i=0; encodings[i]!=NULL; i++) { @@ -217,14 +217,14 @@ gchar *mono_unicode_to_external_checked (const gunichar2 *uni, MonoError *err) if(res!=NULL) { g_free (utf8); g_strfreev (encodings); - + return(res); } } - + g_strfreev (encodings); } - + /* Nothing else worked, so just return the utf8 */ return(utf8); } @@ -333,7 +333,7 @@ mono_utf8_validate_and_len_with_bounds (const gchar *source, glong max_bytes, gl while (*ptr != 0) { length = trailingBytesForUTF8 [*ptr] + 1; srcPtr = (guchar*) ptr + length; - + /* since *ptr is not zero we must ensure that we can decode the current char + the byte after srcPtr points to the first byte after the current char.*/ if (srcPtr >= end) { diff --git a/src/mono/mono/utils/valgrind.h b/src/mono/mono/utils/valgrind.h index 0829ac748b7c6..070617915864c 100644 --- a/src/mono/mono/utils/valgrind.h +++ b/src/mono/mono/utils/valgrind.h @@ -21,16 +21,16 @@ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS @@ -52,13 +52,13 @@ the terms of the GNU General Public License, version 2. See the COPYING file in the source distribution for details. - ---------------------------------------------------------------- + ---------------------------------------------------------------- */ /* This file is for inclusion into client (your!) code. - You can use these macros to manipulate and query Valgrind's + You can use these macros to manipulate and query Valgrind's execution inside your own programs. The resulting executables will still run without Valgrind, just a @@ -222,8 +222,8 @@ this is executed not under Valgrind. Args are passed in a memory block, and so there's no intrinsic limit to the number that could be passed, but it's currently five. - - The macro args are: + + The macro args are: _zzq_rlval result lvalue _zzq_default default value (result returned when running on real CPU) _zzq_request request code @@ -250,7 +250,7 @@ || (defined(PLAT_x86_win32) && defined(__GNUC__)) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -314,7 +314,7 @@ typedef #if defined(PLAT_x86_win32) && !defined(__GNUC__) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -388,7 +388,7 @@ valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request, || (defined(PLAT_amd64_win64) && defined(__GNUC__)) typedef - struct { + struct { unsigned long long int nraddr; /* where's the code? */ } OrigFn; @@ -460,7 +460,7 @@ typedef #if defined(PLAT_ppc32_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -529,7 +529,7 @@ typedef #if defined(PLAT_ppc64be_linux) typedef - struct { + struct { unsigned long long int nraddr; /* where's the code? */ unsigned long long int r2; /* what tocptr do we need? */ } @@ -685,7 +685,7 @@ typedef #if defined(PLAT_arm_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -753,7 +753,7 @@ typedef #if defined(PLAT_arm64_linux) typedef - struct { + struct { unsigned long long int nraddr; /* where's the code? */ } OrigFn; @@ -898,7 +898,7 @@ typedef #if defined(PLAT_mips32_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -912,7 +912,7 @@ typedef "srl $0, $0, 29\n\t" \ "srl $0, $0, 3\n\t" \ "srl $0, $0, 19\n\t" - + #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ _zzq_default, _zzq_request, \ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ @@ -2161,7 +2161,7 @@ typedef #define VALGRIND_RESTORE_STACK \ "mr 1,28\n\t" -/* These CALL_FN_ macros assume that on ppc32-linux, +/* These CALL_FN_ macros assume that on ppc32-linux, sizeof(unsigned long) == 4. */ #define CALL_FN_W_v(lval, orig) \ @@ -4678,7 +4678,7 @@ typedef #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \ "f0","f1","f2","f3","f4","f5","f6","f7" -/* Nb: Although r11 is modified in the asm snippets below (inside +/* Nb: Although r11 is modified in the asm snippets below (inside VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for two reasons: (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not @@ -5128,7 +5128,7 @@ typedef #endif /* PLAT_s390x_linux */ /* ------------------------- mips32-linux ----------------------- */ - + #if defined(PLAT_mips32_linux) /* These regs are trashed by the hidden call. */ @@ -6104,7 +6104,7 @@ typedef #define VG_IS_TOOL_USERREQ(a, b, v) \ (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! This enum comprises an ABI exported by Valgrind to programs which use client requests. DO NOT CHANGE THE ORDER OF THESE ENTRIES, NOR DELETE ANY -- add new ones at the end. */ @@ -6242,7 +6242,7 @@ VALGRIND_PRINTF(const char *format, ...) _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRINTF_VALIST_BY_REF, (unsigned long)format, - (unsigned long)&vargs, + (unsigned long)&vargs, 0, 0, 0); #endif va_end(vargs); @@ -6280,7 +6280,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, (unsigned long)format, - (unsigned long)&vargs, + (unsigned long)&vargs, 0, 0, 0); #endif va_end(vargs); @@ -6291,7 +6291,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* These requests allow control to move from the simulated CPU to the real CPU, calling an arbitary function. - + Note that the current ThreadId is inserted as the first argument. So this call: @@ -6377,7 +6377,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) - It marks the block as being addressable and undefined (if 'is_zeroed' is not set), or addressable and defined (if 'is_zeroed' is set). This controls how accesses to the block by the program are handled. - + 'addr' is the start of the usable block (ie. after any redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator can apply redzones -- these are blocks of padding at the start and end of @@ -6385,7 +6385,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) Valgrind will spot block overruns. `is_zeroed' indicates if the memory is zeroed (or filled with another predictable value), as is the case for calloc(). - + VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a heap block -- that will be used by the client program -- is allocated. It's best to put it at the outermost level of the allocator if possible; diff --git a/src/mono/sample/wasm/wasm.mk b/src/mono/sample/wasm/wasm.mk index 89759c3c7745c..ea466c3f225b9 100644 --- a/src/mono/sample/wasm/wasm.mk +++ b/src/mono/sample/wasm/wasm.mk @@ -10,6 +10,15 @@ CONFIG?=Release WASM_DEFAULT_BUILD_ARGS?=/p:TargetArchitecture=wasm /p:TargetOS=Browser /p:Configuration=$(CONFIG) +# if we're in a container, don't try to open the browser +ifneq ("$(wildcard /.dockerenv)", "") + OPEN_BROWSER= + V8_PATH=v8 +else + OPEN_BROWSER=-o + V8_PATH=~/.jsvu/v8 +endif + all: publish build: @@ -22,15 +31,15 @@ clean: rm -rf bin $(TOP)/artifacts/obj/mono/$(PROJECT_NAME:%.csproj=%) run-browser: - if ! $(DOTNET) tool list --global | grep dotnet-serve; then \ + if ! $(DOTNET) tool list --global | grep dotnet-serve && ! which dotnet-serve ; then \ echo "The tool dotnet-serve could not be found. Install with: $(DOTNET) tool install --global dotnet-serve"; \ exit 1; \ else \ - $(DOTNET) serve -d:bin/$(CONFIG)/AppBundle -o -p:8000; \ + $(DOTNET) serve -d:bin/$(CONFIG)/AppBundle $(OPEN_BROWSER) -p:8000; \ fi run-console: - cd bin/$(CONFIG)/AppBundle && ~/.jsvu/v8 --stack-trace-limit=1000 --single-threaded --expose_wasm $(MAIN_JS) -- $(DOTNET_MONO_LOG_LEVEL) --run $(CONSOLE_DLL) $(ARGS) + cd bin/$(CONFIG)/AppBundle && $(V8_PATH) --stack-trace-limit=1000 --single-threaded --expose_wasm $(MAIN_JS) -- $(DOTNET_MONO_LOG_LEVEL) --run $(CONSOLE_DLL) $(ARGS) run-console-node: cd bin/$(CONFIG)/AppBundle && node --stack-trace-limit=1000 --single-threaded --expose_wasm $(MAIN_JS) -- $(DOTNET_MONO_LOG_LEVEL) --run $(CONSOLE_DLL) $(ARGS) diff --git a/src/mono/wasi/Makefile b/src/mono/wasi/Makefile new file mode 100644 index 0000000000000..d537988471eb8 --- /dev/null +++ b/src/mono/wasi/Makefile @@ -0,0 +1,29 @@ +include Makefile.variable + +all: build-all + +build-all: $(WASI_SDK_CLANG) + mkdir -p $(WASI_OBJ_DIR) + cd $(WASI_OBJ_DIR) && \ + cmake -G Ninja \ + -DWASI_SDK_PREFIX=$(WASI_SDK_ROOT) \ + -DCMAKE_SYSROOT=$(WASI_SDK_ROOT)/share/wasi-sysroot \ + -DCMAKE_TOOLCHAIN_FILE=$(WASI_SDK_ROOT)/share/cmake/wasi-sdk.cmake \ + -DCMAKE_C_FLAGS="--sysroot=$(WASI_SDK_ROOT)/share/wasi-sysroot -I$(CURDIR)/include -I$(TOP)/src/mono" \ + -DCMAKE_CXX_FLAGS="--sysroot=$(WASI_SDK_ROOT)/share/wasi-sysroot" \ + -DENABLE_MINIMAL=jit,sgen_major_marksweep_conc,sgen_split_nursery,sgen_gc_bridge,sgen_toggleref,sgen_debug_helpers,sgen_binary_protocol,logging,shared_perfcounters,interpreter,threads,qcalls,debugger_agent,sockets,eventpipe \ + -DDISABLE_SHARED_LIBS=1 \ + -Wl,--allow-undefined \ + $(TOP)/src/mono + cd $(WASI_OBJ_DIR) && ninja + + mkdir -p $(WASI_BIN_DIR) + cp $(WASI_OBJ_DIR)/mono/mini/*.a $(WASI_OBJ_DIR)/libmono-wasi-driver.a $(WASI_BIN_DIR) + mkdir -p $(WASI_BIN_DIR)/include/mono-wasi + cp mono-wasi-driver/*.h $(WASI_BIN_DIR)/include/mono-wasi + +$(WASI_SDK_CLANG): + mkdir -p $(WASI_OBJ_DIR) + cd $(WASI_OBJ_DIR) && \ + wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$(WASI_SDK_VERSION)/wasi-sdk-$(WASI_SDK_VERSION).0-linux.tar.gz && \ + tar xf wasi-sdk-*.tar.gz diff --git a/src/mono/wasi/Makefile.variable b/src/mono/wasi/Makefile.variable new file mode 100644 index 0000000000000..fb1d6d5a6e5de --- /dev/null +++ b/src/mono/wasi/Makefile.variable @@ -0,0 +1,8 @@ +TOP=$(realpath $(CURDIR)/../../..) +CONFIG?=Release +WASI_SDK_VERSION=12 + +WASI_OBJ_DIR=$(TOP)/artifacts/obj/mono/Wasi.$(CONFIG) +WASI_BIN_DIR=$(TOP)/artifacts/bin/mono/Wasi.$(CONFIG) +WASI_SDK_ROOT=$(WASI_OBJ_DIR)/wasi-sdk-$(WASI_SDK_VERSION).0 +WASI_SDK_CLANG=$(WASI_SDK_ROOT)/bin/clang diff --git a/src/mono/wasi/README.md b/src/mono/wasi/README.md new file mode 100644 index 0000000000000..b4037f7701593 --- /dev/null +++ b/src/mono/wasi/README.md @@ -0,0 +1,52 @@ +# Prototype WASI support + +This directory contains a build configuration for WASI support, plus a basic sample. This is not intended for production use, nor is it currently supported. This is a step towards possible future support. + +## How it works + +The mechanism for executing .NET code in a WASI runtime environment is equivalent to how `dotnet.wasm` executes .NET code in a browser environment. That is, it runs the Mono interpreter to execute .NET bytecode that has been built in the normal way. It should also work with AOT but this is not yet attempted. + +## How to build the runtime + +Currently this can only be built in Linux or WSL (tested on Windows 11). Simply run `make` in this directory. It will automatically download and use [WASI SDK](https://github.com/WebAssembly/wasi-sdk). + +The resulting libraries are placed in `(repo_root)/artifacts/bin/mono/Wasi.Release`. + +## How to build and run the sample + +### 1. Obtain a WASI runtime + +To run an application in a WASI environment, you need to have a WASI runtime available. For example, download [wasmtime](https://github.com/bytecodealliance/wasmtime/releases) and make sure it's available on `PATH`: + +``` +export PATH=~/wasmtime-v0.31.0-x86_64-linux +wasmtime --version +``` + +Other WASI runtimes also work. Tested: [wamr](https://github.com/bytecodealliance/wasm-micro-runtime), [wasmer](https://wasmer.io/). + +### 2. Obtain a suitable .NET build toolchain + +You also need to have a working installation of .NET 7 including the `browser-wasm` runtime pack. For example, obtain the [.NET SDK daily build](https://github.com/dotnet/installer/blob/main/README.md#installers-and-binaries) (`main` branch), and ensure the `browser-wasm` pack is installed: + +``` +dotnet workload install wasm-tools -s https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json +``` + +To make this available to the build scripts, supply environment variables. Example: + +``` +export DOTNET_ROOT=~/dotnet7 +export BROWSER_WASM_RUNTIME_PATH=$(DOTNET_ROOT)/packs/Microsoft.NETCore.App.Runtime.Mono.browser-wasm/7.0.0-alpha.1.22061.11/runtimes/browser-wasm +``` + +You'll need to update these paths to match the location where you extracted the .NET daily SDK build and the exact version of the `browser-wasm` pack you received. + +### 3. Run it + +Finally, you can build and run the sample: + +``` +cd samples/console +make run +``` diff --git a/src/mono/wasi/include/pthread.h b/src/mono/wasi/include/pthread.h new file mode 100644 index 0000000000000..a5ea63882e7b9 --- /dev/null +++ b/src/mono/wasi/include/pthread.h @@ -0,0 +1,230 @@ +// This file is multi-licensed: +// Apache-2.0: https://github.com/WebAssembly/wasi-libc/blob/main/LICENSE-APACHE +// MIT: https://github.com/WebAssembly/wasi-libc/blob/main/LICENSE-MIT + +// This file is duplicated from https://github.com/WebAssembly/wasi-libc/blob/ad5133410f66b93a2381db5b542aad5e0964db96/libc-top-half/musl/include/pthread.h +// with small edits for compatibility. We may be able to remove it once https://github.com/WebAssembly/wasi-libc/issues/209 is resolved + +// The WASI SDK doesn't include pthread.h, but the definitions are required by various parts of the Mono sources +// On certain runtimes such as WAMR there is actually an implementation provided for the pthread APIs so threading +// does work. However that's not yet in the WASI standard, so we're not yet relying on being able to call the ones +// that really start up new threads. + +#ifndef _PTHREAD_H +#define _PTHREAD_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t +#define __NEED_clockid_t +#define __NEED_struct_timespec +#define __NEED_sigset_t +#define __NEED_pthread_t +#define __NEED_pthread_attr_t +#define __NEED_pthread_mutexattr_t +#define __NEED_pthread_condattr_t +#define __NEED_pthread_rwlockattr_t +#define __NEED_pthread_barrierattr_t +#define __NEED_pthread_mutex_t +#define __NEED_pthread_cond_t +#define __NEED_pthread_rwlock_t +#define __NEED_pthread_barrier_t +#define __NEED_pthread_spinlock_t +#define __NEED_pthread_key_t +#define __NEED_pthread_once_t +#define __NEED_size_t + +#include + +#include +#include + +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_CREATE_DETACHED 1 + +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_DEFAULT 0 +#define PTHREAD_MUTEX_RECURSIVE 1 +#define PTHREAD_MUTEX_ERRORCHECK 2 + +#define PTHREAD_MUTEX_STALLED 0 +#define PTHREAD_MUTEX_ROBUST 1 + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 + +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_EXPLICIT_SCHED 1 + +#define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_SCOPE_PROCESS 1 + +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + + +#define PTHREAD_MUTEX_INITIALIZER {{{0}}} +#define PTHREAD_RWLOCK_INITIALIZER {{{0}}} +#define PTHREAD_COND_INITIALIZER {{{0}}} +#define PTHREAD_ONCE_INIT 0 + + +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_MASKED 2 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCELED ((void *)-1) + + +#define PTHREAD_BARRIER_SERIAL_THREAD (-1) + +struct sched_param; +#define PTHREAD_NULL ((pthread_t)0) + +int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); +int pthread_detach(pthread_t); +_Noreturn void pthread_exit(void *); +int pthread_join(pthread_t, void **); + +pthread_t pthread_self(void); + +int pthread_equal(pthread_t, pthread_t); +#ifndef __cplusplus +#define pthread_equal(x,y) ((x)==(y)) +#endif + +int pthread_setcancelstate(int, int *); +int pthread_setcanceltype(int, int *); +void pthread_testcancel(void); +int pthread_cancel(pthread_t); + +int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict); +int pthread_setschedparam(pthread_t, int, const struct sched_param *); +int pthread_setschedprio(pthread_t, int); + +int pthread_once(pthread_once_t *, void (*)(void)); + +int pthread_mutex_init(pthread_mutex_t *__restrict, const pthread_mutexattr_t *__restrict); +int pthread_mutex_lock(pthread_mutex_t *); +int pthread_mutex_unlock(pthread_mutex_t *); +int pthread_mutex_trylock(pthread_mutex_t *); +int pthread_mutex_timedlock(pthread_mutex_t *__restrict, const struct timespec *__restrict); +int pthread_mutex_destroy(pthread_mutex_t *); +int pthread_mutex_consistent(pthread_mutex_t *); + +int pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict, int *__restrict); +int pthread_mutex_setprioceiling(pthread_mutex_t *__restrict, int, int *__restrict); + +int pthread_cond_init(pthread_cond_t *__restrict, const pthread_condattr_t *__restrict); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_wait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict); +int pthread_cond_timedwait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict, const struct timespec *__restrict); +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_cond_signal(pthread_cond_t *); + +int pthread_rwlock_init(pthread_rwlock_t *__restrict, const pthread_rwlockattr_t *__restrict); +int pthread_rwlock_destroy(pthread_rwlock_t *); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlock_trywrlock(pthread_rwlock_t *); +int pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict); +int pthread_rwlock_unlock(pthread_rwlock_t *); + +int pthread_spin_init(pthread_spinlock_t *, int); +int pthread_spin_destroy(pthread_spinlock_t *); +int pthread_spin_lock(pthread_spinlock_t *); +int pthread_spin_trylock(pthread_spinlock_t *); +int pthread_spin_unlock(pthread_spinlock_t *); + +int pthread_barrier_init(pthread_barrier_t *__restrict, const pthread_barrierattr_t *__restrict, unsigned); +int pthread_barrier_destroy(pthread_barrier_t *); +int pthread_barrier_wait(pthread_barrier_t *); + +int pthread_key_create(pthread_key_t *, void (*)(void *)); +int pthread_key_delete(pthread_key_t); +void *pthread_getspecific(pthread_key_t); +int pthread_setspecific(pthread_key_t, const void *); + +int pthread_attr_init(pthread_attr_t *); +int pthread_attr_destroy(pthread_attr_t *); + +int pthread_attr_getguardsize(const pthread_attr_t *__restrict, size_t *__restrict); +int pthread_attr_setguardsize(pthread_attr_t *, size_t); +int pthread_attr_getstacksize(const pthread_attr_t *__restrict, size_t *__restrict); +int pthread_attr_setstacksize(pthread_attr_t *, size_t); +int pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int pthread_attr_setdetachstate(pthread_attr_t *, int); +int pthread_attr_getstack(const pthread_attr_t *__restrict, void **__restrict, size_t *__restrict); +int pthread_attr_setstack(pthread_attr_t *, void *, size_t); +int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setscope(pthread_attr_t *, int); +int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setschedpolicy(pthread_attr_t *, int); +int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict); +int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict); +int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setinheritsched(pthread_attr_t *, int); + +int pthread_mutexattr_destroy(pthread_mutexattr_t *); +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getrobust(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_init(pthread_mutexattr_t *); +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int); +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int); +int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); +int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int); +int pthread_mutexattr_settype(pthread_mutexattr_t *, int); + +int pthread_condattr_init(pthread_condattr_t *); +int pthread_condattr_destroy(pthread_condattr_t *); +int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); +int pthread_condattr_setpshared(pthread_condattr_t *, int); +int pthread_condattr_getclock(const pthread_condattr_t *__restrict, clockid_t *__restrict); +int pthread_condattr_getpshared(const pthread_condattr_t *__restrict, int *__restrict); + +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict, int *__restrict); + +int pthread_barrierattr_destroy(pthread_barrierattr_t *); +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict, int *__restrict); +int pthread_barrierattr_init(pthread_barrierattr_t *); +int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); + +int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); + +int pthread_getconcurrency(void); +int pthread_setconcurrency(int); + +int pthread_getcpuclockid(pthread_t, clockid_t *); + +struct __ptcb { + void (*__f)(void *); + void *__x; + struct __ptcb *__next; +}; + +void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *); +void _pthread_cleanup_pop(struct __ptcb *, int); + +#define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); +#define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/mono/wasi/include/setjmp.h b/src/mono/wasi/include/setjmp.h new file mode 100644 index 0000000000000..5fd8fd2380818 --- /dev/null +++ b/src/mono/wasi/include/setjmp.h @@ -0,0 +1,2 @@ +// setjmp.h isn't provided by WASI SDK, but many Mono source files want to import it, so we need this here +// We don't call any of its symbols at runtime so it can be left empty diff --git a/src/mono/wasi/mono-wasi-driver/driver.c b/src/mono/wasi/mono-wasi-driver/driver.c new file mode 100644 index 0000000000000..cadbcbd4aebc4 --- /dev/null +++ b/src/mono/wasi/mono-wasi-driver/driver.c @@ -0,0 +1,624 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include +#include +#include +#include +#include +#include + +#define INVARIANT_GLOBALIZATION 1 + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "wasm/runtime/pinvoke.h" + +void mono_wasm_enable_debugging (int); + +int mono_wasm_register_root (char *start, size_t size, const char *name); +void mono_wasm_deregister_root (char *addr); + +void mono_ee_interp_init (const char *opts); +void mono_marshal_ilgen_init (void); +void mono_method_builder_ilgen_init (void); +void mono_sgen_mono_ilgen_init (void); +void mono_icall_table_init (void); +void mono_aot_register_module (void **aot_info); +char *monoeg_g_getenv(const char *variable); +int monoeg_g_setenv(const char *variable, const char *value, int overwrite); +int32_t monoeg_g_hasenv(const char *variable); +void mono_free (void*); +int32_t mini_parse_debug_option (const char *option); +char *mono_method_get_full_name (MonoMethod *method); + +int mono_wasm_enable_gc = 1; + +int +mono_string_instance_is_interned (MonoString *str_raw); + +void mono_trace_init (void); + +#define g_new(type, size) ((type *) malloc (sizeof (type) * (size))) +#define g_new0(type, size) ((type *) calloc (sizeof (type), (size))) + +static MonoDomain *root_domain; + +#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin" + +static void +wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) +{ + printf("[wasm_trace_logger] %s\n", message); + if (fatal) + exit (1); +} + +typedef uint32_t target_mword; +typedef target_mword SgenDescriptor; +typedef SgenDescriptor MonoGCDescriptor; + +typedef struct WasmAssembly_ WasmAssembly; + +struct WasmAssembly_ { + MonoBundledAssembly assembly; + WasmAssembly *next; +}; + +static WasmAssembly *assemblies; +static int assembly_count; + +int +mono_wasm_add_assembly (const char *name, const unsigned char *data, unsigned int size) +{ + int len = strlen (name); + if (!strcasecmp (".pdb", &name [len - 4])) { + char *new_name = strdup (name); + //FIXME handle debugging assemblies with .exe extension + strcpy (&new_name [len - 3], "dll"); + mono_register_symfile_for_assembly (new_name, data, size); + return 1; + } + WasmAssembly *entry = g_new0 (WasmAssembly, 1); + entry->assembly.name = strdup (name); + entry->assembly.data = data; + entry->assembly.size = size; + entry->next = assemblies; + assemblies = entry; + ++assembly_count; + return mono_has_pdb_checksum ((char*)data, size); +} + +typedef struct WasmSatelliteAssembly_ WasmSatelliteAssembly; + +struct WasmSatelliteAssembly_ { + MonoBundledSatelliteAssembly *assembly; + WasmSatelliteAssembly *next; +}; + +static WasmSatelliteAssembly *satellite_assemblies; +static int satellite_assembly_count; + +void +mono_wasm_add_satellite_assembly (const char *name, const char *culture, const unsigned char *data, unsigned int size) +{ + WasmSatelliteAssembly *entry = g_new0 (WasmSatelliteAssembly, 1); + entry->assembly = mono_create_new_bundled_satellite_assembly (name, culture, data, size); + entry->next = satellite_assemblies; + satellite_assemblies = entry; + ++satellite_assembly_count; +} + +void +mono_wasm_setenv (const char *name, const char *value) +{ + monoeg_g_setenv (strdup (name), strdup (value), 1); +} + +static void *sysglobal_native_handle; +int32_t SystemNative_LChflagsCanSetHiddenFlag(void); +char* SystemNative_GetEnv(char* name); +intptr_t SystemNative_Dup(intptr_t oldfd); +int32_t SystemNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize); +int64_t SystemNative_GetSystemTimeAsTicks(); +int32_t SystemNative_LStat(const char* path, int output); +int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno); +void* SystemNative_LowLevelMonitor_Create(); +void SystemNative_LowLevelMonitor_Acquire(void* monitor); +void SystemNative_LowLevelMonitor_Release(void* monitor); +int32_t SystemNative_LowLevelMonitor_TimedWait(void *monitor, int32_t timeoutMilliseconds); +void SystemNative_LowLevelMonitor_Wait(void* monitor); +int SystemNative_GetErrNo(); +void SystemNative_SetErrNo(int value); + +int32_t SystemNative_Write2(intptr_t fd, const void* buffer, int32_t bufferSize) { + // Not sure why, but am getting fd=-1 when trying to write to stdout (which fails), so here's a workaround + return SystemNative_Write((int)fd == -1 ? 1: fd, buffer, bufferSize); +} + +static PinvokeImport SystemNativeImports [] = { + {"SystemNative_GetEnv", SystemNative_GetEnv }, + {"SystemNative_LChflagsCanSetHiddenFlag", SystemNative_LChflagsCanSetHiddenFlag }, + {"SystemNative_Dup", SystemNative_Dup}, + {"SystemNative_Write", SystemNative_Write2}, + {"SystemNative_GetSystemTimeAsTicks", SystemNative_GetSystemTimeAsTicks}, + {"SystemNative_LStat", SystemNative_LStat}, + {"SystemNative_ConvertErrorPlatformToPal", SystemNative_ConvertErrorPlatformToPal}, + {"SystemNative_LowLevelMonitor_Create", SystemNative_LowLevelMonitor_Create}, + {"SystemNative_LowLevelMonitor_Acquire", SystemNative_LowLevelMonitor_Acquire}, + {"SystemNative_LowLevelMonitor_Release", SystemNative_LowLevelMonitor_Release}, + {"SystemNative_LowLevelMonitor_TimedWait", SystemNative_LowLevelMonitor_TimedWait}, + {"SystemNative_LowLevelMonitor_Wait", SystemNative_LowLevelMonitor_Wait}, + {"SystemNative_GetErrNo", SystemNative_GetErrNo}, + {"SystemNative_SetErrNo", SystemNative_SetErrNo}, + {NULL, NULL} +}; + +void GlobalizationNative_LoadICU() { + assert(0); +} + +static PinvokeImport SystemGlobalizationNativeImports [] = { + {"GlobalizationNative_LoadICU", GlobalizationNative_LoadICU }, + {NULL, NULL} +}; + +static void* +wasm_dl_load (const char *name, int flags, char **err, void *user_data) +{ + if (!strcmp (name, "libSystem.Native")) + return SystemNativeImports; + if (!strcmp (name, "libSystem.Globalization.Native")) + return SystemGlobalizationNativeImports; + //printf("In wasm_dl_load for name %s but treating as NOT FOUND\n", name); + return 0; +} + +static void* +wasm_dl_symbol (void *handle, const char *name, char **err, void *user_data) +{ + if (handle == sysglobal_native_handle) + assert (0); + + PinvokeImport *table = (PinvokeImport*)handle; + for (int i = 0; table [i].name; ++i) { + if (!strcmp (table [i].name, name)) + return table [i].func; + } + return NULL; +} + +#define NEED_INTERP 1 + +/* + * get_native_to_interp: + * + * Return a pointer to a wasm function which can be used to enter the interpreter to + * execute METHOD from native code. + * EXTRA_ARG is the argument passed to the interp entry functions in the runtime. + */ +void* +get_native_to_interp (MonoMethod *method, void *extra_arg) +{ + MonoClass *klass = mono_method_get_class (method); + MonoImage *image = mono_class_get_image (klass); + MonoAssembly *assembly = mono_image_get_assembly (image); + MonoAssemblyName *aname = mono_assembly_get_name (assembly); + const char *name = mono_assembly_name_get_name (aname); + const char *class_name = mono_class_get_name (klass); + const char *method_name = mono_method_get_name (method); + char key [128]; + int len; + + assert (strlen (name) < 100); + snprintf (key, sizeof(key), "%s_%s_%s", name, class_name, method_name); + len = strlen (key); + for (int i = 0; i < len; ++i) { + if (key [i] == '.') + key [i] = '_'; + } + + assert(0); return 0; + //void *addr = wasm_dl_get_native_to_interp (key, extra_arg); + //return addr; +} + +void +mono_wasm_register_bundled_satellite_assemblies () +{ + /* In legacy satellite_assembly_count is always false */ + if (satellite_assembly_count) { + MonoBundledSatelliteAssembly **satellite_bundle_array = g_new0 (MonoBundledSatelliteAssembly *, satellite_assembly_count + 1); + WasmSatelliteAssembly *cur = satellite_assemblies; + int i = 0; + while (cur) { + satellite_bundle_array [i] = cur->assembly; + cur = cur->next; + ++i; + } + mono_register_bundled_satellite_assemblies ((const MonoBundledSatelliteAssembly **)satellite_bundle_array); + } +} + +void +cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data) +{ + free (args); + free (user_data); +} + +void +mono_wasm_load_runtime (const char *unused, int debug_level) +{ + const char *interp_opts = ""; + +#ifndef INVARIANT_GLOBALIZATION + mono_wasm_link_icu_shim (); +#else + monoeg_g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "true", 1); +#endif + +#ifdef DEBUG + monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 0); + monoeg_g_setenv ("MONO_LOG_MASK", "gc", 0); + // Setting this env var allows Diagnostic.Debug to write to stderr. In a browser environment this + // output will be sent to the console. Right now this is the only way to emit debug logging from + // corlib assemblies. + monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0); +#endif + // When the list of app context properties changes, please update RuntimeConfigReservedProperties for + // target _WasmGenerateRuntimeConfig in WasmApp.targets file + const char *appctx_keys[2]; + appctx_keys [0] = "APP_CONTEXT_BASE_DIRECTORY"; + appctx_keys [1] = "RUNTIME_IDENTIFIER"; + + const char *appctx_values[2]; + appctx_values [0] = "/"; + appctx_values [1] = "browser-wasm"; + + char *file_name = RUNTIMECONFIG_BIN_FILE; + int str_len = strlen (file_name) + 1; // +1 is for the "/" + char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character + int num_char = snprintf (file_path, (str_len + 1), "/%s", file_name); + struct stat buffer; + + assert (num_char > 0 && num_char == str_len); + + if (stat (file_path, &buffer) == 0) { + MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments)); + arg->kind = 0; + arg->runtimeconfig.name.path = file_path; + monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path); + } else { + free (file_path); + } + + monovm_initialize (2, appctx_keys, appctx_values); + + mini_parse_debug_option ("top-runtime-invoke-unhandled"); + + mono_dl_fallback_register (wasm_dl_load, wasm_dl_symbol, NULL, NULL); + mono_wasm_install_get_native_to_interp_tramp (get_native_to_interp); + + mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_ONLY); + + /* + * debug_level > 0 enables debugging and sets the debug log level to debug_level + * debug_level == 0 disables debugging and enables interpreter optimizations + * debug_level < 0 enabled debugging and disables debug logging. + * + * Note: when debugging is enabled interpreter optimizations are disabled. + */ + if (debug_level) { + // Disable optimizations which interfere with debugging + interp_opts = "-all"; + mono_wasm_enable_debugging (debug_level); + } + + mono_ee_interp_init (interp_opts); + mono_marshal_ilgen_init (); + mono_method_builder_ilgen_init (); + mono_sgen_mono_ilgen_init (); + + if (assembly_count) { + MonoBundledAssembly **bundle_array = g_new0 (MonoBundledAssembly*, assembly_count + 1); + WasmAssembly *cur = assemblies; + int i = 0; + while (cur) { + bundle_array [i] = &cur->assembly; + cur = cur->next; + ++i; + } + mono_register_bundled_assemblies ((const MonoBundledAssembly **)bundle_array); + } + + mono_wasm_register_bundled_satellite_assemblies (); + mono_trace_init (); + mono_trace_set_log_handler (wasm_trace_logger, NULL); + + root_domain = mono_jit_init_version ("mono", "v4.0.30319"); + mono_thread_set_main (mono_thread_current ()); +} + +MonoAssembly* +mono_wasm_assembly_load (const char *name) +{ + MonoImageOpenStatus status; + MonoAssemblyName* aname = mono_assembly_name_new (name); + if (!name) + return NULL; + + MonoAssembly *res = mono_assembly_load (aname, NULL, &status); + mono_assembly_name_free (aname); + + return res; +} + +MonoClass* +mono_wasm_find_corlib_class (const char *namespace, const char *name) +{ + return mono_class_from_name (mono_get_corlib (), namespace, name); +} + +MonoClass* +mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name) +{ + return mono_class_from_name (mono_assembly_get_image (assembly), namespace, name); +} + +MonoMethod* +mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments) +{ + return mono_class_get_method_from_name (klass, name, arguments); +} + +MonoMethod* +mono_wasm_get_delegate_invoke (MonoObject *delegate) +{ + return mono_get_delegate_invoke(mono_object_get_class (delegate)); +} + +MonoObject* +mono_wasm_box_primitive (MonoClass *klass, void *value, int value_size) +{ + if (!klass) + return NULL; + + MonoType *type = mono_class_get_type (klass); + int alignment; + if (mono_type_size (type, &alignment) > value_size) + return NULL; + + // TODO: use mono_value_box_checked and propagate error out + return mono_value_box (root_domain, klass, value); +} + +MonoObject* +mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], MonoObject **out_exc) +{ + MonoObject *exc = NULL; + MonoObject *res; + + if (out_exc) + *out_exc = NULL; + res = mono_runtime_invoke (method, this_arg, params, &exc); + if (exc) { + if (out_exc) + *out_exc = exc; + + MonoObject *exc2 = NULL; + res = (MonoObject*)mono_object_to_string (exc, &exc2); + if (exc2) + res = (MonoObject*) mono_string_new (root_domain, "Exception Double Fault"); + return res; + } + + MonoMethodSignature *sig = mono_method_signature (method); + MonoType *type = mono_signature_get_return_type (sig); + // If the method return type is void return null + // This gets around a memory access crash when the result return a value when + // a void method is invoked. + if (mono_type_get_type (type) == MONO_TYPE_VOID) + return NULL; + + return res; +} + +MonoMethod* +mono_wasm_assembly_get_entry_point (MonoAssembly *assembly) +{ + MonoImage *image; + MonoMethod *method; + + image = mono_assembly_get_image (assembly); + uint32_t entry = mono_image_get_entry_point (image); + if (!entry) + return NULL; + + mono_domain_ensure_entry_assembly (root_domain, assembly); + method = mono_get_method (image, entry, NULL); + + /* + * If the entry point looks like a compiler generated wrapper around + * an async method in the form "" then try to look up the async methods + * "$" and "Name" it could be wrapping. We do this because the generated + * sync wrapper will call task.GetAwaiter().GetResult() when we actually want + * to yield to the host runtime. + */ + if (mono_method_get_flags (method, NULL) & 0x0800 /* METHOD_ATTRIBUTE_SPECIAL_NAME */) { + const char *name = mono_method_get_name (method); + int name_length = strlen (name); + + if ((*name != '<') || (name [name_length - 1] != '>')) + return method; + + MonoClass *klass = mono_method_get_class (method); + char *async_name = malloc (name_length + 2); + snprintf (async_name, name_length + 2, "%s$", name); + + // look for "$" + MonoMethodSignature *sig = mono_method_get_signature (method, image, mono_method_get_token (method)); + MonoMethod *async_method = mono_class_get_method_from_name (klass, async_name, mono_signature_get_param_count (sig)); + if (async_method != NULL) { + free (async_name); + return async_method; + } + + // look for "Name" by trimming the first and last character of "" + async_name [name_length - 1] = '\0'; + async_method = mono_class_get_method_from_name (klass, async_name + 1, mono_signature_get_param_count (sig)); + + free (async_name); + if (async_method != NULL) + return async_method; + } + return method; +} + +char * +mono_wasm_string_get_utf8 (MonoString *str) +{ + return mono_string_to_utf8 (str); //XXX JS is responsible for freeing this +} + +mono_wasm_string_from_js (const char *str) +{ + if (str) + return mono_string_new (root_domain, str); + else + return NULL; +} + +int +mono_unbox_int (MonoObject *obj) +{ + if (!obj) + return 0; + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type (type)) { + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + return *(signed char*)ptr; + case MONO_TYPE_U1: + return *(unsigned char*)ptr; + case MONO_TYPE_I2: + return *(short*)ptr; + case MONO_TYPE_U2: + return *(unsigned short*)ptr; + case MONO_TYPE_I4: + case MONO_TYPE_I: + return *(int*)ptr; + case MONO_TYPE_U4: + return *(unsigned int*)ptr; + case MONO_TYPE_CHAR: + return *(short*)ptr; + // WASM doesn't support returning longs to JS + // case MONO_TYPE_I8: + // case MONO_TYPE_U8: + default: + printf ("Invalid type %d to mono_unbox_int\n", mono_type_get_type (type)); + return 0; + } +} + +int +mono_wasm_array_length (MonoArray *array) +{ + return mono_array_length (array); +} + +MonoObject* +mono_wasm_array_get (MonoArray *array, int idx) +{ + return mono_array_get (array, MonoObject*, idx); +} + +MonoArray* +mono_wasm_obj_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_object_class (), size); +} + +void +mono_wasm_obj_array_set (MonoArray *array, int idx, MonoObject *obj) +{ + mono_array_setref (array, idx, obj); +} + +MonoArray* +mono_wasm_string_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_string_class (), size); +} + +void +mono_wasm_string_get_data ( + MonoString *string, mono_unichar2 **outChars, int *outLengthBytes, int *outIsInterned +) { + if (!string) { + if (outChars) + *outChars = 0; + if (outLengthBytes) + *outLengthBytes = 0; + if (outIsInterned) + *outIsInterned = 1; + return; + } + + if (outChars) + *outChars = mono_string_chars (string); + if (outLengthBytes) + *outLengthBytes = mono_string_length (string) * 2; + if (outIsInterned) + *outIsInterned = mono_string_instance_is_interned (string); + return; +} + +void add_assembly(const char* base_dir, const char *name) { + FILE *fileptr; + unsigned char *buffer; + long filelen; + char filename[256]; + sprintf(filename, "%s/%s", base_dir, name); + // printf("Loading %s...\n", filename); + + fileptr = fopen(filename, "rb"); + if (fileptr == 0) { + printf("Failed to load %s\n", filename); + fflush(stdout); + } + + fseek(fileptr, 0, SEEK_END); + filelen = ftell(fileptr); + rewind(fileptr); + + buffer = (unsigned char *)malloc(filelen * sizeof(char)); + fread(buffer, filelen, 1, fileptr); + fclose(fileptr); + + assert(mono_wasm_add_assembly(name, buffer, filelen)); +} + +MonoMethod* lookup_dotnet_method(const char* assembly_name, const char* namespace, const char* type_name, const char* method_name, int num_params) { + MonoAssembly* assembly = mono_wasm_assembly_load (assembly_name); + assert (assembly); + MonoClass* class = mono_wasm_assembly_find_class (assembly, namespace, type_name); + assert (class); + MonoMethod* method = mono_wasm_assembly_find_method (class, method_name, num_params); + assert (method); + return method; +} diff --git a/src/mono/wasi/mono-wasi-driver/driver.h b/src/mono/wasi/mono-wasi-driver/driver.h new file mode 100644 index 0000000000000..af5043e0a27a6 --- /dev/null +++ b/src/mono/wasi/mono-wasi-driver/driver.h @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include + +void mono_wasm_load_runtime (const char *unused, int debug_level); +int mono_wasm_add_assembly (const char *name, const unsigned char *data, unsigned int size); +MonoAssembly* mono_wasm_assembly_load(const char *name); +MonoMethod* mono_wasm_assembly_get_entry_point (MonoAssembly *assembly); +MonoClass* mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name); +MonoMethod* mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments); +MonoObject* mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], MonoObject **out_exc); +int mono_unbox_int (MonoObject *obj); +void mono_wasm_setenv (const char *name, const char *value); +void add_assembly(const char* base_dir, const char *name); + +MonoArray* mono_wasm_obj_array_new (int size); +void mono_wasm_obj_array_set (MonoArray *array, int idx, MonoObject *obj); +MonoArray* mono_wasm_string_array_new (int size); +MonoString *mono_wasm_string_from_js (const char *str); +int mono_wasm_array_length(MonoArray* array); +char *mono_wasm_string_get_utf8 (MonoString *str); + +MonoMethod* lookup_dotnet_method(const char* assembly_name, const char* namespace, const char* type_name, const char* method_name, int num_params); diff --git a/src/mono/wasi/mono-wasi-driver/stubs.c b/src/mono/wasi/mono-wasi-driver/stubs.c new file mode 100644 index 0000000000000..90ae87c5b62ae --- /dev/null +++ b/src/mono/wasi/mono-wasi-driver/stubs.c @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +// These are symbols that are never used at runtime, or at least don't need to do anything for prototype apps + +int sem_init(int a, int b, int c) { return 0; } +int sem_destroy(int x) { return 0; } +int sem_post(int x) { return 0; } +int sem_wait(int x) { return 0; } +int sem_trywait(int x) { return 0; } +int sem_timedwait (int *sem, const struct timespec *abs_timeout) { assert(0); return 0; } + +int __errno_location() { return 0; } + +void mono_log_close_syslog () { assert(0); } +void mono_log_open_syslog (const char *a, void *b) { assert(0); } +void mono_log_write_syslog (const char *a, int b, int c, const char *d) { assert(0); } + +void mono_runtime_setup_stat_profiler () { assert(0); } +int mono_thread_state_init_from_handle (int *tctx, int *info, void *sigctx) { assert(0); return 0; } diff --git a/src/mono/wasi/mono-wasi-driver/synthetic-pthread.c b/src/mono/wasi/mono-wasi-driver/synthetic-pthread.c new file mode 100644 index 0000000000000..aa15f21f71107 --- /dev/null +++ b/src/mono/wasi/mono-wasi-driver/synthetic-pthread.c @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#define SYNTHETIC_PTHREAD_KEYS_MAX 32 + +typedef struct { + int is_created; + const void* current_value; + void* destructor_func; +} synthetic_pthread_key; + +// Since we're not really supporting multiple threads, there's just a single global list of pthread keys +// (If we did have real threads, there would be a separate set for each thread) +synthetic_pthread_key synthetic_key_list[SYNTHETIC_PTHREAD_KEYS_MAX]; + +int pthread_key_create(int *key_index, void* destructor) { + int i; + for (i = 0; i < SYNTHETIC_PTHREAD_KEYS_MAX; i++) { + if (!synthetic_key_list[i].is_created) { + break; + } + } + + if (i == SYNTHETIC_PTHREAD_KEYS_MAX) { + return -1; + } + + synthetic_key_list[i].is_created = 1; + synthetic_key_list[i].destructor_func = destructor; // Not really used since we never destroy keys + *key_index = i; + return 0; +} + +int pthread_setspecific(int key_index, const void* value) { + if (!synthetic_key_list[key_index].is_created) + return -1; + + synthetic_key_list[key_index].current_value = value; + return 0; +} + +const void* pthread_getspecific(int key_index) { + assert (synthetic_key_list[key_index].is_created); + return synthetic_key_list[key_index].current_value; +} + +// Since we're not really supporting threads, mutex operations are no-ops +// It would be more robust if we actually just aborted if you tried to lock an already-locked mutex +int pthread_mutex_lock(void *mutex) { /*printf("pthread_mutex_lock with mutex=%i\n", mutex);*/ return 0; } +int pthread_mutex_unlock(int *mutex) { /*printf("pthread_mutex_unlock with mutex=%i\n", mutex);*/ return 0; } + +// Unused pthread APIs +int pthread_self() { assert(0); return 0; } +int pthread_cond_signal(int a) { assert(0); return 0; } +int pthread_cond_init(int a, int b) { return 0; } +int pthread_cond_wait(int a, int b) { return 0; } +int pthread_cond_destroy(int a) { return 0; } +int pthread_mutex_init(int a, int b) { return 0; } +int pthread_mutex_destroy(int a) { return 0; } +int pthread_cond_timedwait(int a, int b, int c) { return 0; } diff --git a/src/mono/wasi/sample/.gitignore b/src/mono/wasi/sample/.gitignore new file mode 100644 index 0000000000000..19e1bced9ad8a --- /dev/null +++ b/src/mono/wasi/sample/.gitignore @@ -0,0 +1 @@ +*.wasm diff --git a/src/mono/wasi/sample/Directory.Build.props b/src/mono/wasi/sample/Directory.Build.props new file mode 100644 index 0000000000000..69b70ee868b5a --- /dev/null +++ b/src/mono/wasi/sample/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + bin/$(Configuration)/net7.0 + + diff --git a/src/mono/wasi/sample/SampleMakefile.variable b/src/mono/wasi/sample/SampleMakefile.variable new file mode 100644 index 0000000000000..ba14317ec54cb --- /dev/null +++ b/src/mono/wasi/sample/SampleMakefile.variable @@ -0,0 +1,18 @@ +TOP=$(realpath $(CURDIR)/../../../../..) + +COMPILE_FLAGS=\ + $(WASI_BIN_DIR)/*.a \ + $(BROWSER_WASM_RUNTIME_PATH)/native/libSystem.Native.a \ + --sysroot=$(WASI_SDK_ROOT)/share/wasi-sysroot \ + -I$(TOP)/src/mono + +LINK_FLAGS=\ + -Wl,--export=malloc,--export=free,--export=__heap_base,--export=__data_end \ + -Wl,-z,stack-size=1048576,--initial-memory=5242880,--max-memory=52428800,-lwasi-emulated-mman + +ifndef DOTNET_ROOT +$(error DOTNET_ROOT is undefined. Example: export DOTNET_ROOT=~/dotnet7) +endif +ifndef BROWSER_WASM_RUNTIME_PATH +$(error BROWSER_WASM_RUNTIME_PATH is undefined. Example: export BROWSER_WASM_RUNTIME_PATH=$(DOTNET_ROOT)/packs/Microsoft.NETCore.App.Runtime.Mono.browser-wasm/7.0.0-alpha.1.22061.11/runtimes/browser-wasm) +endif diff --git a/src/mono/wasi/sample/console/Makefile b/src/mono/wasi/sample/console/Makefile new file mode 100644 index 0000000000000..bc9fd14dcb751 --- /dev/null +++ b/src/mono/wasi/sample/console/Makefile @@ -0,0 +1,20 @@ +include ../../Makefile.variable +include ../SampleMakefile.variable + +BIN_DIR=WasiConsoleApp/bin/$(CONFIG)/net7.0 + +all: console.wasm $(BIN_DIR)/WasiConsoleApp.dll + +run: all + wasmtime --dir=. console.wasm + +run-wasmer: all + wasmer --dir=. console.wasm + +console.wasm: main.c + $(WASI_SDK_CLANG) main.c -o console.wasm $(COMPILE_FLAGS) $(LINK_FLAGS) + +$(BIN_DIR)/WasiConsoleApp.dll: WasiConsoleApp/*.csproj WasiConsoleApp/*.cs + cd WasiConsoleApp && $(DOTNET_ROOT)/dotnet build -c $(CONFIG) + touch $(BIN_DIR)/*.dll + cp -R $(BROWSER_WASM_RUNTIME_PATH) $(BIN_DIR)/runtime diff --git a/src/mono/wasi/sample/console/WasiConsoleApp/Program.cs b/src/mono/wasi/sample/console/WasiConsoleApp/Program.cs new file mode 100644 index 0000000000000..83a7facbcf64d --- /dev/null +++ b/src/mono/wasi/sample/console/WasiConsoleApp/Program.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace WasiConsoleApp +{ + public class Program + { + public static int Main() + { + Console.WriteLine($"Hello from .NET at {DateTime.Now.ToLongTimeString()}"); + return 0; + } + } +} diff --git a/src/mono/wasi/sample/console/WasiConsoleApp/WasiConsoleApp.csproj b/src/mono/wasi/sample/console/WasiConsoleApp/WasiConsoleApp.csproj new file mode 100644 index 0000000000000..49755d024c8a1 --- /dev/null +++ b/src/mono/wasi/sample/console/WasiConsoleApp/WasiConsoleApp.csproj @@ -0,0 +1,9 @@ + + + + Exe + net7.0 + true + + + diff --git a/src/mono/wasi/sample/console/main.c b/src/mono/wasi/sample/console/main.c new file mode 100644 index 0000000000000..4ee373135cd72 --- /dev/null +++ b/src/mono/wasi/sample/console/main.c @@ -0,0 +1,21 @@ +#include +#include "../../mono-wasi-driver/driver.h" + +int main() { + // Assume the runtime pack has been copied into the output directory as 'runtime' + // Otherwise we have to mount an unrelated part of the filesystem within the WASM environment + const char* app_base_dir = "./WasiConsoleApp/bin/Release/net7.0"; + char* assemblies_path; + asprintf(&assemblies_path, "%s:%s/runtime/native:%s/runtime/lib/net7.0", app_base_dir, app_base_dir, app_base_dir); + + add_assembly(app_base_dir, "WasiConsoleApp.dll"); + mono_set_assemblies_path(assemblies_path); + + mono_wasm_load_runtime("", 0); + + MonoAssembly* assembly = mono_wasm_assembly_load ("WasiConsoleApp.dll"); + MonoMethod* entry_method = mono_wasm_assembly_get_entry_point (assembly); + MonoObject* out_exc; + MonoObject *exit_code = mono_wasm_invoke_method (entry_method, NULL, NULL, &out_exc); + return mono_unbox_int (exit_code); +} diff --git a/src/mono/wasm/build/README.md b/src/mono/wasm/build/README.md index faed3d05827f6..c6fb0a8681944 100644 --- a/src/mono/wasm/build/README.md +++ b/src/mono/wasm/build/README.md @@ -132,3 +132,13 @@ them for the new task assembly. - `eng/testing/linker/trimmingTests.targets`, - `src/tests/Common/wasm-test-runner/WasmTestRunner.proj` - `src/tests/Directory.Build.targets` + +## Profiling build performance + +If encountering build performance issues, you can use the rollup `--perf` option and the typescript compiler `--generateCpuProfile` option to get build profile data, like so: + +```../emsdk/node/14.15.5_64bit/bin/npm run rollup --perf -- --perf --environment Configuration:Release,NativeBinDir:./rollup-test-data,ProductVersion:12.3.4``` + +```node node_modules/typescript/lib/tsc.js --generateCpuProfile dotnet-tsc.cpuprofile -p tsconfig.json ``` + +The .cpuprofile file generated by node can be opened in the Performance tab of Chrome or Edge's devtools. \ No newline at end of file diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 7860aef3772e8..cf9eff051b886 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -332,7 +332,7 @@ internal class MethodInfo internal LocalScopeHandleCollection localScopes; public bool IsStatic() => (methodDef.Attributes & MethodAttributes.Static) != 0; public int IsAsync { get; set; } - public bool IsHiddenFromDebugger { get; } + public DebuggerAttributesInfo DebuggerAttrInfo { get; set; } public TypeInfo TypeInfo { get; } public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, int token, SourceFile source, TypeInfo type, MetadataReader asmMetadataReader, MetadataReader pdbMetadataReader) @@ -370,6 +370,7 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, StartLocation = new SourceLocation(this, start); EndLocation = new SourceLocation(this, end); + DebuggerAttrInfo = new DebuggerAttributesInfo(); foreach (var cattr in methodDef.GetCustomAttributes()) { var ctorHandle = asmMetadataReader.GetCustomAttribute(cattr).Constructor; @@ -377,14 +378,25 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (name == "DebuggerHiddenAttribute") + switch (name) { - this.IsHiddenFromDebugger = true; - break; + case "DebuggerHiddenAttribute": + DebuggerAttrInfo.HasDebuggerHidden = true; + break; + case "DebuggerStepThroughAttribute": + DebuggerAttrInfo.HasStepThrough = true; + break; + case "DebuggerNonUserCodeAttribute": + DebuggerAttrInfo.HasNonUserCode = true; + break; + case "DebuggerStepperBoundaryAttribute": + DebuggerAttrInfo.HasStepperBoundary = true; + break; } } } + DebuggerAttrInfo.ClearInsignificantAttrFlags(); } localScopes = pdbMetadataReader.GetLocalScopes(methodDefHandle); } @@ -472,6 +484,38 @@ public VarInfo[] GetLiveVarsAt(int offset) } public override string ToString() => "MethodInfo(" + Name + ")"; + + public class DebuggerAttributesInfo + { + internal bool HasDebuggerHidden { get; set; } + internal bool HasStepThrough { get; set; } + internal bool HasNonUserCode { get; set; } + public bool HasStepperBoundary { get; internal set; } + + internal void ClearInsignificantAttrFlags() + { + // hierarchy: hidden > stepThrough > nonUserCode > boundary + if (HasDebuggerHidden) + HasStepThrough = HasNonUserCode = HasStepperBoundary = false; + else if (HasStepThrough) + HasNonUserCode = HasStepperBoundary = false; + else if (HasNonUserCode) + HasStepperBoundary = false; + } + + public bool DoAttributesAffectCallStack(bool justMyCodeEnabled) + { + return HasStepThrough || + HasDebuggerHidden || + HasStepperBoundary || + (HasNonUserCode && justMyCodeEnabled); + } + + public bool ShouldStepOut(EventKind eventKind) + { + return HasDebuggerHidden || (HasStepperBoundary && eventKind == EventKind.Step); + } + } } internal class TypeInfo diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index e17c3d2bccc4f..9b9c5a410cf2f 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -14,7 +14,7 @@ namespace Microsoft.WebAssembly.Diagnostics { - public struct SessionId + public struct SessionId : IEquatable { public readonly string sessionId; @@ -26,7 +26,9 @@ public SessionId(string sessionId) // hashset treats 0 as unset public override int GetHashCode() => sessionId?.GetHashCode() ?? -1; - public override bool Equals(object obj) => (obj is SessionId) ? ((SessionId)obj).sessionId == sessionId : false; + public override bool Equals(object obj) => obj is SessionId other && Equals(other); + + public bool Equals(SessionId other) => other.sessionId == sessionId; public static bool operator ==(SessionId a, SessionId b) => a.sessionId == b.sessionId; @@ -37,7 +39,7 @@ public SessionId(string sessionId) public override string ToString() => $"session-{sessionId}"; } - public struct MessageId + public struct MessageId : IEquatable { public readonly string sessionId; public readonly int id; @@ -54,7 +56,9 @@ public MessageId(string sessionId, int id) public override int GetHashCode() => (sessionId?.GetHashCode() ?? 0) ^ id.GetHashCode(); - public override bool Equals(object obj) => (obj is MessageId) ? ((MessageId)obj).sessionId == sessionId && ((MessageId)obj).id == id : false; + public override bool Equals(object obj) => obj is MessageId other && Equals(other); + + public bool Equals(MessageId other) => other.sessionId == sessionId && other.id == id; } internal class DotnetObjectId @@ -312,6 +316,8 @@ public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData) public TaskCompletionSource ready; public bool IsRuntimeReady => ready != null && ready.Task.IsCompleted; public bool IsSkippingHiddenMethod { get; set; } + public bool IsSteppingThroughMethod { get; set; } + public bool IsResumedAfterBp { get; set; } public int ThreadId { get; set; } public int Id { get; set; } public object AuxData { get; set; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 13979ad0f4968..aed459c2218c4 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -26,6 +26,7 @@ internal class MonoProxy : DevToolsProxy private const string sPauseOnCaught = "pause_on_caught"; // index of the runtime in a same JS page/process public int RuntimeId { get; private init; } + public bool JustMyCode { get; private set; } public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList, int runtimeId = 0) : base(loggerFactory) { @@ -498,6 +499,14 @@ protected override async Task AcceptCommand(MessageId id, string method, J } // Protocol extensions + case "DotnetDebugger.applyUpdates": + { + if (await ApplyUpdates(id, args, token)) + SendResponse(id, Result.OkFromObject(new { }), token); + else + SendResponse(id, Result.Err("ApplyUpdate failed."), token); + return true; + } case "DotnetDebugger.addSymbolServerUrl": { string url = args["url"]?.Value(); @@ -573,10 +582,46 @@ protected override async Task AcceptCommand(MessageId id, string method, J return true; } } + case "DotnetDebugger.justMyCode": + { + try + { + SetJustMyCode(id, args, token); + } + catch (Exception) + { + SendResponse(id, + Result.Exception(new ArgumentException( + $"DotnetDebugger.justMyCode got incorrect argument ({args})")), + token); + } + return true; + } } return false; } + + private async Task ApplyUpdates(MessageId id, JObject args, CancellationToken token) + { + var context = GetContext(id); + string moduleGUID = args["moduleGUID"]?.Value(); + string dmeta = args["dmeta"]?.Value(); + string dil = args["dil"]?.Value(); + string dpdb = args["dpdb"]?.Value(); + var moduleId = await context.SdbAgent.GetModuleId(moduleGUID, token); + var applyUpdates = await context.SdbAgent.ApplyUpdates(moduleId, dmeta, dil, dpdb, token); + return applyUpdates; + } + + private void SetJustMyCode(MessageId id, JObject args, CancellationToken token) + { + var isEnabled = args["enabled"]?.Value(); + if (isEnabled == null) + throw new ArgumentException(); + JustMyCode = isEnabled.Value; + SendResponse(id, Result.OkFromObject(new { justMyCodeEnabled = JustMyCode }), token); + } private async Task CallOnFunction(MessageId id, JObject args, CancellationToken token) { var context = GetContext(id); @@ -813,24 +858,46 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con DebugStore store = await LoadStore(sessionId, token); var method = await context.SdbAgent.GetMethodInfo(methodId, token); - if (context.IsSkippingHiddenMethod == true) + var shouldReturn = await SkipMethod( + isSkippable: context.IsSkippingHiddenMethod, + shouldBeSkipped: event_kind != EventKind.UserBreak, + StepKind.Over); + context.IsSkippingHiddenMethod = false; + if (shouldReturn) + return true; + + shouldReturn = await SkipMethod( + isSkippable: context.IsSteppingThroughMethod, + shouldBeSkipped: event_kind != EventKind.UserBreak && event_kind != EventKind.Breakpoint, + StepKind.Over); + context.IsSteppingThroughMethod = false; + if (shouldReturn) + return true; + + if (j == 0 && method?.Info.DebuggerAttrInfo.DoAttributesAffectCallStack(JustMyCode) == true) { - context.IsSkippingHiddenMethod = false; - if (event_kind != EventKind.UserBreak) + if (method.Info.DebuggerAttrInfo.ShouldStepOut(event_kind)) { - await context.SdbAgent.Step(context.ThreadId, StepKind.Over, token); - await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - return true; + if (event_kind == EventKind.Step) + context.IsSkippingHiddenMethod = true; + if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) + return true; + } + if (!method.Info.DebuggerAttrInfo.HasStepperBoundary) + { + if (event_kind == EventKind.Step || + (JustMyCode && (event_kind == EventKind.Breakpoint || event_kind == EventKind.UserBreak))) + { + if (context.IsResumedAfterBp) + context.IsResumedAfterBp = false; + else if (event_kind != EventKind.UserBreak) + context.IsSteppingThroughMethod = true; + if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) + return true; + } + if (event_kind == EventKind.Breakpoint) + context.IsResumedAfterBp = true; } - } - - if (j == 0 && method?.Info.IsHiddenFromDebugger == true) - { - if (event_kind == EventKind.Step) - context.IsSkippingHiddenMethod = true; - await context.SdbAgent.Step(context.ThreadId, StepKind.Out, token); - await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - return true; } SourceLocation location = method?.Info.GetLocationByIl(il_pos); @@ -910,6 +977,17 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con SendEvent(sessionId, "Debugger.paused", o, token); return true; + + async Task SkipMethod(bool isSkippable, bool shouldBeSkipped, StepKind stepKind) + { + if (isSkippable && shouldBeSkipped) + { + await context.SdbAgent.Step(context.ThreadId, stepKind, token); + await SendCommand(sessionId, "Debugger.resume", new JObject(), token); + return true; + } + return false; + } } private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObject args, CancellationToken token) { @@ -1388,7 +1466,7 @@ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, Breakpoi { SourceLocation loc = sourceId.First(); req.Method = loc.IlLocation.Method; - if (req.Method.IsHiddenFromDebugger) + if (req.Method.DebuggerAttrInfo.HasDebuggerHidden) continue; Breakpoint bp = await SetMonoBreakpoint(sessionId, req.Id, loc, req.Condition, token); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 3b1dc557259b6..1d62e94f556f1 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -139,7 +139,8 @@ internal enum CmdVM { StopBuffering = 15, VmReadMemory = 16, VmWriteMemory = 17, - GetAssemblyByName = 18 + GetAssemblyByName = 18, + GetModuleByGUID = 19 } internal enum CmdFrame { @@ -483,8 +484,7 @@ public MonoBinaryWriter() : base(new MemoryStream(20)) {} public override void Write(string val) { var bytes = Encoding.UTF8.GetBytes(val); - Write(bytes.Length); - Write(bytes); + WriteByteArray(bytes); } public override void Write(long val) => WriteBigEndian(val); @@ -520,6 +520,13 @@ public void WriteObj(DotnetObjectId objectId, MonoSDBHelper SdbHelper) Write(SdbHelper.valueTypes[objectId.Value].valueTypeBuffer); } } + + public void WriteByteArray(byte[] bytes) + { + Write(bytes.Length); + Write(bytes); + } + public async Task WriteConst(LiteralExpressionSyntax constValue, MonoSDBHelper SdbHelper, CancellationToken token) { switch (constValue.Kind()) @@ -996,6 +1003,16 @@ public async Task GetAssemblyId(string asm_name, CancellationToken token) return retDebuggerCmdReader.ReadInt32(); } + public async Task GetModuleId(string moduleGuid, CancellationToken token) + { + using var commandParamsWriter = new MonoBinaryWriter(); + var guidArray = Convert.FromBase64String(moduleGuid); + commandParamsWriter.WriteByteArray(guidArray); + + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdVM.GetModuleByGUID, commandParamsWriter, token); + return retDebuggerCmdReader.ReadInt32(); + } + public async Task GetAssemblyNameFromModule(int moduleId, CancellationToken token) { using var command_params_writer = new MonoBinaryWriter(); @@ -2665,6 +2682,39 @@ public async Task SetVariableValue(int thread_id, int frame_id, int varId, return false; return true; } + + public async Task CreateByteArray(string diff, CancellationToken token) + { + var diffArr = Convert.FromBase64String(diff); + using var commandParamsWriter = new MonoBinaryWriter(); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAppDomain.GetRootDomain, commandParamsWriter, token); + var root = retDebuggerCmdReader.ReadInt32(); + + commandParamsWriter.Write(root); + commandParamsWriter.WriteByteArray(diffArr); + using var arrayDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAppDomain.CreateByteArray, commandParamsWriter, token); + return arrayDebuggerCmdReader.ReadInt32(); + } + + public async Task ApplyUpdates(int moduleId, string dmeta, string dil, string dpdb, CancellationToken token) + { + int dpdbId = -1; + var dmetaId = await CreateByteArray(dmeta, token); + var dilId = await CreateByteArray(dil, token); + if (dpdb != null) + dpdbId = await CreateByteArray(dpdb, token); + + using var commandParamsWriter = new MonoBinaryWriter(); + commandParamsWriter.Write(moduleId); + commandParamsWriter.Write(dmetaId); + commandParamsWriter.Write(dilId); + if (dpdbId != -1) + commandParamsWriter.Write(dpdbId); + else + commandParamsWriter.Write((byte)ValueTypeId.Null); + await SendDebuggerAgentCommand(CmdModule.ApplyChanges, commandParamsWriter, token); + return true; + } } internal static class HelperExtensions diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 2644e8f754040..30c9417b6e484 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -667,45 +667,393 @@ await EvaluateAndCheck( } - [Fact] - public async Task DebuggerAttributeNoStopInDebuggerHidden() + [Theory] + [InlineData("RunDebuggerHidden", "HiddenMethod")] + [InlineData("RunStepThroughWithHidden", "StepThroughWithHiddenBp")] // debuggerHidden shadows the effect of stepThrough + [InlineData("RunNonUserCodeWithHidden", "NonUserCodeWithHiddenBp")] // and nonUserCode + public async Task DebuggerHiddenNoStopOnBp(string evalFunName, string decoratedFunName) { - var bp_hidden = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "HiddenMethod", 1); - var bp_visible = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "VisibleMethod", 1); + var bp_hidden = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 1); + var bp_final = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); Assert.Empty(bp_hidden.Value["locations"]); await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:Run'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", "dotnet://debugger-test.dll/debugger-test.cs", - bp_visible.Value["locations"][0]["lineNumber"].Value(), - bp_visible.Value["locations"][0]["columnNumber"].Value(), - "VisibleMethod" + bp_final.Value["locations"][0]["lineNumber"].Value(), + bp_final.Value["locations"][0]["columnNumber"].Value(), + evalFunName ); } - [Fact] - public async Task DebuggerAttributeStopOnDebuggerHiddenCallWithDebuggerBreakCall() + [Theory] + [InlineData("RunDebuggerHidden")] + [InlineData("RunStepThroughWithHidden")] // debuggerHidden shadows the effect of stepThrough + [InlineData("RunNonUserCodeWithHidden")] // and nonUserCode + public async Task DebuggerHiddenStopOnUserBp(string evalFunName) { - var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 0); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); + var bp_final = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 3); var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 2);", "dotnet://debugger-test.dll/debugger-test.cs", bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunDebuggerBreak" + evalFunName ); - var pause_location = await SendCommandAndCheck(null, "Debugger.resume", + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", - bp_init.Value["locations"][0]["lineNumber"].Value() + 1, - 8, - "RunDebuggerBreak"); - Assert.Equal(init_location["callFrames"][0]["functionName"], pause_location["callFrames"][0]["functionName"]); - var id = pause_location["callFrames"][0]["callFrameId"].Value(); - await EvaluateOnCallFrame(id, "local_var", false); + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + evalFunName); await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", - 835, - 8, - "VisibleMethodDebuggerBreak"); + bp_final.Value["locations"][0]["lineNumber"].Value(), + bp_final.Value["locations"][0]["columnNumber"].Value(), + evalFunName); + } + + [Fact] + public async Task DebugHotReloadMethodChangedUserBreakUsingSDB() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "MethodBody1", "StaticMethod1"); + + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 10); + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody1", "StaticMethod1", 1); + + JToken top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod1", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 12, 16, scripts, top_frame["location"]); + + locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "b", 15); + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody1", "StaticMethod1", 2); + + top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod1", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 12, 12, scripts, top_frame["location"]); + + locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + await CheckBool(locals, "c", true); + } + + [Fact] + public async Task DebugHotReloadMethodUnchangedUsingSDB() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "MethodBody2", "StaticMethod1"); + + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 10); + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody2", "StaticMethod1", 1); + + JToken top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod1", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 21, 12, scripts, top_frame["location"]); + + locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 10); + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody2", "StaticMethod1", 2); + + top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod1", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 21, 12, scripts, top_frame["location"]); + } + + [Fact] + public async Task DebugHotReloadMethodAddBreakpointUsingSDB() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + + int line = 30; + await SetBreakpoint(".*/MethodBody1.cs$", line, 12, use_regex: true); + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "MethodBody3", "StaticMethod3"); + + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 10); + + //apply first update + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody3", "StaticMethod3", 1); + + JToken top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod3", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); + + locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "b", 15); + + //apply second update + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody3", "StaticMethod3", 2); + + top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod3", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); + + locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + await CheckBool(locals, "c", true); + + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 31, 12, "StaticMethod3", + locals_fn: async (locals) => + { + CheckNumber(locals, "d", 10); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 32, 12, "StaticMethod3", + locals_fn: async (locals) => + { + CheckNumber(locals, "d", 10); + CheckNumber(locals, "e", 20); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 33, 8, "StaticMethod3", + locals_fn: async (locals) => + { + CheckNumber(locals, "d", 10); + CheckNumber(locals, "e", 20); + CheckNumber(locals, "f", 50); + await Task.CompletedTask; + } + ); + } + + + [Fact] + public async Task DebugHotReloadMethodEmptyUsingSDB() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + + int line = 38; + await SetBreakpoint(".*/MethodBody1.cs$", line, 0, use_regex: true); + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "MethodBody4", "StaticMethod4"); + + //apply first update + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody4", "StaticMethod4", 1); + + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 39, 12, "StaticMethod4", + locals_fn: async (locals) => + { + CheckNumber(locals, "a", 10); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 40, 12, "StaticMethod4", + locals_fn: async (locals) => + { + CheckNumber(locals, "a", 10); + CheckNumber(locals, "b", 20); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 41, 12, "StaticMethod4", + locals_fn: async (locals) => + { + CheckNumber(locals, "a", 10); + CheckNumber(locals, "b", 20); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 42, 12, "StaticMethod4", + locals_fn: async (locals) => + { + CheckNumber(locals, "a", 10); + CheckNumber(locals, "b", 20); + await Task.CompletedTask; + } + ); + await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 43, 8, "StaticMethod4", + locals_fn: async (locals) => + { + CheckNumber(locals, "a", 10); + CheckNumber(locals, "b", 20); + await Task.CompletedTask; + } + ); + //pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 38, 8, "StaticMethod4"); + } + + [Theory] + [InlineData(false, "RunStepThrough", 847, 8)] + [InlineData(true, "RunStepThrough", 847, 8)] + [InlineData(false, "RunNonUserCode", 852, 4, "NonUserCodeBp")] + [InlineData(true, "RunNonUserCode", 867, 8)] + [InlineData(false, "RunStepThroughWithNonUserCode", 933, 8)] + [InlineData(true, "RunStepThroughWithNonUserCode", 933, 8)] + public async Task StepThroughOrNonUserCodeAttributeStepInNoBp(bool justMyCodeEnabled, string evalFunName, int line, int col, string funcName="") + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + evalFunName + ); + await SetJustMyCode(justMyCodeEnabled); + if (funcName == "") + funcName = evalFunName; + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, col, funcName); + } + + [Theory] + [InlineData(false, "RunStepThrough", "StepThrougBp", "", 846, 8)] + [InlineData(true, "RunStepThrough", "StepThrougBp", "RunStepThrough", 847, 8)] + [InlineData(false, "RunNonUserCode", "NonUserCodeBp", "NonUserCodeBp", 852, 4)] + [InlineData(true, "RunNonUserCode", "NonUserCodeBp", "RunNonUserCode", 867, 8)] + [InlineData(false, "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeBp", "", 932, 8)] + [InlineData(true, "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeBp", "RunStepThroughWithNonUserCode", 933, 8)] + public async Task StepThroughOrNonUserCodeAttributeStepInWithBp( + bool justMyCodeEnabled, string evalFunName, string decoratedFunName, + string funName, int line, int col) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + evalFunName + ); + + await SetJustMyCode(justMyCodeEnabled); + if (!justMyCodeEnabled && funName == "") + { + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 1); + var bp2_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 3); + var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, decoratedFunName); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, decoratedFunName); + funName = evalFunName; + } + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, col, funName); + } + + [Theory] + [InlineData(false, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunNonUserCode", "NonUserCodeBp")] + [InlineData(false, "RunNonUserCode", "NonUserCodeBp")] + [InlineData(false, "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeBp")] + [InlineData(true, "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeBp")] + public async Task StepThroughOrNonUserCodeAttributeResumeWithBp(bool justMyCodeEnabled, string evalFunName, string decoratedFunName) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + evalFunName + ); + + await SetJustMyCode(justMyCodeEnabled); + if (!justMyCodeEnabled) + { + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 1); + var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, decoratedFunName); + } + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); + var line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, evalFunName); + } + + [Theory] + [InlineData(false, "Debugger.stepInto", "RunStepThrough", "StepThrougUserBp", 841, 8, "RunStepThrough", 848, 4)] + [InlineData(true, "Debugger.stepInto", "RunStepThrough", "RunStepThrough", -1, 8, "RunStepThrough", -1, 4)] + [InlineData(false, "Debugger.resume", "RunStepThrough", "StepThrougUserBp", 841, 8, "RunStepThrough", 848, 4)] + [InlineData(true, "Debugger.resume", "RunStepThrough", "RunStepThrough", -1, 8, "RunStepThrough", -1, 4)] + [InlineData(false, "Debugger.stepInto", "RunNonUserCode", "NonUserCodeUserBp", 860, 4, "NonUserCodeUserBp", 861, 8)] + [InlineData(true, "Debugger.stepInto", "RunNonUserCode", "RunNonUserCode", -1, 8, "RunNonUserCode", -1, 4)] + [InlineData(false, "Debugger.resume", "RunNonUserCode", "NonUserCodeUserBp", 861, 8, "RunNonUserCode", -1, 4)] + [InlineData(true, "Debugger.resume", "RunNonUserCode", "RunNonUserCode", -1, 8, "RunNonUserCode", -1, 4)] + [InlineData(false, "Debugger.stepInto", "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeUserBp", 927, 8, "RunStepThroughWithNonUserCode", 934, 4)] + [InlineData(true, "Debugger.stepInto", "RunStepThroughWithNonUserCode", "RunStepThroughWithNonUserCode", -1, 8, "RunStepThroughWithNonUserCode", -1, 4)] + [InlineData(false, "Debugger.resume", "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeUserBp", 927, 8, "RunStepThroughWithNonUserCode", -1, 4)] + [InlineData(true, "Debugger.resume", "RunStepThroughWithNonUserCode", "RunStepThroughWithNonUserCode", -1, 8, "RunStepThroughWithNonUserCode", -1, 4)] + public async Task StepThroughOrNonUserCodeAttributeWithUserBp( + bool justMyCodeEnabled, string debuggingFunction, string evalFunName, + string functionNameCheck1, int line1, int col1, + string functionNameCheck2, int line2, int col2) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 3); + + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + evalFunName + ); + + await SetJustMyCode(justMyCodeEnabled); + if (line1 == -1) + line1 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value() - 1; + if (line2 == -1) + line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line1, col1, functionNameCheck1); + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, col2, functionNameCheck2); + } + + [Theory] + [InlineData("Debugger.stepInto", 1, 2, false)] + [InlineData("Debugger.stepInto", 1, 2, true)] + [InlineData("Debugger.resume", 1, 2, true)] + [InlineData("Debugger.stepInto", 2, 3, false)] + [InlineData("Debugger.resume", 2, 3, false)] + public async Task StepperBoundary(string debuggingAction, int lineBpInit, int lineBpFinal, bool hasBpInDecoratedFun) + { + // behavior of StepperBoundary is the same for JMC enabled and disabled + // but the effect of NonUserCode escape is better visible for JMC: enabled + await SetJustMyCode(true); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunNoBoundary", lineBpInit); + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:RunNoBoundary'); }}, {lineBpInit});", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunNoBoundary" + ); + var bp_final = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunNoBoundary", lineBpFinal); + if (hasBpInDecoratedFun) + { + var bp_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "BoundaryBp", 2); + var line_decorated_fun = bp_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var col_decorated_fun = bp_decorated_fun.Value["locations"][0]["columnNumber"].Value(); + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", line_decorated_fun, col_decorated_fun, "BoundaryBp"); + } + if (lineBpInit == 2) + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", 879, 8, "BoundaryUserBp"); + + var line = bp_final.Value["locations"][0]["lineNumber"].Value(); + var col = bp_final.Value["locations"][0]["columnNumber"].Value(); + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", line, col, "RunNoBoundary"); } [Fact] @@ -777,6 +1125,30 @@ await EvaluateAndCheck( ); } + [Fact] + public async Task DebugHotReloadMethod_CheckBreakpointLineUpdated_ByVS_Simulated() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + + var bp = await SetBreakpoint(".*/MethodBody1.cs$", 48, 12, use_regex: true); + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "MethodBody5", "StaticMethod1"); + + //apply first update + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "MethodBody5", "StaticMethod1", 1, + rebindBreakpoint : async () => + { + await RemoveBreakpoint(bp.Value["breakpointId"].Value()); + await SetBreakpoint(".*/MethodBody1.cs$", 49, 12, use_regex: true); + }); + + JToken top_frame = pause_location["callFrames"]?[0]; + AssertEqual("StaticMethod1", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 49, 12, scripts, top_frame["location"]); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 5660e8c55011b..23ac172cf69b1 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -1189,9 +1189,76 @@ internal async Task LoadAssemblyDynamicallyALCAndRunMethod(string asm_f return await insp.WaitFor(Inspector.PAUSE); } + internal async Task LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges(string asm_file, string pdb_file, string class_name, string method_name) + { + byte[] bytes = File.ReadAllBytes(asm_file); + string asm_base64 = Convert.ToBase64String(bytes); + bytes = File.ReadAllBytes(pdb_file); + string pdb_base64 = Convert.ToBase64String(bytes); + + string expression = $"let asm_b64 = '{asm_base64}'; let pdb_b64 = '{pdb_base64}';"; + expression = $"{{ {expression} invoke_static_method('[debugger-test] TestHotReloadUsingSDB:LoadLazyHotReload', asm_b64, pdb_b64); }}"; + var load_assemblies = JObject.FromObject(new + { + expression + }); + + Result load_assemblies_res = await cli.SendCommand("Runtime.evaluate", load_assemblies, token); + + Thread.Sleep(1000); + var run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { invoke_static_method('[debugger-test] TestHotReloadUsingSDB:RunMethod', '" + class_name + "', '" + method_name + "'); }, 1);" + }); + + await cli.SendCommand("Runtime.evaluate", run_method, token); + return await insp.WaitFor(Inspector.PAUSE); + } + + internal async Task LoadAssemblyAndTestHotReloadUsingSDB(string asm_file_hot_reload, string class_name, string method_name, int id, Func rebindBreakpoint = null) + { + await cli.SendCommand("Debugger.resume", null, token); + var bytes = File.ReadAllBytes($"{asm_file_hot_reload}.{id}.dmeta"); + string dmeta1 = Convert.ToBase64String(bytes); + + bytes = File.ReadAllBytes($"{asm_file_hot_reload}.{id}.dil"); + string dil1 = Convert.ToBase64String(bytes); + + bytes = File.ReadAllBytes($"{asm_file_hot_reload}.{id}.dpdb"); + string dpdb1 = Convert.ToBase64String(bytes); + + var run_method = JObject.FromObject(new + { + expression = "invoke_static_method('[debugger-test] TestHotReloadUsingSDB:GetModuleGUID');" + }); + + var moduleGUID_res = await cli.SendCommand("Runtime.evaluate", run_method, token); + + Assert.True(moduleGUID_res.IsOk); + var moduleGUID = moduleGUID_res.Value["result"]["value"]; + + var applyUpdates = JObject.FromObject(new + { + moduleGUID, + dmeta = dmeta1, + dil = dil1, + dpdb = dpdb1 + }); + await cli.SendCommand("DotnetDebugger.applyUpdates", applyUpdates, token); + + if (rebindBreakpoint != null) + await rebindBreakpoint(); + + run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { invoke_static_method('[debugger-test] TestHotReloadUsingSDB:RunMethod', '" + class_name + "', '" + method_name + "'); }, 1);" + }); + await cli.SendCommand("Runtime.evaluate", run_method, token); + return await insp.WaitFor(Inspector.PAUSE); + } + internal async Task LoadAssemblyAndTestHotReload(string asm_file, string pdb_file, string asm_file_hot_reload, string class_name, string method_name) { - // Simulate loading an assembly into the framework byte[] bytes = File.ReadAllBytes(asm_file); string asm_base64 = Convert.ToBase64String(bytes); bytes = File.ReadAllBytes(pdb_file); @@ -1237,6 +1304,14 @@ internal async Task LoadAssemblyAndTestHotReload(string asm_file, strin await cli.SendCommand("Runtime.evaluate", run_method, token); return await insp.WaitFor(Inspector.PAUSE); } + + internal async Task SetJustMyCode(bool enabled) + { + var req = JObject.FromObject(new { enabled = enabled }); + var res = await cli.SendCommand("DotnetDebugger.justMyCode", req, token); + Assert.True(res.IsOk); + Assert.Equal(res.Value["justMyCodeEnabled"], enabled); + } } class DotnetObjectId diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index bb61841cdd1f7..c19669bd0c88e 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -913,7 +913,7 @@ public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 860, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 965, 8, "CallToEvaluateLocal", wait_for_event_fn: async (pause_location) => { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs index 3feb6695eed15..45f26a74c84a3 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs @@ -959,75 +959,49 @@ await EvaluateAndCheck( } [Fact] - public async Task DebuggerAttributeIgnoreStepIntoDebuggerHidden() + public async Task DebuggerHiddenIgnoreStepInto() { - var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "Run", 1); + var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerHidden", 1); await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:Run'); }, 1);", + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerHidden'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", pause_location.Value["locations"][0]["lineNumber"].Value(), pause_location.Value["locations"][0]["columnNumber"].Value(), - "Run" + "RunDebuggerHidden" ); var step_into = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); - Assert.Equal( step_into["callFrames"][0]["location"]["lineNumber"].Value(), pause_location.Value["locations"][0]["lineNumber"].Value() + 1 ); - } - [Fact] - public async Task DebuggerAttributeIgnoreStepIntoDebuggerHiddenWithDebuggerBreakCall() + [Theory] + [InlineData("Debugger.stepInto")] + [InlineData("Debugger.stepOver")] + public async Task DebuggerHiddenIgnoreStepUserBreakpoint(string steppingFunction) { - var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 1); + var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerHidden", 1); await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); }, 1);", + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerHidden'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", pause_location.Value["locations"][0]["lineNumber"].Value(), pause_location.Value["locations"][0]["columnNumber"].Value(), - "RunDebuggerBreak" + "RunDebuggerHidden" ); - var step_into1 = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); - + // stepOver HiddenMethod: + var step_into1 = await SendCommandAndCheck(null, steppingFunction, null, -1, -1, null); Assert.Equal( - pause_location.Value["locations"][0]["lineNumber"].Value(), + pause_location.Value["locations"][0]["lineNumber"].Value() + 1, step_into1["callFrames"][0]["location"]["lineNumber"].Value() ); - var step_into2 = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); - + // freeze on HiddenMethodUserBreak: + var step_into2 = await SendCommandAndCheck(null, steppingFunction, null, -1, -1, null); Assert.Equal( pause_location.Value["locations"][0]["lineNumber"].Value() + 1, step_into2["callFrames"][0]["location"]["lineNumber"].Value() ); - - } - - [Fact] - public async Task DebuggerAttributeIgnoreStepOverDebuggerHiddenWithDebuggerBreakCall() - { - var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 1); - await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); 1});", - "dotnet://debugger-test.dll/debugger-test.cs", - pause_location.Value["locations"][0]["lineNumber"].Value(), - pause_location.Value["locations"][0]["columnNumber"].Value(), - "RunDebuggerBreak" - ); - var step_over1 = await SendCommandAndCheck(null, $"Debugger.stepOver", null, -1, -1, null); - Assert.Equal( - pause_location.Value["locations"][0]["lineNumber"].Value(), - step_over1["callFrames"][0]["location"]["lineNumber"].Value() - ); - - var step_over2 = await SendCommandAndCheck(null, $"Debugger.stepOver", null, -1, -1, null); - - Assert.Equal( - pause_location.Value["locations"][0]["lineNumber"].Value() + 1, - step_over2["callFrames"][0]["location"]["lineNumber"].Value() - ); } } } diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs index d092ec07cf7e5..047e293c08236 100644 --- a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System; - +//keep the same line number for class in the original file and the updates ones namespace ApplyUpdateReferencedAssembly { public class MethodBody1 { @@ -38,4 +38,15 @@ public class MethodBody4 { public static void StaticMethod4 () { } } + + + + + + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("original"); + } + } } diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs index 6ce229dff5966..ce9d974b8bf16 100644 --- a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System; - +//keep the same line number for class in the original file and the updates ones namespace ApplyUpdateReferencedAssembly { public class MethodBody1 { @@ -43,4 +43,11 @@ public static void StaticMethod4 () { Console.WriteLine(a + b); } } + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("beforeoriginal"); + Console.WriteLine("original"); + } + } } diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs index 1ced5fd3826e1..8850f85956d30 100644 --- a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System; - +//keep the same line number for class in the original file and the updates ones namespace ApplyUpdateReferencedAssembly { public class MethodBody1 { @@ -38,4 +38,16 @@ public class MethodBody4 { public static void StaticMethod4 () { } } + + + + + + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("beforeoriginal"); + Console.WriteLine("original"); + } + } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 98b9cb00dc401..f2a97c2007727 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -810,43 +810,148 @@ public int Increment(int count) public class DebuggerAttribute { - static int currentCount = 0; - [System.Diagnostics.DebuggerHidden] public static void HiddenMethod() { - currentCount++; + var a = 9; } [System.Diagnostics.DebuggerHidden] - public static void HiddenMethodDebuggerBreak() + public static void HiddenMethodUserBreak() { - var local_var = 12; System.Diagnostics.Debugger.Break(); - currentCount++; } - public static void VisibleMethod() + public static void RunDebuggerHidden() + { + HiddenMethod(); + HiddenMethodUserBreak(); + } + + [System.Diagnostics.DebuggerStepThroughAttribute] + public static void StepThrougBp() { - currentCount++; + var a = 0; + a++; + var b = 1; } - public static void VisibleMethodDebuggerBreak() + [System.Diagnostics.DebuggerStepThroughAttribute] + public static void StepThrougUserBp() { System.Diagnostics.Debugger.Break(); - currentCount++; } - public static void Run() + public static void RunStepThrough() { - HiddenMethod(); - VisibleMethod(); + StepThrougBp(); + StepThrougUserBp(); + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeBp() + { + var a = 0; + a++; + var b = 1; + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + public static void RunNonUserCode() + { + NonUserCodeBp(); + NonUserCodeUserBp(); + } + + [System.Diagnostics.DebuggerStepperBoundary] + public static void BoundaryBp() + { + var a = 5; + } + + [System.Diagnostics.DebuggerStepperBoundary] + public static void BoundaryUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeForBoundaryEscape(Action boundaryTestFun) + { + boundaryTestFun(); + } + + public static void RunNoBoundary() + { + NonUserCodeForBoundaryEscape(DebuggerAttribute.BoundaryBp); + NonUserCodeForBoundaryEscape(DebuggerAttribute.BoundaryUserBp); + } + + [System.Diagnostics.DebuggerStepThroughAttribute] + [System.Diagnostics.DebuggerHidden] + public static void StepThroughWithHiddenBp() + { + var a = 9; + } + + [System.Diagnostics.DebuggerStepThroughAttribute] + [System.Diagnostics.DebuggerHidden] + public static void StepThroughWithHiddenUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + public static void RunStepThroughWithHidden() + { + StepThroughWithHiddenBp(); + StepThroughWithHiddenUserBp(); + } + + [System.Diagnostics.DebuggerStepThroughAttribute] + [System.Diagnostics.DebuggerNonUserCode] + public static void StepThroughWithNonUserCodeBp() + { + var a = 0; + a++; + var b = 1; + } + + [System.Diagnostics.DebuggerStepThroughAttribute] + [System.Diagnostics.DebuggerNonUserCode] + public static void StepThroughWithNonUserCodeUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + public static void RunStepThroughWithNonUserCode() + { + StepThroughWithNonUserCodeBp(); + StepThroughWithNonUserCodeUserBp(); + } + + [System.Diagnostics.DebuggerNonUserCode] + [System.Diagnostics.DebuggerHidden] + public static void NonUserCodeWithHiddenBp() + { + var a = 9; } - public static void RunDebuggerBreak() + [System.Diagnostics.DebuggerNonUserCode] + [System.Diagnostics.DebuggerHidden] + public static void NonUserCodeWithHiddenUserBp() { - HiddenMethodDebuggerBreak(); - VisibleMethodDebuggerBreak(); + System.Diagnostics.Debugger.Break(); + } + + public static void RunNonUserCodeWithHidden() + { + NonUserCodeWithHiddenBp(); + NonUserCodeWithHiddenUserBp(); } } @@ -861,3 +966,29 @@ public static void CallToEvaluateLocal() System.Diagnostics.Debugger.Break(); } } + +public class TestHotReloadUsingSDB { + static System.Reflection.Assembly loadedAssembly; + public static string LoadLazyHotReload(string asm_base64, string pdb_base64) + { + byte[] asm_bytes = Convert.FromBase64String(asm_base64); + byte[] pdb_bytes = Convert.FromBase64String(pdb_base64); + + loadedAssembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(new System.IO.MemoryStream(asm_bytes), new System.IO.MemoryStream(pdb_bytes)); + var GUID = loadedAssembly.Modules.FirstOrDefault()?.ModuleVersionId.ToByteArray(); + return Convert.ToBase64String(GUID); + } + + public static string GetModuleGUID() + { + var GUID = loadedAssembly.Modules.FirstOrDefault()?.ModuleVersionId.ToByteArray(); + return Convert.ToBase64String(GUID); + } + + public static void RunMethod(string className, string methodName) + { + var myType = loadedAssembly.GetType($"ApplyUpdateReferencedAssembly.{className}"); + var myMethod = myType.GetMethod(methodName); + myMethod.Invoke(null, null); + } +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/cs-to-js.ts b/src/mono/wasm/runtime/cs-to-js.ts index 2a7646d85973f..de208efe3c93b 100644 --- a/src/mono/wasm/runtime/cs-to-js.ts +++ b/src/mono/wasm/runtime/cs-to-js.ts @@ -3,7 +3,7 @@ import { mono_wasm_new_root, WasmRoot } from "./roots"; import { - GCHandle, JSHandleDisposed, MonoArray, + GCHandle, JSHandleDisposed, MarshalError, MarshalType, MonoArray, MonoArrayNull, MonoObject, MonoObjectNull, MonoString, MonoType, MonoTypeNull } from "./types"; @@ -18,49 +18,6 @@ import { _are_promises_supported, _create_cancelable_promise } from "./cancelabl import { getU32, getI32, getF32, getF64 } from "./memory"; import { Int32Ptr, VoidPtr } from "./types/emscripten"; -// see src/mono/wasm/driver.c MARSHAL_TYPE_xxx and Runtime.cs MarshalType -export enum MarshalType { - NULL = 0, - INT = 1, - FP64 = 2, - STRING = 3, - VT = 4, - DELEGATE = 5, - TASK = 6, - OBJECT = 7, - BOOL = 8, - ENUM = 9, - URI = 22, - SAFEHANDLE = 23, - ARRAY_BYTE = 10, - ARRAY_UBYTE = 11, - ARRAY_UBYTE_C = 12, - ARRAY_SHORT = 13, - ARRAY_USHORT = 14, - ARRAY_INT = 15, - ARRAY_UINT = 16, - ARRAY_FLOAT = 17, - ARRAY_DOUBLE = 18, - FP32 = 24, - UINT32 = 25, - INT64 = 26, - UINT64 = 27, - CHAR = 28, - STRING_INTERNED = 29, - VOID = 30, - ENUM64 = 31, - POINTER = 32 -} - -// see src/mono/wasm/driver.c MARSHAL_ERROR_xxx and Runtime.cs -export enum MarshalError { - BUFFER_TOO_SMALL = 512, - NULL_CLASS_POINTER = 513, - NULL_TYPE_POINTER = 514, - UNSUPPORTED_TYPE = 515, - FIRST = BUFFER_TOO_SMALL -} - const delegate_invoke_symbol = Symbol.for("wasm delegate_invoke"); const delegate_invoke_signature_symbol = Symbol.for("wasm delegate_invoke_signature"); diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts index 98dd8f8e4e9bb..fab4a0e264549 100644 --- a/src/mono/wasm/runtime/cwraps.ts +++ b/src/mono/wasm/runtime/cwraps.ts @@ -97,7 +97,7 @@ export interface t_Cwraps { mono_wasm_find_corlib_type(namespace: string, name: string): MonoType; mono_wasm_assembly_find_type(assembly: MonoAssembly, namespace: string, name: string): MonoType; mono_wasm_assembly_find_method(klass: MonoClass, name: string, args: number): MonoMethod; - mono_wasm_invoke_method(method: MonoMethod, this_arg: MonoObject, params: VoidPtr, out_exc: MonoObject): MonoObject; + mono_wasm_invoke_method(method: MonoMethod, this_arg: MonoObject, params: VoidPtr, out_exc: VoidPtr): MonoObject; mono_wasm_string_get_utf8(str: MonoString): CharPtr; mono_wasm_string_from_utf16(str: CharPtr, len: number): MonoString; mono_wasm_get_obj_type(str: MonoObject): number; diff --git a/src/mono/wasm/runtime/debug.ts b/src/mono/wasm/runtime/debug.ts index 8eb60b46e5478..2aa8f121a55b8 100644 --- a/src/mono/wasm/runtime/debug.ts +++ b/src/mono/wasm/runtime/debug.ts @@ -179,7 +179,7 @@ export function mono_wasm_call_function_on(request: CallRequest): CFOResponse { const fn_args = request.arguments != undefined ? request.arguments.map(a => JSON.stringify(a.value)) : []; - const fn_body_template = `var fn = ${request.functionDeclaration}; return fn.apply(proxy, [${fn_args}]);`; + const fn_body_template = `const fn = ${request.functionDeclaration}; return fn.apply(proxy, [${fn_args}]);`; const fn_defn = new Function("proxy", fn_body_template); const fn_res = fn_defn(proxy); diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index 1f18501c18b59..6d210e51ad7cc 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -100,10 +100,7 @@ declare class WasmRootBuffer { release(): void; toString(): string; } -declare class WasmRoot { - private __buffer; - private __index; - constructor(buffer: WasmRootBuffer, index: number); +interface WasmRoot { get_address(): NativePointer; get_address_32(): number; get(): T; @@ -253,12 +250,13 @@ declare function mono_call_assembly_entry_point(assembly: string, args?: any[], declare function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr; declare type _MemOffset = number | VoidPtr | NativePointer; +declare type _NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; declare function setU8(offset: _MemOffset, value: number): void; declare function setU16(offset: _MemOffset, value: number): void; -declare function setU32(offset: _MemOffset, value: number): void; +declare function setU32(offset: _MemOffset, value: _NumberOrPointer): void; declare function setI8(offset: _MemOffset, value: number): void; declare function setI16(offset: _MemOffset, value: number): void; -declare function setI32(offset: _MemOffset, value: number): void; +declare function setI32(offset: _MemOffset, value: _NumberOrPointer): void; declare function setI64(offset: _MemOffset, value: number): void; declare function setF32(offset: _MemOffset, value: number): void; declare function setF64(offset: _MemOffset, value: number): void; diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index dbe9800b9f12d..a84d1d9b0ec04 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -575,7 +575,7 @@ mono_wasm_assembly_load (const char *name) return res; } -EMSCRIPTEN_KEEPALIVE MonoAssembly* +EMSCRIPTEN_KEEPALIVE MonoAssembly* mono_wasm_get_corlib () { return mono_image_get_assembly (mono_get_corlib()); @@ -656,7 +656,7 @@ mono_wasm_assembly_get_entry_point (MonoAssembly *assembly) uint32_t entry = mono_image_get_entry_point (image); if (!entry) return NULL; - + mono_domain_ensure_entry_assembly (root_domain, assembly); method = mono_get_method (image, entry, NULL); @@ -784,7 +784,8 @@ mono_wasm_marshal_type_from_mono_type (int mono_type, MonoClass *klass, MonoType return MARSHAL_TYPE_VOID; case MONO_TYPE_BOOLEAN: return MARSHAL_TYPE_BOOL; - case MONO_TYPE_I: // IntPtr + case MONO_TYPE_I: // IntPtr + case MONO_TYPE_U: // UIntPtr case MONO_TYPE_PTR: return MARSHAL_TYPE_POINTER; case MONO_TYPE_I1: @@ -929,7 +930,7 @@ mono_wasm_try_unbox_primitive_and_get_type (MonoObject *obj, void *result, int r MonoType *type = mono_class_get_type (klass), *original_type = type; if (!type) return MARSHAL_ERROR_NULL_TYPE_POINTER; - + if ((klass == mono_get_string_class ()) && mono_string_instance_is_interned ((MonoString *)obj)) { *resultL = 0; @@ -939,14 +940,14 @@ mono_wasm_try_unbox_primitive_and_get_type (MonoObject *obj, void *result, int r if (mono_class_is_enum (klass)) type = mono_type_get_underlying_type (type); - + if (!type) return MARSHAL_ERROR_NULL_TYPE_POINTER; - + int mono_type = mono_type_get_type (type); - + if (mono_type == MONO_TYPE_GENERICINST) { - // HACK: While the 'any other type' fallback is valid for classes, it will do the + // HACK: While the 'any other type' fallback is valid for classes, it will do the // wrong thing for structs, so we need to make sure the valuetype handler is used if (mono_type_generic_inst_is_valuetype (type)) mono_type = MONO_TYPE_VALUETYPE; @@ -994,7 +995,7 @@ mono_wasm_try_unbox_primitive_and_get_type (MonoObject *obj, void *result, int r break; case MONO_TYPE_VALUETYPE: { - int obj_size = mono_object_get_size (obj), + int obj_size = mono_object_get_size (obj), required_size = (sizeof (int)) + (sizeof (MonoType *)) + obj_size; // Check whether this struct has special-case marshaling @@ -1104,7 +1105,7 @@ mono_wasm_enable_on_demand_gc (int enable) } EMSCRIPTEN_KEEPALIVE MonoString * -mono_wasm_intern_string (MonoString *string) +mono_wasm_intern_string (MonoString *string) { return mono_string_intern (string); } @@ -1156,12 +1157,12 @@ mono_wasm_unbox_rooted (MonoObject *obj) return mono_object_unbox (obj); } -EMSCRIPTEN_KEEPALIVE char * +EMSCRIPTEN_KEEPALIVE char * mono_wasm_get_type_name (MonoType * typePtr) { return mono_type_get_name_full (typePtr, MONO_TYPE_NAME_FORMAT_REFLECTION); } -EMSCRIPTEN_KEEPALIVE char * +EMSCRIPTEN_KEEPALIVE char * mono_wasm_get_type_aqn (MonoType * typePtr) { return mono_type_get_name_full (typePtr, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED); } diff --git a/src/mono/wasm/runtime/memory.ts b/src/mono/wasm/runtime/memory.ts index e8a89bd11a574..c8760a0c7a994 100644 --- a/src/mono/wasm/runtime/memory.ts +++ b/src/mono/wasm/runtime/memory.ts @@ -1,36 +1,44 @@ import { Module } from "./imports"; -import { VoidPtr, NativePointer } from "./types/emscripten"; +import { VoidPtr, NativePointer, ManagedPointer } from "./types/emscripten"; -const _temp_mallocs: Array | null> = []; +const alloca_stack: Array = []; +const alloca_buffer_size = 32 * 1024; +let alloca_base: VoidPtr, alloca_offset: VoidPtr, alloca_limit: VoidPtr; + +function _ensure_allocated(): void { + if (alloca_base) + return; + alloca_base = Module._malloc(alloca_buffer_size); + alloca_offset = alloca_base; + alloca_limit = (alloca_base + alloca_buffer_size); +} export function temp_malloc(size: number): VoidPtr { - if (!_temp_mallocs || !_temp_mallocs.length) + _ensure_allocated(); + if (!alloca_stack.length) throw new Error("No temp frames have been created at this point"); - const frame = _temp_mallocs[_temp_mallocs.length - 1] || []; - const result = Module._malloc(size); - frame.push(result); - _temp_mallocs[_temp_mallocs.length - 1] = frame; + const result = alloca_offset; + alloca_offset += size; + if (alloca_offset >= alloca_limit) + throw new Error("Out of temp storage space"); return result; } export function _create_temp_frame(): void { - _temp_mallocs.push(null); + _ensure_allocated(); + alloca_stack.push(alloca_offset); } export function _release_temp_frame(): void { - if (!_temp_mallocs.length) + if (!alloca_stack.length) throw new Error("No temp frames have been created at this point"); - const frame = _temp_mallocs.pop(); - if (!frame) - return; - - for (let i = 0, l = frame.length; i < l; i++) - Module._free(frame[i]); + alloca_offset = alloca_stack.pop(); } type _MemOffset = number | VoidPtr | NativePointer; +type _NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; export function setU8(offset: _MemOffset, value: number): void { Module.HEAPU8[offset] = value; @@ -40,8 +48,8 @@ export function setU16(offset: _MemOffset, value: number): void { Module.HEAPU16[offset >>> 1] = value; } -export function setU32(offset: _MemOffset, value: number): void { - Module.HEAPU32[offset >>> 2] = value; +export function setU32 (offset: _MemOffset, value: _NumberOrPointer) : void { + Module.HEAPU32[offset >>> 2] = value; } export function setI8(offset: _MemOffset, value: number): void { @@ -52,8 +60,8 @@ export function setI16(offset: _MemOffset, value: number): void { Module.HEAP16[offset >>> 1] = value; } -export function setI32(offset: _MemOffset, value: number): void { - Module.HEAP32[offset >>> 2] = value; +export function setI32 (offset: _MemOffset, value: _NumberOrPointer) : void { + Module.HEAP32[offset >>> 2] = value; } // NOTE: Accepts a number, not a BigInt, so values over Number.MAX_SAFE_INTEGER will be corrupted diff --git a/src/mono/wasm/runtime/method-binding.ts b/src/mono/wasm/runtime/method-binding.ts index 4827766f88c49..04010b20ab72b 100644 --- a/src/mono/wasm/runtime/method-binding.ts +++ b/src/mono/wasm/runtime/method-binding.ts @@ -2,11 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. import { WasmRoot, WasmRootBuffer, mono_wasm_new_root } from "./roots"; -import { MonoClass, MonoMethod, MonoObject, coerceNull, VoidPtrNull, MonoType } from "./types"; +import { MonoClass, MonoMethod, MonoObject, coerceNull, VoidPtrNull, MonoType, MarshalType } from "./types"; import { BINDING, Module, runtimeHelpers } from "./imports"; import { js_to_mono_enum, _js_to_mono_obj, _js_to_mono_uri } from "./js-to-cs"; import { js_string_to_mono_string, js_string_to_mono_string_interned } from "./strings"; -import { MarshalType, _unbox_mono_obj_root_with_known_nonprimitive_type } from "./cs-to-js"; +import { _unbox_mono_obj_root_with_known_nonprimitive_type } from "./cs-to-js"; import { _create_temp_frame, getI32, getU32, getF32, getF64, diff --git a/src/mono/wasm/runtime/roots.ts b/src/mono/wasm/runtime/roots.ts index 010732c23a894..2d473fb22ff20 100644 --- a/src/mono/wasm/runtime/roots.ts +++ b/src/mono/wasm/runtime/roots.ts @@ -10,6 +10,7 @@ let _scratch_root_buffer: WasmRootBuffer | null = null; let _scratch_root_free_indices: Int32Array | null = null; let _scratch_root_free_indices_count = 0; const _scratch_root_free_instances: WasmRoot[] = []; +const _external_root_free_instances: WasmExternalRoot[] = []; /** * Allocates a block of memory that can safely contain pointers into the managed heap. @@ -52,6 +53,26 @@ export function mono_wasm_new_root_buffer_from_pointer(offset: VoidPtr, capacity return new WasmRootBuffer(offset, capacity, false, name); } +/** + * Allocates a WasmRoot pointing to a root provided and controlled by external code. Typicaly on managed stack. + * Releasing this root will not de-allocate the root space. You still need to call .release(). + */ +export function mono_wasm_new_external_root(address: VoidPtr): WasmRoot { + let result: WasmExternalRoot; + + if (!address) + throw new Error("address must be a location in the native heap"); + + if (_external_root_free_instances.length > 0) { + result = _external_root_free_instances.pop()!; + result._set_address(address); + } else { + result = new WasmExternalRoot(address); + } + + return result; +} + /** * Allocates temporary storage for a pointer into the managed heap. * Pointers stored here will be visible to the GC, ensuring that the object they point to aren't moved or collected. @@ -68,7 +89,7 @@ export function mono_wasm_new_root(val const index = _mono_wasm_claim_scratch_index(); const buffer = _scratch_root_buffer; - result = new WasmRoot(buffer!, index); + result = new WasmJsOwnedRoot(buffer!, index); } if (value !== undefined) { @@ -239,7 +260,20 @@ export class WasmRootBuffer { } } -export class WasmRoot { +export interface WasmRoot { + get_address(): NativePointer; + get_address_32(): number; + get(): T; + set(value: T): T; + get value(): T; + set value(value: T); + valueOf(): T; + clear(): void; + release(): void; + toString(): string; +} + +class WasmJsOwnedRoot implements WasmRoot { private __buffer: WasmRootBuffer; private __index: number; @@ -301,3 +335,61 @@ export class WasmRoot { return `[root @${this.get_address()}]`; } } + +class WasmExternalRoot implements WasmRoot { + private __external_address: NativePointer = undefined; + private __external_address_32: number = undefined; + + constructor(address: NativePointer) { + this._set_address(address); + } + + _set_address(address: NativePointer): void { + this.__external_address = address; + this.__external_address_32 = address >>> 2; + } + + get_address(): NativePointer { + return this.__external_address; + } + + get_address_32(): number { + return this.__external_address_32; + } + + get(): T { + const result = Module.HEAPU32[this.__external_address_32]; + return result; + } + + set(value: T): T { + Module.HEAPU32[this.__external_address_32] = value; + return value; + } + + get value(): T { + return this.get(); + } + + set value(value: T) { + this.set(value); + } + + valueOf(): T { + return this.get(); + } + + clear(): void { + this.set(0); + } + + release(): void { + const maxPooledInstances = 128; + if (_external_root_free_instances.length < maxPooledInstances) + _external_root_free_instances.push(this); + } + + toString(): string { + return `[external root @${this.get_address()}]`; + } +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts index 02b4ce78e803a..cc0d1b24583e3 100644 --- a/src/mono/wasm/runtime/types.ts +++ b/src/mono/wasm/runtime/types.ts @@ -192,4 +192,48 @@ export function assert(condition: unknown, messsage: string): asserts condition if (!condition) { throw new Error(`Assert failed: ${messsage}`); } +} + +// see src/mono/wasm/driver.c MARSHAL_TYPE_xxx and Runtime.cs MarshalType +export const enum MarshalType { + NULL = 0, + INT = 1, + FP64 = 2, + STRING = 3, + VT = 4, + DELEGATE = 5, + TASK = 6, + OBJECT = 7, + BOOL = 8, + ENUM = 9, + URI = 22, + SAFEHANDLE = 23, + ARRAY_BYTE = 10, + ARRAY_UBYTE = 11, + ARRAY_UBYTE_C = 12, + ARRAY_SHORT = 13, + ARRAY_USHORT = 14, + ARRAY_INT = 15, + ARRAY_UINT = 16, + ARRAY_FLOAT = 17, + ARRAY_DOUBLE = 18, + FP32 = 24, + UINT32 = 25, + INT64 = 26, + UINT64 = 27, + CHAR = 28, + STRING_INTERNED = 29, + VOID = 30, + ENUM64 = 31, + POINTER = 32, + SPAN_BYTE = 33, +} + +// see src/mono/wasm/driver.c MARSHAL_ERROR_xxx and Runtime.cs +export const enum MarshalError { + BUFFER_TOO_SMALL = 512, + NULL_CLASS_POINTER = 513, + NULL_TYPE_POINTER = 514, + UNSUPPORTED_TYPE = 515, + FIRST = BUFFER_TOO_SMALL } \ No newline at end of file diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 4348444be6299..9de96a2749fcc 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -354,6 +354,27 @@ try { console.error(e); } +if (is_node) { + const modulesToLoad = processedArguments.setenv["NPM_MODULES"]; + if (modulesToLoad) { + modulesToLoad.split(',').forEach(module => { + const parts = module.split(':'); + + let message = `Loading npm '${parts[0]}'`; + const moduleExport = require(parts[0]); + if (parts.length == 2) { + message += ` and attaching to global as '${parts[1]}'.`; + globalThis[parts[1]] = moduleExport; + } + + console.log(message); + }); + } +} + +// Must be after loading npm modules. +processedArguments.setenv["IsWebSocketSupported"] = ("WebSocket" in globalThis).toString().toLowerCase(); + async function loadDotnet(file) { let loadScript = undefined; if (typeof WScript !== "undefined") { // Chakra diff --git a/src/native/corehost/fxr/host_context.cpp b/src/native/corehost/fxr/host_context.cpp index 82fe8c2b494dc..73af214ed3b8a 100644 --- a/src/native/corehost/fxr/host_context.cpp +++ b/src/native/corehost/fxr/host_context.cpp @@ -129,8 +129,8 @@ host_context_t::host_context_t( const corehost_context_contract &hostpolicy_context_contract) : marker { valid_host_context_marker } , type { type } - , hostpolicy_contract { hostpolicy_contract } - , hostpolicy_context_contract { hostpolicy_context_contract } + , hostpolicy_contract (hostpolicy_contract) + , hostpolicy_context_contract (hostpolicy_context_contract) { } void host_context_t::initialize_frameworks(const corehost_init_t& init) diff --git a/src/native/corehost/fxr/standalone/CMakeLists.txt b/src/native/corehost/fxr/standalone/CMakeLists.txt index 42785ac91d4b6..5e30750ab4a60 100644 --- a/src/native/corehost/fxr/standalone/CMakeLists.txt +++ b/src/native/corehost/fxr/standalone/CMakeLists.txt @@ -56,3 +56,7 @@ else() endif(WIN32) target_link_libraries(hostfxr libhostcommon) + +if (CLR_CMAKE_TARGET_ARCH_ARMV6) + target_link_libraries(${DOTNET_PROJECT_NAME} atomic) +endif() diff --git a/src/native/corehost/hostmisc/utils.cpp b/src/native/corehost/hostmisc/utils.cpp index 7f5fdbca40ab0..18e54a3e6d7f8 100644 --- a/src/native/corehost/hostmisc/utils.cpp +++ b/src/native/corehost/hostmisc/utils.cpp @@ -191,6 +191,8 @@ const pal::char_t* get_arch() return _X("x64"); #elif defined(TARGET_X86) return _X("x86"); +#elif defined(TARGET_ARMV6) + return _X("armv6"); #elif defined(TARGET_ARM) return _X("arm"); #elif defined(TARGET_ARM64) diff --git a/src/native/corehost/test/nativehost/CMakeLists.txt b/src/native/corehost/test/nativehost/CMakeLists.txt index c21e95a1c71d9..d8b23ca12ce56 100644 --- a/src/native/corehost/test/nativehost/CMakeLists.txt +++ b/src/native/corehost/test/nativehost/CMakeLists.txt @@ -58,3 +58,7 @@ endif() if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) target_link_libraries(${DOTNET_PROJECT_NAME} Ole32.lib OleAut32.lib) endif() + +if (CLR_CMAKE_TARGET_ARCH_ARMV6) + target_link_libraries(${DOTNET_PROJECT_NAME} atomic) +endif() diff --git a/src/native/eventpipe/ep-event-source.c b/src/native/eventpipe/ep-event-source.c index 78d1c4852b991..0da7ebc50caad 100644 --- a/src/native/eventpipe/ep-event-source.c +++ b/src/native/eventpipe/ep-event-source.c @@ -34,6 +34,8 @@ const ep_char8_t* _ep_os_info = "Unknown"; const ep_char8_t* _ep_arch_info = "x86"; #elif defined(TARGET_AMD64) const ep_char8_t* _ep_arch_info = "x64"; +#elif defined(TARGET_ARMV6) +const ep_char8_t* _ep_arch_info = "arm32"; #elif defined(TARGET_ARM) const ep_char8_t* _ep_arch_info = "arm32"; #elif defined(TARGET_ARM64) diff --git a/src/native/libs/Common/pal_utilities.h b/src/native/libs/Common/pal_utilities.h index 4e582ed6cd002..0bab812bd613e 100644 --- a/src/native/libs/Common/pal_utilities.h +++ b/src/native/libs/Common/pal_utilities.h @@ -43,6 +43,10 @@ #define CONST_CAST2(TOTYPE, FROMTYPE, X) ((union { FROMTYPE _q; TOTYPE _nq; }){ ._q = (X) }._nq) #define CONST_CAST(TYPE, X) CONST_CAST2(TYPE, const TYPE, (X)) +#ifndef __has_attribute +#define __has_attribute(x) (0) +#endif + #if __has_attribute(fallthrough) #define FALLTHROUGH __attribute__((fallthrough)) #else diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index 0e54f4b5f1519..b02a2ad1e6ca9 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -109,6 +109,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_LockFileRegion) DllImportEntry(SystemNative_LChflags) DllImportEntry(SystemNative_LChflagsCanSetHiddenFlag) + DllImportEntry(SystemNative_CanGetHiddenFlag) DllImportEntry(SystemNative_ReadProcessStatusInfo) DllImportEntry(SystemNative_Log) DllImportEntry(SystemNative_LogError) @@ -238,6 +239,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_Exit) DllImportEntry(SystemNative_Abort) DllImportEntry(SystemNative_UTimensat) + DllImportEntry(SystemNative_FUTimens) DllImportEntry(SystemNative_GetTimestamp) DllImportEntry(SystemNative_GetCpuUtilization) DllImportEntry(SystemNative_GetPwUidR) diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 66c934ed182fa..f6cf0d2aa23ea 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -332,6 +332,12 @@ int32_t SystemNative_Unlink(const char* path) intptr_t SystemNative_ShmOpen(const char* name, int32_t flags, int32_t mode) { +#if defined(SHM_NAME_MAX) // macOS + assert(strlen(name) <= SHM_NAME_MAX); +#elif defined(PATH_MAX) // other Unixes + assert(strlen(name) <= PATH_MAX); +#endif + #if HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP flags = ConvertOpenFlags(flags); if (flags == -1) @@ -1553,7 +1559,16 @@ int32_t SystemNative_LChflags(const char* path, uint32_t flags) int32_t SystemNative_LChflagsCanSetHiddenFlag(void) { -#if defined(UF_HIDDEN) && defined(HAVE_STAT_FLAGS) && defined(HAVE_LCHFLAGS) +#if defined(HAVE_LCHFLAGS) + return SystemNative_CanGetHiddenFlag(); +#else + return false; +#endif +} + +int32_t SystemNative_CanGetHiddenFlag(void) +{ +#if defined(UF_HIDDEN) && defined(HAVE_STAT_FLAGS) return true; #else return false; diff --git a/src/native/libs/System.Native/pal_io.h b/src/native/libs/System.Native/pal_io.h index 726b097aff133..6ebde79230af9 100644 --- a/src/native/libs/System.Native/pal_io.h +++ b/src/native/libs/System.Native/pal_io.h @@ -744,6 +744,13 @@ PALEXPORT int32_t SystemNative_LChflags(const char* path, uint32_t flags); */ PALEXPORT int32_t SystemNative_LChflagsCanSetHiddenFlag(void); +/** + * Determines if the current platform supports getting UF_HIDDEN (0x8000) flag + * + * Returns true (non-zero) if supported, false (zero) if not. + */ +PALEXPORT int32_t SystemNative_CanGetHiddenFlag(void); + /** * Reads the psinfo_t struct and converts into ProcessStatus. * diff --git a/src/native/libs/System.Native/pal_networkchange.c b/src/native/libs/System.Native/pal_networkchange.c index 725dfe677b952..b3b39ad3aaa83 100644 --- a/src/native/libs/System.Native/pal_networkchange.c +++ b/src/native/libs/System.Native/pal_networkchange.c @@ -35,6 +35,7 @@ Error SystemNative_CreateNetworkChangeListenerSocket(int32_t* retSocket) sa.nl_family = AF_NETLINK; sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE; int32_t sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + #elif HAVE_RT_MSGHDR int32_t sock = socket(PF_ROUTE, SOCK_RAW, 0); #endif @@ -44,6 +45,20 @@ Error SystemNative_CreateNetworkChangeListenerSocket(int32_t* retSocket) return (Error)(SystemNative_ConvertErrorPlatformToPal(errno)); } + // Added receive timeout to prevent recvmsg method in SystemNative_ReadEvents to block thread indefinitely. + // This allows method SystemNative_ReadEvents to periodically exit and allows .NET thread to exit if needed. + struct timeval tv; + tv.tv_sec = 1; //we will wait in SystemNative_ReadEvents method for max one second (TODO: is this good default value?) + tv.tv_usec = 0; + + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv) != 0) + { + *retSocket = -1; + Error palError = (Error)(SystemNative_ConvertErrorPlatformToPal(errno)); + close(sock); + return palError; + } + #if HAVE_LINUX_RTNETLINK_H if (bind(sock, (struct sockaddr*)(&sa), sizeof(sa)) != 0) { diff --git a/src/native/libs/System.Native/pal_runtimeinformation.h b/src/native/libs/System.Native/pal_runtimeinformation.h index adae223d48339..da39ac51d55ac 100644 --- a/src/native/libs/System.Native/pal_runtimeinformation.h +++ b/src/native/libs/System.Native/pal_runtimeinformation.h @@ -23,5 +23,6 @@ enum ARCH_ARM64, ARCH_WASM, ARCH_S390X, - ARCH_LOONGARCH64 + ARCH_LOONGARCH64, + ARCH_ARMV6, }; diff --git a/src/native/libs/System.Native/pal_time.c b/src/native/libs/System.Native/pal_time.c index 4f9b5326cb73c..8aaffe115fb46 100644 --- a/src/native/libs/System.Native/pal_time.c +++ b/src/native/libs/System.Native/pal_time.c @@ -53,6 +53,21 @@ int32_t SystemNative_UTimensat(const char* path, TimeSpec* times) return result; } +int32_t SystemNative_FUTimens(intptr_t fd, TimeSpec* times) +{ + int32_t result; + + struct timespec updatedTimes[2]; + updatedTimes[0].tv_sec = (time_t)times[0].tv_sec; + updatedTimes[0].tv_nsec = (long)times[0].tv_nsec; + updatedTimes[1].tv_sec = (time_t)times[1].tv_sec; + updatedTimes[1].tv_nsec = (long)times[1].tv_nsec; + + while (CheckInterrupted(result = futimens(ToFileDescriptor(fd), updatedTimes))); + + return result; +} + uint64_t SystemNative_GetTimestamp() { #if HAVE_CLOCK_GETTIME_NSEC_NP diff --git a/src/native/libs/System.Native/pal_time.h b/src/native/libs/System.Native/pal_time.h index 12fe500133418..c7ef77da1e5bd 100644 --- a/src/native/libs/System.Native/pal_time.h +++ b/src/native/libs/System.Native/pal_time.h @@ -27,6 +27,13 @@ typedef struct ProcessCpuInformation */ PALEXPORT int32_t SystemNative_UTimensat(const char* path, TimeSpec* times); +/** + * Sets the last access and last modified time of a file + * + * Returns 0 on success; otherwise, returns -1 and errno is set. + */ +PALEXPORT int32_t SystemNative_FUTimens(intptr_t fd, TimeSpec* times); + /** * Gets a high-resolution timestamp that can be used for time-interval measurements. */ diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 0b38944d502e8..a64aac0c676e9 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -270,6 +270,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); LEGACY_FUNCTION(ERR_load_crypto_strings) \ LIGHTUP_FUNCTION(ERR_new) \ REQUIRED_FUNCTION(ERR_peek_error) \ + REQUIRED_FUNCTION(ERR_peek_error_line) \ REQUIRED_FUNCTION(ERR_peek_last_error) \ FALLBACK_FUNCTION(ERR_put_error) \ REQUIRED_FUNCTION(ERR_reason_error_string) \ @@ -728,6 +729,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define ERR_load_crypto_strings ERR_load_crypto_strings_ptr #define ERR_new ERR_new_ptr #define ERR_peek_error ERR_peek_error_ptr +#define ERR_peek_error_line ERR_peek_error_line_ptr #define ERR_peek_last_error ERR_peek_last_error_ptr #define ERR_put_error ERR_put_error_ptr #define ERR_reason_error_string ERR_reason_error_string_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c index 6839d4c2fe04e..79de386f09721 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c @@ -152,20 +152,59 @@ EVP_PKEY* CryptoNative_DecodePkcs8PrivateKey(const uint8_t* buf, int32_t len, in return key; } -int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey) +int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey, int32_t* p8size) { assert(pkey != NULL); + assert(p8size != NULL); + + *p8size = 0; + ERR_clear_error(); PKCS8_PRIV_KEY_INFO* p8 = EVP_PKEY2PKCS8(pkey); if (p8 == NULL) { + // OpenSSL 1.1 and 3 have a behavioral change with EVP_PKEY2PKCS8 + // with regard to handling EVP_PKEYs that do not contain a private key. + // + // In OpenSSL 1.1, it would always succeed, but the private parameters + // would be missing (thus making an invalid PKCS8 structure). + // Over in the managed side, we detect these invalid PKCS8 blobs and + // convert that to a "no private key" error. + // + // In OpenSSL 3, this now correctly errors, with the error + // ASN1_R_ILLEGAL_ZERO_CONTENT. We want to preserve allocation failures + // as OutOfMemoryException. So we peek at the error. If it's a malloc + // failure, -1 is returned to indcate "throw what is on the error queue". + // If the error is not a malloc failure, return -2 to mean "no private key". + // If OpenSSL ever changes the error to something more to explicitly mean + // "no private key" then we should test for that explicitly. Until then, + // we treat all errors, except a malloc error, to mean "no private key". + + const char* file = NULL; + int line = 0; + unsigned long error = ERR_peek_error_line(&file, &line); + + // If it's not a malloc failure, assume it's because the private key is + // missing. + if (ERR_GET_REASON(error) != ERR_R_MALLOC_FAILURE) + { + ERR_clear_error(); + return -2; + } + + // It is a malloc failure. Clear the error queue and set the error + // as a malloc error so it's the only error in the queue. + ERR_clear_error(); + ERR_put_error(ERR_GET_LIB(error), 0, ERR_R_MALLOC_FAILURE, file, line); + return -1; } - int ret = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL); + *p8size = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL); PKCS8_PRIV_KEY_INFO_free(p8); - return ret; + + return *p8size < 0 ? -1 : 1; } int32_t CryptoNative_EncodePkcs8PrivateKey(EVP_PKEY* pkey, uint8_t* buf) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h index 012ac98e03db2..fac7ee32b5bbc 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h @@ -58,9 +58,13 @@ Requres a non-null buf, and len > 0. PALEXPORT EVP_PKEY* CryptoNative_DecodePkcs8PrivateKey(const uint8_t* buf, int32_t len, int32_t algId); /* -Reports the number of bytes rqeuired to encode an EVP_PKEY* as a Pkcs8PrivateKeyInfo, or a negative value on error. +Gets the number of bytes rqeuired to encode an EVP_PKEY* as a Pkcs8PrivateKeyInfo. + +On success, 1 is returned and p8size contains the size of the Pkcs8PrivateKeyInfo. +On failure, -1 is used to indicate the openssl error queue contains the error. +On failure, -2 is used to indcate that the supplied EVP_PKEY* is possibly missing a private key. */ -PALEXPORT int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey); +PALEXPORT int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey, int32_t* p8size); /* Encodes the EVP_PKEY* as a Pkcs8PrivateKeyInfo, writing the encoded value to buf. diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 9526a602876f2..34b42e2db3ad6 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -478,7 +478,9 @@ private static bool IsBlittable (Type type) private static void Error (string msg) => throw new LogAsErrorException(msg); } +#pragma warning disable CA1067 internal sealed class PInvoke : IEquatable +#pragma warning restore CA1067 { public PInvoke(string entryPoint, string module, MethodInfo method) { diff --git a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs index 9d27d24c46080..fa92071c917e8 100644 --- a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs +++ b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs @@ -10,7 +10,7 @@ public static class OptionsHelper private const string PriorityOption = "build_property.Priority"; private const string RuntimeFlavorOption = "build_property.RuntimeFlavor"; private const string IsOutOfProcessTestAssemblyOption = "build_metadata.AdditionalFiles.IsOutOfProcessTestAssembly"; - private const string TestFilterOption = "build_metadata.AdditionalFiles.TestFilter"; + private const string TestFilterOption = "build_property.TestFilter"; private const string TestAssemblyRelativePathOption = "build_metadata.AdditionalFiles.TestAssemblyRelativePath"; private const string TestDisplayNameOption = "build_metadata.AdditionalFiles.TestDisplayName"; private const string SingleTestDisplayNameOption = "build_metadata.AdditionalFiles.SingleTestDisplayName"; diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index eb4295c06cc33..7b12b995f6801 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -402,7 +402,7 @@ private static IEnumerable GetTestMethodInfosForMethod(IMethodSymbol } break; case "Xunit.SkipOnMonoAttribute": - if (options.GlobalOptions.RuntimeFlavor() != "Mono") + if (options.GlobalOptions.RuntimeFlavor().ToLowerInvariant() != "mono") { // If we're building tests not for Mono, we can skip handling the specifics of the SkipOnMonoAttribute. continue; @@ -419,7 +419,7 @@ private static IEnumerable GetTestMethodInfosForMethod(IMethodSymbol testInfos = FilterForSkippedTargetFrameworkMonikers(testInfos, (int)filterAttribute.ConstructorArguments[0].Value!); break; case "Xunit.SkipOnCoreClrAttribute": - if (options.GlobalOptions.RuntimeFlavor() != "CoreCLR") + if (options.GlobalOptions.RuntimeFlavor().ToLowerInvariant() != "coreclr") { // If we're building tests not for CoreCLR, we can skip handling the specifics of the SkipOnCoreClrAttribute. continue; @@ -599,12 +599,12 @@ private static ImmutableArray CreateTestCases(IMethodSymbol method, L private static ImmutableArray FilterForSkippedRuntime(ImmutableArray testInfos, int skippedRuntimeValue, AnalyzerConfigOptionsProvider options) { Xunit.TestRuntimes skippedRuntimes = (Xunit.TestRuntimes)skippedRuntimeValue; - string runtimeFlavor = options.GlobalOptions.RuntimeFlavor(); - if (runtimeFlavor == "Mono" && skippedRuntimes.HasFlag(Xunit.TestRuntimes.Mono)) + string runtimeFlavor = options.GlobalOptions.RuntimeFlavor().ToLowerInvariant(); + if (runtimeFlavor == "mono" && skippedRuntimes.HasFlag(Xunit.TestRuntimes.Mono)) { return ImmutableArray.Empty; } - else if (runtimeFlavor == "CoreCLR" && skippedRuntimes.HasFlag(Xunit.TestRuntimes.CoreCLR)) + else if (runtimeFlavor == "coreclr" && skippedRuntimes.HasFlag(Xunit.TestRuntimes.CoreCLR)) { return ImmutableArray.Empty; } diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index c8d6e0d31e59e..aae081a187126 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -62,6 +62,7 @@ COMPlus_JitEdgeProfiling; COMPlus_JitRandomGuardedDevirtualization; COMPlus_JitRandomEdgeCounts; + COMPlus_JitRandomOnStackReplacement; RunningIlasmRoundTrip @@ -187,6 +188,7 @@ + diff --git a/src/tests/Common/tests.targets b/src/tests/Common/tests.targets index ff6ba352e24cc..a99db7918fd22 100644 --- a/src/tests/Common/tests.targets +++ b/src/tests/Common/tests.targets @@ -66,17 +66,6 @@ $(XunitArgs) -nocolor - - $(CORE_ROOT)\corerun - $(CORE_ROOT)\corerun.exe - - - dotnet --roll-forward LatestMajor - $(DotnetRoot)/dotnet - true - $(DotnetExecutable) - $(CorerunExecutable) $(XunitConsoleRunner) @(TestAssemblies->'%(Identity)', ' ') $(XunitArgs) + $(DotNetCli) --roll-forward latestmajor $(XunitConsoleRunner) @(TestAssemblies->'%(Identity)', ' ') $(XunitArgs) false true WasmTestOnBrowser + $(TestArchiveRoot)browseronly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER 42 main.js false diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj index d9c7984051cd3..90d9fa155b924 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj +++ b/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj @@ -2,6 +2,9 @@ true WasmTestOnBrowser + $(TestArchiveRoot)browseronly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER 42 main.js diff --git a/src/tests/GC/API/Frozen/Frozen.cs b/src/tests/GC/API/Frozen/Frozen.cs new file mode 100644 index 0000000000000..3a9ad49175064 --- /dev/null +++ b/src/tests/GC/API/Frozen/Frozen.cs @@ -0,0 +1,188 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace HelloFrozenSegment +{ + using System; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Runtime.CompilerServices; + + struct FrozenSegment + { + IntPtr underlyingSegment; + IntPtr underlyingBuffer; + + public FrozenSegment(IntPtr underlyingSegment, IntPtr underlyingBuffer) + { + this.underlyingSegment = underlyingSegment; + this.underlyingBuffer = underlyingBuffer; + } + + public void Release() + { + GCHelpers.UnregisterFrozenSegment(this.underlyingSegment); + Marshal.FreeHGlobal(this.underlyingBuffer); + } + } + + internal static class GCHelpers + { + private static MethodInfo s_registerFrozenSegmentMethod; + private static MethodInfo s_unregisterFrozenSegmentMethod; + + private static MethodInfo RegisterFrozenSegmentMethod + { + get + { + if (s_registerFrozenSegmentMethod == null) + { + s_registerFrozenSegmentMethod = typeof(GC).GetMethod("_RegisterFrozenSegment", BindingFlags.NonPublic|BindingFlags.Static); + } + + return s_registerFrozenSegmentMethod; + } + } + + private static MethodInfo UnregisterFrozenSegmentMethod + { + get + { + if (s_unregisterFrozenSegmentMethod == null) + { + s_unregisterFrozenSegmentMethod = typeof(GC).GetMethod("_UnregisterFrozenSegment", BindingFlags.NonPublic|BindingFlags.Static); + } + + return s_unregisterFrozenSegmentMethod; + } + } + + public static IntPtr RegisterFrozenSegment(IntPtr buffer, nint size) + { + return (IntPtr)RegisterFrozenSegmentMethod.Invoke(null, new object[]{buffer, size}); + + } + + public static void UnregisterFrozenSegment(IntPtr segment) + { + UnregisterFrozenSegmentMethod.Invoke(null, new object[]{segment}); + } + } + + internal unsafe class FrozenSegmentBuilder + { + private IntPtr _buffer; + private IntPtr _allocated; + private IntPtr _limit; + + // This only work for BaseSize (i.e. not arrays) + private static unsafe short GetObjectSize(IntPtr methodTable) + { + IntPtr pointerToSize = methodTable + 4; + return *((short*)pointerToSize); + } + + public FrozenSegmentBuilder(int capacity) + { + _buffer = Marshal.AllocHGlobal(capacity); + for (int i = 0; i < capacity; i++) + { + *((byte*)(_buffer + i)) = 0; + } + _allocated = _buffer + IntPtr.Size; + _limit = _buffer + capacity; + } + + public IntPtr Allocate(IntPtr methodTable) + { + if (_allocated == IntPtr.Zero) + { + throw new Exception("Segment already built"); + } + int objectSize = GetObjectSize(methodTable); + if ((_allocated + objectSize).CompareTo(_limit) > 0) + { + throw new Exception("OutOfCapacity"); + } + + IntPtr* pMethodTable = (IntPtr*)_allocated; + *pMethodTable = methodTable; + IntPtr result = _allocated; + _allocated = _allocated + objectSize; + return result; + } + + public FrozenSegment GetSegment() + { + if (_allocated == IntPtr.Zero) + { + throw new Exception("Segment already built"); + } + + nint size = (nint)(_allocated.ToInt64() - _buffer.ToInt64()); + _allocated = IntPtr.Zero; + IntPtr segment = GCHelpers.RegisterFrozenSegment(_buffer, size); + return new FrozenSegment(segment, _buffer); + } + } + + internal class Node + { + public Node next; + public int number; + } + + internal static class Program + { + private static unsafe IntPtr GetMethodTablePointer(object obj) + { + GCHandle gch = GCHandle.Alloc(obj); + IntPtr pointerToPointerToObject = GCHandle.ToIntPtr(gch); + IntPtr pointerToObject = *((IntPtr*)pointerToPointerToObject); + IntPtr methodTable = *((IntPtr*)pointerToObject); + gch.Free(); + return methodTable; + } + + private static unsafe int Main(string[] args) + { + Node template = new Node(); + IntPtr methodTable = GetMethodTablePointer(template); + + FrozenSegmentBuilder frozenSegmentBuilder = new FrozenSegmentBuilder(1000); + IntPtr node1Ptr = frozenSegmentBuilder.Allocate(methodTable); + IntPtr node2Ptr = frozenSegmentBuilder.Allocate(methodTable); + + FrozenSegment frozenSegment = frozenSegmentBuilder.GetSegment(); + Node root = new Node(); + Node node1 = Unsafe.AsRef((void*)&node1Ptr); + Node node2 = Unsafe.AsRef((void*)&node2Ptr); + // It is okay for any object to reference a frozen object. + root.next = node1; + + // It is not okay for a frozen object to reference another frozen object + // This is because the WriteBarrier code may (depending on the pointer + // value returned by AllocHGlobal) determine node2 to be an ephemeral object + // when it isn't. + // node1.next = node2; + + // It is not okay for a frozen object to reference another object that is not frozen + // This is because we may miss the marking of the new Node or miss the relocation + // of the new Node. + // node2.next = new Node(); + + // Making changes to non-GC references is fine + node1.number = 10086; + node2.number = 12580; + + GC.Collect(); + node1 = null; + GC.Collect(); + node2 = null; + GC.Collect(); + Console.WriteLine(root.next.next != null); + frozenSegment.Release(); + return 100; + } + } +} diff --git a/src/tests/GC/API/Frozen/Frozen.csproj b/src/tests/GC/API/Frozen/Frozen.csproj new file mode 100644 index 0000000000000..365f9ae36ae06 --- /dev/null +++ b/src/tests/GC/API/Frozen/Frozen.csproj @@ -0,0 +1,16 @@ + + + Exe + true + 1 + true + true + + + + PdbOnly + + + + + diff --git a/src/tests/Interop/CMakeLists.txt b/src/tests/Interop/CMakeLists.txt index 35f34f87d6b49..289dac39c27c9 100644 --- a/src/tests/Interop/CMakeLists.txt +++ b/src/tests/Interop/CMakeLists.txt @@ -60,6 +60,7 @@ add_subdirectory(ICustomMarshaler/ConflictingNames) add_subdirectory(ICustomMarshaler/Primitives) add_subdirectory(LayoutClass) add_subdirectory(PInvoke/DateTime) +add_subdirectory(DisabledRuntimeMarshalling) if(CLR_CMAKE_TARGET_WIN32) add_subdirectory(ExecInDefAppDom) add_subdirectory(MarshalAPI/IUnknown) diff --git a/src/tests/Interop/COM/ComWrappers/API/Program.cs b/src/tests/Interop/COM/ComWrappers/API/Program.cs index 99a2094c80b91..b5f6b4d09cfdc 100644 --- a/src/tests/Interop/COM/ComWrappers/API/Program.cs +++ b/src/tests/Interop/COM/ComWrappers/API/Program.cs @@ -6,6 +6,7 @@ namespace ComWrappersTests using System; using System.Collections; using System.Collections.Generic; + using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -376,7 +377,7 @@ public enum FailureMode throw new Exception() { HResult = ExceptionErrorCode }; default: Assert.True(false, "Invalid failure mode"); - throw new Exception("UNREACHABLE"); + throw new UnreachableException(); } } @@ -390,7 +391,7 @@ protected override object CreateObject(IntPtr externalComObject, CreateObjectFla throw new Exception() { HResult = ExceptionErrorCode }; default: Assert.True(false, "Invalid failure mode"); - throw new Exception("UNREACHABLE"); + throw new UnreachableException(); } } diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/AutoLayout.cs b/src/tests/Interop/DisabledRuntimeMarshalling/AutoLayout.cs new file mode 100644 index 0000000000000..2f5166a18d21d --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/AutoLayout.cs @@ -0,0 +1,54 @@ +// 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.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling; + +public unsafe class PInvokes_AutoLayout +{ + [Fact] + public static void AutoLayoutStruct() + { + short s = 42; + bool b = true; + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithAutoLayoutStruct(new AutoLayoutStruct())); + } + + [Fact] + public static void StructWithAutoLayoutField() + { + short s = 42; + bool b = true; + AssertThrowsMarshalDirectiveOrTypeLoad(() => DisabledRuntimeMarshallingNative.CallWithAutoLayoutStruct(new SequentialWithAutoLayoutField())); + } + + [Fact] + public static void StructWithNestedAutoLayoutField() + { + short s = 42; + bool b = true; + AssertThrowsMarshalDirectiveOrTypeLoad(() => DisabledRuntimeMarshallingNative.CallWithAutoLayoutStruct(new SequentialWithAutoLayoutNestedField())); + } + + private static void AssertThrowsMarshalDirectiveOrTypeLoad(Action testCode) + { + try + { + testCode(); + return; + } + catch (Exception ex) when(ex is MarshalDirectiveException or TypeLoadException) + { + return; + } + catch (Exception ex) + { + Assert.False(true, $"Expected either a MarshalDirectiveException or a TypeLoadException, but received a '{ex.GetType().FullName}' exception: '{ex.ToString()}'"); + } + Assert.False(true, $"Expected either a MarshalDirectiveException or a TypeLoadException, but received no exception."); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/CMakeLists.txt b/src/tests/Interop/DisabledRuntimeMarshalling/CMakeLists.txt new file mode 100644 index 0000000000000..018819bf33073 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/CMakeLists.txt @@ -0,0 +1,10 @@ +project (DisabledRuntimeMarshallingNative) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES DisabledRuntimeMarshallingNative.cpp ) + +# add the executable +add_library (DisabledRuntimeMarshallingNative SHARED ${SOURCES}) +target_link_libraries(DisabledRuntimeMarshallingNative ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS DisabledRuntimeMarshallingNative DESTINATION bin) diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshallingNative.cpp b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshallingNative.cpp new file mode 100644 index 0000000000000..e0a0a9e7f32a1 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshallingNative.cpp @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +struct StructWithShortAndBool +{ + bool b; + short s; + // Make sure we don't have any cases where the native code could return a value of this type one way, + // but an invalid managed declaration would expect it differently. This ensures that test failures won't be + // due to crashes from a mismatched return scheme in the calling convention. + int padding; +}; + +struct StructWithWCharAndShort +{ + short s; + WCHAR c; +}; + +extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithShortAndBool(StructWithShortAndBool str, short s, bool b) +{ + return str.s == s && str.b == b; +} + +extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithWCharAndShort(StructWithWCharAndShort str, short s, WCHAR c) +{ + return str.s == s && str.c == c; +} + +using CheckStructWithShortAndBoolCallback = bool (STDMETHODCALLTYPE*)(StructWithShortAndBool, short, bool); + +extern "C" DLL_EXPORT CheckStructWithShortAndBoolCallback STDMETHODCALLTYPE GetStructWithShortAndBoolCallback() +{ + return &CheckStructWithShortAndBool; +} + +extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CallCheckStructWithShortAndBoolCallback(CheckStructWithShortAndBoolCallback cb, StructWithShortAndBool str, short s, bool b) +{ + return cb(str, s, b); +} + +extern "C" DLL_EXPORT BYTE PassThrough(BYTE b) +{ + return b; +} + +extern "C" DLL_EXPORT void Invalid(...) {} + + +extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithShortAndBoolWithVariantBool(StructWithShortAndBool str, short s, VARIANT_BOOL b) +{ + // Specifically use VARIANT_TRUE here as invalid marshalling (in the "disabled runtime marshalling" case) will incorrectly marshal VARAINT_TRUE + // but could accidentally marshal VARIANT_FALSE correctly since it is 0, which is the same representation as a zero or sign extension of the C# false value. + return str.s == s && str.b == (b == VARIANT_TRUE); +} + +using CheckStructWithShortAndBoolWithVariantBoolCallback = bool (STDMETHODCALLTYPE*)(StructWithShortAndBool, short, VARIANT_BOOL); + +extern "C" DLL_EXPORT CheckStructWithShortAndBoolWithVariantBoolCallback STDMETHODCALLTYPE GetStructWithShortAndBoolWithVariantBoolCallback() +{ + return &CheckStructWithShortAndBoolWithVariantBool; +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyDisabled.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyDisabled.csproj new file mode 100644 index 0000000000000..2de6caeb97d02 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyDisabled.csproj @@ -0,0 +1,13 @@ + + + true + + + + + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyEnabled.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyEnabled.csproj new file mode 100644 index 0000000000000..88ce904b51e4b --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeAssemblyEnabled.csproj @@ -0,0 +1,13 @@ + + + true + + + + + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly.csproj new file mode 100644 index 0000000000000..702588382eb33 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly.csproj @@ -0,0 +1,11 @@ + + + true + + + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly_ro.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly_ro.csproj new file mode 100644 index 0000000000000..b947e14f0b891 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_Disabled_NativeTypeInAssembly_ro.csproj @@ -0,0 +1,14 @@ + + + true + + None + true + + + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_NativeAssemblyDisabled.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_NativeAssemblyDisabled.csproj new file mode 100644 index 0000000000000..61ddd72ac618b --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/DisabledRuntimeMarshalling_NativeAssemblyDisabled.csproj @@ -0,0 +1,14 @@ + + + true + + + + + + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/FunctionPointers.cs b/src/tests/Interop/DisabledRuntimeMarshalling/FunctionPointers.cs new file mode 100644 index 0000000000000..927c175623629 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/FunctionPointers.cs @@ -0,0 +1,29 @@ +// 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.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling; + +public unsafe class FunctionPointers +{ + [Fact] + public static void StructWithDefaultNonBlittableFields_DoesNotMarshal() + { + short s = 42; + bool b = true; + Assert.True(DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolCallback()(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + public static void StructWithDefaultNonBlittableFields_IgnoresMarshalAsInfo() + { + short s = 41; + bool b = true; + + Assert.False(DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolWithVariantBoolCallback()(new StructWithShortAndBool(s, b), s, b)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative.cs b/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative.cs new file mode 100644 index 0000000000000..5be5549f7b157 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative.cs @@ -0,0 +1,153 @@ +// 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.Runtime.InteropServices; +using Xunit; + +public unsafe class DisabledRuntimeMarshallingNative +{ + public struct StructWithShortAndBool + { + public bool b; + public short s; + int padding; + + public StructWithShortAndBool(short s, bool b) + { + this.s = s; + this.b = b; + this.padding = 0xdeadbee; + } + } + + public struct StructWithShortAndBoolWithMarshalAs + { + [MarshalAs(UnmanagedType.U1)] + bool b; + short s; + int padding; + + public StructWithShortAndBoolWithMarshalAs(short s, bool b) + { + this.s = s; + this.b = b; + this.padding = 0xdeadbee; + } + } + + public struct StructWithWCharAndShort + { + short s; + [MarshalAs(UnmanagedType.U2)] + char c; + + public StructWithWCharAndShort(short s, char c) + { + this.s = s; + this.c = c; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct StructWithWCharAndShortWithMarshalAs + { + short s; + [MarshalAs(UnmanagedType.U2)] + char c; + + public StructWithWCharAndShortWithMarshalAs(short s, char c) + { + this.s = s; + this.c = c; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct StructWithShortAndGeneric + { + short s; + T t; + public StructWithShortAndGeneric(short s, T t) + { + this.s = s; + this.t = t; + } + } + + [StructLayout(LayoutKind.Auto)] + public struct AutoLayoutStruct + { + int i; + } + + public struct SequentialWithAutoLayoutField + { + AutoLayoutStruct auto; + } + + public struct SequentialWithAutoLayoutNestedField + { + SequentialWithAutoLayoutField field; + } + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithShortAndBool(StructWithShortAndBool str, short s, bool b); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithShortAndBool(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.Bool)] bool b); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShort str, short s, char c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithWCharAndShort(StructWithShortAndGeneric str, short s, char c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithWCharAndShort(StructWithShortAndGeneric str, short s, short c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShortWithMarshalAs str, short s, [MarshalAs(UnmanagedType.U1)] char c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern delegate* unmanaged GetStructWithShortAndBoolCallback(); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CallCheckStructWithShortAndBoolCallback(delegate* cb, StructWithShortAndBool str, short s, bool b); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern delegate* unmanaged GetStructWithShortAndBoolWithVariantBoolCallback(); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "PassThrough")] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool GetByteAsBool(byte b); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(AutoLayoutStruct s); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(SequentialWithAutoLayoutField s); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(SequentialWithAutoLayoutNestedField s); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithShortAndBoolWithVariantBool(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.VariantBool)] bool b); + + // Apply the UnmanagedFunctionPointer attributes with the default calling conventions so that Mono's AOT compiler + // recognizes that these delegate types are used in interop and should have managed->native thunks generated for them. + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate bool CheckStructWithShortAndBoolCallback(StructWithShortAndBool str, short s, bool b); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate bool CheckStructWithShortAndBoolWithMarshalAsAndVariantBoolCallback(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.VariantBool)] bool b); + + [UnmanagedCallersOnly] + public static bool CheckStructWithShortAndBoolManaged(StructWithShortAndBool str, short s, bool b) + { + return str.s == s && str.b == b; + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative_Default.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative_Default.csproj new file mode 100644 index 0000000000000..e06e1e391659f --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/Native_Default/DisabledRuntimeMarshallingNative_Default.csproj @@ -0,0 +1,10 @@ + + + Library + SharedLibrary + true + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs new file mode 100644 index 0000000000000..ed9b121bef6a2 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs @@ -0,0 +1,190 @@ +// 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.Runtime.InteropServices; +using Xunit; + +public unsafe class DisabledRuntimeMarshallingNative +{ + public struct StructWithShortAndBool + { + public bool b; + public short s; + int padding; + + public StructWithShortAndBool(short s, bool b) + { + this.s = s; + this.b = b; + this.padding = 0xdeadbee; + } + } + + public struct StructWithShortAndBoolWithMarshalAs + { + [MarshalAs(UnmanagedType.VariantBool)] + bool b; + short s; + int padding; + + public StructWithShortAndBoolWithMarshalAs(short s, bool b) + { + this.s = s; + this.b = b; + this.padding = 0xdeadbee; + } + } + + public struct StructWithWCharAndShort + { + short s; + char c; + + public StructWithWCharAndShort(short s, char c) + { + this.s = s; + this.c = c; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct StructWithWCharAndShortWithMarshalAs + { + short s; + [MarshalAs(UnmanagedType.U1)] + char c; + + public StructWithWCharAndShortWithMarshalAs(short s, char c) + { + this.s = s; + this.c = c; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct StructWithShortAndGeneric + { + short s; + T t; + public StructWithShortAndGeneric(short s, T t) + { + this.s = s; + this.t = t; + } + } + + public struct StructWithString + { + string s; + + public StructWithString(string s) + { + this.s = s; + } + } + + [StructLayout(LayoutKind.Sequential)] + public class LayoutClass + {} + + [StructLayout(LayoutKind.Auto)] + public struct AutoLayoutStruct + { + int i; + } + + public struct SequentialWithAutoLayoutField + { + AutoLayoutStruct auto; + } + + public struct SequentialWithAutoLayoutNestedField + { + SequentialWithAutoLayoutField field; + } + + public enum ByteEnum : byte + { + Value = 42 + } + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithShortAndBool(StructWithShortAndBool str, short s, bool b); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithShortAndBool(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.I4)] bool b); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShort str, short s, char c); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShortWithMarshalAs str, short s, char c); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithWCharAndShort(StructWithShortAndGeneric str, short s, char c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CheckStructWithWCharAndShort(StructWithShortAndGeneric str, short s, short c); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid", CharSet = CharSet.Ansi)] + public static extern void CheckStringWithAnsiCharSet(string s); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid", CharSet = CharSet.Unicode)] + public static extern void CheckStringWithUnicodeCharSet(string s); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid", CharSet = CharSet.Unicode)] + public static extern string GetStringWithUnicodeCharSet(); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CheckStructWithStructWithString(StructWithString s); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CheckLayoutClass(LayoutClass c); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid", SetLastError = true)] + public static extern void CallWithSetLastError(); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + [LCIDConversion(0)] + public static extern void CallWithLCID(); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid", PreserveSig = false)] + public static extern int CallWithHResultSwap(); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(AutoLayoutStruct s); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(SequentialWithAutoLayoutField s); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithAutoLayoutStruct(SequentialWithAutoLayoutNestedField s); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithByRef(ref int i); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithVarargs(__arglist); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern delegate* unmanaged GetStructWithShortAndBoolCallback(); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern delegate* unmanaged GetStructWithShortAndBoolWithVariantBoolCallback(); + + [DllImport(nameof(DisabledRuntimeMarshallingNative))] + public static extern bool CallCheckStructWithShortAndBoolCallback(delegate* unmanaged cb, StructWithShortAndBool str, short s, bool b); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "PassThrough")] + public static extern bool GetByteAsBool(byte b); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "PassThrough")] + public static extern byte GetEnumUnderlyingValue(ByteEnum b); + + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "CheckStructWithShortAndBoolWithVariantBool")] + [return:MarshalAs(UnmanagedType.U1)] + public static extern bool CheckStructWithShortAndBoolWithVariantBool_FailureExpected(StructWithShortAndBool str, short s, [MarshalAs(UnmanagedType.VariantBool)] bool b); + + // Apply the UnmanagedFunctionPointer attributes with the default calling conventions so that Mono's AOT compiler + // recognizes that these delegate types are used in interop and should have managed->native thunks generated for them. + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate bool CheckStructWithShortAndBoolCallback(StructWithShortAndBool str, short s, bool b); + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate bool CheckStructWithShortAndBoolWithVariantBoolCallback(StructWithShortAndBool str, short s, [MarshalAs(UnmanagedType.VariantBool)] bool b); + + [UnmanagedCallersOnly] + public static bool CheckStructWithShortAndBoolManaged(StructWithShortAndBool str, short s, bool b) + { + return str.s == s && str.b == b; + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj new file mode 100644 index 0000000000000..c3572ce1ae3a5 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj @@ -0,0 +1,11 @@ + + + Library + SharedLibrary + true + + + + + + diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/Delegates.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/Delegates.cs new file mode 100644 index 0000000000000..a4eb0f33159d0 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/Delegates.cs @@ -0,0 +1,34 @@ +// 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.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingDisabled; + +public unsafe class DelegatesFromExternalAssembly +{ + [Fact] + public static void StructWithDefaultNonBlittableFields_DoesNotMarshal() + { + short s = 42; + bool b = true; + + var callback = Marshal.GetDelegateForFunctionPointer((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolCallback()); + + Assert.True(callback(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + public static void StructWithDefaultNonBlittableFields_IgnoresMarshalAsInfo() + { + short s = 41; + bool b = true; + + var callback = Marshal.GetDelegateForFunctionPointer((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolWithVariantBoolCallback()); + + Assert.False(callback(new StructWithShortAndBool(s, b), s, b)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs new file mode 100644 index 0000000000000..4fa7315d43063 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingDisabled; + +public class PInvokes +{ + + [Fact] + public static void StructWithDefaultNonBlittableFields_MarshalAsInfo() + { + short s = 41; + bool b = true; + + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); + + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShortWithMarshalAs(s, c), s, c)); + } + + [Fact] + public static void Strings_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckStringWithAnsiCharSet("")); + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckStringWithUnicodeCharSet("")); + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckStructWithStructWithString(new StructWithString(""))); + Assert.Throws(() => DisabledRuntimeMarshallingNative.GetStringWithUnicodeCharSet()); + } + + [Fact] + public static void LayoutClass_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckLayoutClass(new LayoutClass())); + } + + [Fact] + public static void SetLastError_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithSetLastError()); + } + + [Fact] + [SkipOnMono("Mono does not support LCIDs at all and it is not worth the effort to add support just to make it throw an exception.")] + public static void LCID_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithLCID()); + } + + [Fact] + [SkipOnMono("Mono does not support PreserveSig=False in P/Invokes and it is not worth the effort to add support just to make it throw an exception.")] + public static void PreserveSig_False_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithHResultSwap()); + } + + [Fact] + public static void Varargs_NotSupported() + { + AssertThrowsCorrectException(() => DisabledRuntimeMarshallingNative.CallWithVarargs(__arglist(1, 2, 3))); + + static void AssertThrowsCorrectException(Action testCode) + { + try + { + testCode(); + return; + } +#pragma warning disable CS0618 // ExecutionEngineException has an ObsoleteAttribute + catch (Exception ex) when(ex is MarshalDirectiveException or InvalidProgramException or ExecutionEngineException) +#pragma warning restore CS0618 + { + // CoreCLR is expected to throw MarshalDirectiveException + // JIT-enabled Mono is expected to throw an InvalidProgramException + // AOT-only Mono throws an ExecutionEngineException when attempting to JIT the callback that would throw the InvalidProgramException. + return; + } + catch (Exception ex) + { + Assert.False(true, $"Expected either a MarshalDirectiveException, InvalidProgramException, or ExecutionEngineException, but received a '{ex.GetType().FullName}' exception: '{ex.ToString()}'"); + } + Assert.False(true, $"Expected either a MarshalDirectiveException, InvalidProgramException, or ExecutionEngineException, but received no exception."); + } + } + + [Fact] + public static void ByRef_Args_Not_Supported() + { + Assert.Throws(() => + { + int i = 0; + DisabledRuntimeMarshallingNative.CallWithByRef(ref i); + }); + } + + [Fact] + public static void NoBooleanNormalization() + { + byte byteVal = 42; + Assert.Equal(byteVal, Unsafe.As(ref Unsafe.AsRef(DisabledRuntimeMarshallingNative.GetByteAsBool(byteVal)))); + } + + [Fact] + public static void StructWithDefaultNonBlittableFields_DoesNotDoMarshalling() + { + short s = 42; + bool b = true; + + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBool(s, b), s, b)); + + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShort(s, c), s, c)); + + Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolWithVariantBool_FailureExpected(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + public static void StructWithNonBlittableGenericInstantiation() + { + short s = 42; + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithShortAndGeneric(s, c), s, c)); + } + + [Fact] + public static void StructWithBlittableGenericInstantiation() + { + short s = 42; + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithShortAndGeneric(s, (short)c), s, (short)c)); + } + + [Fact] + public static void CanUseEnumsWithDisabledMarshalling() + { + Assert.Equal((byte)ByteEnum.Value, DisabledRuntimeMarshallingNative.GetEnumUnderlyingValue(ByteEnum.Value)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/UnmanagedCallersOnly.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/UnmanagedCallersOnly.cs new file mode 100644 index 0000000000000..f3f963f670d20 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/UnmanagedCallersOnly.cs @@ -0,0 +1,23 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingDisabled; + +public unsafe class UnmanagedCallersOnly +{ + + [Fact] + public static void UnmanagedCallersOnly_WithNonBlittableParameters_DoesNotMarshal() + { + short s = 41; + bool b = true; + + Assert.True(DisabledRuntimeMarshallingNative.CallCheckStructWithShortAndBoolCallback(&DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolManaged, new StructWithShortAndBool(s, b), s, b)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/Delegates.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/Delegates.cs new file mode 100644 index 0000000000000..1e2f1118c88b5 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/Delegates.cs @@ -0,0 +1,35 @@ +// 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.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingEnabled; + +public unsafe class DelegatesFromExternalAssembly +{ + [Fact] + public static void StructWithDefaultNonBlittableFields() + { + short s = 42; + bool b = true; + + var callback = Marshal.GetDelegateForFunctionPointer((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolCallback()); + + Assert.False(callback(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public static void StructWithDefaultNonBlittableFields_MarshalAsInfo() + { + short s = 41; + bool b = true; + + var callback = Marshal.GetDelegateForFunctionPointer((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolWithVariantBoolCallback()); + + Assert.True(callback(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/PInvokes.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/PInvokes.cs new file mode 100644 index 0000000000000..69f91b2391707 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/PInvokes.cs @@ -0,0 +1,96 @@ +// 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.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingEnabled; + +public class PInvokes +{ + public static bool IsWindowsX86Process => OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.X86; + public static bool IsNotWindowsX86Process => !IsWindowsX86Process; + + [ConditionalFact(nameof(IsNotWindowsX86Process))] + public static void StructWithDefaultNonBlittableFields_Bool() + { + short s = 42; + bool b = true; + + // By default, bool is a 4-byte Windows BOOL, which will cause us to incorrectly marshal back the struct from native code. + Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + [SkipOnMono("Mono doesn't support marshalling a .NET Char to a C char (only a char16_t).")] + public static void StructWithDefaultNonBlittableFields_Char() + { + short s = 42; + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShort(s, c), s, c)); + + } + + [ConditionalFact(nameof(IsNotWindowsX86Process))] + public static void StructWithDefaultNonBlittableFields_Bool_MarshalAsInfo() + { + short s = 41; + bool b = true; + + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); + } + + [Fact] + [SkipOnMono("Mono doesn't support marshalling a .NET Char to a C char (only a char16_t).")] + public static void StructWithDefaultNonBlittableFields_Char_MarshalAsInfo() + { + short s = 41; + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShortWithMarshalAs(s, c), s, c)); + } + + [ConditionalFact(nameof(IsWindowsX86Process))] + public static void EntryPoint_With_StructWithDefaultNonBlittableFields_NotFound() + { + short s = 42; + bool b = true; + + // By default, bool is a 4-byte Windows BOOL, which will make the calculation of stack space for the stdcall calling convention + // incorrect, causing the entry point to not be found. + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBool(s, b), s, b)); + } + + [Fact] + [SkipOnMono("Mono supports non-blittable generic instantiations in P/Invokes")] + public static void StructWithNonBlittableGenericInstantiation_Fails() + { + short s = 41; + char c = '✅'; + Assert.Throws(() => DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithShortAndGeneric(s, c), s, c)); + } + + [Fact] + public static void StructWithBlittableGenericInstantiation() + { + short s = 42; + // We use a the "green check mark" character so that we use both bytes and + // have a value that can't be accidentally round-tripped. + char c = '✅'; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithShortAndGeneric(s, (short)c), s, (short)c)); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public static void StructWithDefaultNonBlittableFields_MarshalAsInfo_WindowsOnly() + { + short s = 41; + bool b = true; + Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolWithVariantBool(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/UnmanagedCallersOnly.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/UnmanagedCallersOnly.cs new file mode 100644 index 0000000000000..6f94ad67f6b97 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingEnabled/UnmanagedCallersOnly.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. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; +using static DisabledRuntimeMarshallingNative; + +namespace DisabledRuntimeMarshalling.PInvokeAssemblyMarshallingDisabled; + +public unsafe class UnmanagedCallersOnly +{ + + [Fact] + public static void UnmanagedCallersOnly_Defined_InDisabledAssembly_WithNonBlittableParameters_Fails() + { + short s = 41; + bool b = true; + + Assert.Throws(() => + { + delegate* unmanaged cb = &DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolManaged; + cb(new StructWithShortAndBool(s, b), s, b); + }); + } +} diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/RuntimeMarshallingDisabledAttribute.cs b/src/tests/Interop/DisabledRuntimeMarshalling/RuntimeMarshallingDisabledAttribute.cs new file mode 100644 index 0000000000000..6383488049037 --- /dev/null +++ b/src/tests/Interop/DisabledRuntimeMarshalling/RuntimeMarshallingDisabledAttribute.cs @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; + +[assembly:DisableRuntimeMarshalling] diff --git a/src/tests/Interop/ObjectiveC/ObjectiveCMarshalAPI/Program.cs b/src/tests/Interop/ObjectiveC/ObjectiveCMarshalAPI/Program.cs index b9d06dd542162..f899919ef9dab 100644 --- a/src/tests/Interop/ObjectiveC/ObjectiveCMarshalAPI/Program.cs +++ b/src/tests/Interop/ObjectiveC/ObjectiveCMarshalAPI/Program.cs @@ -5,6 +5,7 @@ namespace ObjectiveCMarshalAPI { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ObjectiveC; @@ -269,7 +270,7 @@ public ExceptionException() {} } Assert.True(false, "Unknown exception type"); - throw new Exception("Unreachable"); + throw new UnreachableException(); } class Scenario diff --git a/src/tests/Interop/common/xplatform.h b/src/tests/Interop/common/xplatform.h index cb86b1559fec5..00f9a08b12e63 100644 --- a/src/tests/Interop/common/xplatform.h +++ b/src/tests/Interop/common/xplatform.h @@ -155,6 +155,16 @@ typedef struct tagDEC { #define FALSE 0 #endif +typedef USHORT VARIANT_BOOL; + +#ifndef VARIANT_TRUE +#define VARIANT_TRUE -1 +#endif + +#ifndef VARIANT_FALSE +#define VARIANT_FALSE 0 +#endif + #ifndef __IUnknown_INTERFACE_DEFINED__ #define __IUnknown_INTERFACE_DEFINED__ @@ -175,12 +185,12 @@ IUnknown #endif // __IUnknown_INTERFACE_DEFINED__ -typedef /* [v1_enum] */ +typedef /* [v1_enum] */ enum TrustLevel { BaseTrust = 0, PartialTrust = ( BaseTrust + 1 ) , - FullTrust = ( PartialTrust + 1 ) + FullTrust = ( PartialTrust + 1 ) } TrustLevel; // AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90 diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorDotTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorDotTest.template index 1ce27afea848f..4c1a118bf4ffd 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorDotTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorDotTest.template @@ -292,12 +292,20 @@ namespace JIT.HardwareIntrinsics.General bool succeeded = true; {RetBaseType} actualResult = default; + {RetBaseType} intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += ({RetBaseType})(left[i] * right[i]); + if ((i % Vector128<{Op1BaseType}>.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += ({RetBaseType})(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Byte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Byte.cs index b47e148e18b67..1b5ea700a92bd 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Byte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Byte.cs @@ -292,12 +292,20 @@ private void ValidateResult(Byte[] left, Byte[] right, Byte result, [CallerMembe bool succeeded = true; Byte actualResult = default; + Byte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Byte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Byte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Double.cs index 83c5af2fadf54..3536b176fd1e1 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Double.cs @@ -292,12 +292,20 @@ private void ValidateResult(Double[] left, Double[] right, Double result, [Calle bool succeeded = true; Double actualResult = default; + Double intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Double)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Double)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int16.cs index 76fda4aba92fd..81309878d06ca 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int16.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int16[] left, Int16[] right, Int16 result, [CallerMe bool succeeded = true; Int16 actualResult = default; + Int16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int32.cs index 4c009089fab18..8d43f641710e2 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int32.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int32[] left, Int32[] right, Int32 result, [CallerMe bool succeeded = true; Int32 actualResult = default; + Int32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int64.cs index fb06bc4a819e2..58290b2dacb86 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Int64.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int64[] left, Int64[] right, Int64 result, [CallerMe bool succeeded = true; Int64 actualResult = default; + Int64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.SByte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.SByte.cs index f48ccd4a2b7de..cff451915fbdf 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.SByte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.SByte.cs @@ -292,12 +292,20 @@ private void ValidateResult(SByte[] left, SByte[] right, SByte result, [CallerMe bool succeeded = true; SByte actualResult = default; + SByte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (SByte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (SByte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Single.cs index fa8cc2f3d1cf9..7d8da79078983 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.Single.cs @@ -292,12 +292,20 @@ private void ValidateResult(Single[] left, Single[] right, Single result, [Calle bool succeeded = true; Single actualResult = default; + Single intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Single)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Single)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt16.cs index 69a9398548ffb..24b2373f0389f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt16.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16 result, [Calle bool succeeded = true; UInt16 actualResult = default; + UInt16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt32.cs index a64294fd81ce3..2d3938ee276ec 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt32.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32 result, [Calle bool succeeded = true; UInt32 actualResult = default; + UInt32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt64.cs index 107e290548444..857fc0b40cc5b 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Dot.UInt64.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64 result, [Calle bool succeeded = true; UInt64 actualResult = default; + UInt64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Byte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Byte.cs index 83747a6dceac9..5caa395f64971 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Byte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Byte.cs @@ -292,12 +292,20 @@ private void ValidateResult(Byte[] left, Byte[] right, Byte result, [CallerMembe bool succeeded = true; Byte actualResult = default; + Byte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Byte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Byte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Double.cs index ab68e695516e2..a23b1243101d1 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Double.cs @@ -292,12 +292,20 @@ private void ValidateResult(Double[] left, Double[] right, Double result, [Calle bool succeeded = true; Double actualResult = default; + Double intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Double)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Double)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int16.cs index 2ddda2b99ba9b..9a7eabec83c22 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int16.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int16[] left, Int16[] right, Int16 result, [CallerMe bool succeeded = true; Int16 actualResult = default; + Int16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int32.cs index 2ccb11f221fac..50c9043847421 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int32.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int32[] left, Int32[] right, Int32 result, [CallerMe bool succeeded = true; Int32 actualResult = default; + Int32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int64.cs index 986f169835cc8..f60de061554ff 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Int64.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int64[] left, Int64[] right, Int64 result, [CallerMe bool succeeded = true; Int64 actualResult = default; + Int64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.SByte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.SByte.cs index b911d6f1386dd..ee6db7af26a83 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.SByte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.SByte.cs @@ -292,12 +292,20 @@ private void ValidateResult(SByte[] left, SByte[] right, SByte result, [CallerMe bool succeeded = true; SByte actualResult = default; + SByte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (SByte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (SByte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Single.cs index b79bd666e1918..a67955e62e58c 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.Single.cs @@ -292,12 +292,20 @@ private void ValidateResult(Single[] left, Single[] right, Single result, [Calle bool succeeded = true; Single actualResult = default; + Single intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Single)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Single)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt16.cs index 8f1dd9dc151ff..41d65f320ebae 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt16.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16 result, [Calle bool succeeded = true; UInt16 actualResult = default; + UInt16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt32.cs index 6e4896091879a..51bead414374b 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt32.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32 result, [Calle bool succeeded = true; UInt32 actualResult = default; + UInt32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt64.cs index 06efcedd2a21f..dd4bbf866cb1b 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Dot.UInt64.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64 result, [Calle bool succeeded = true; UInt64 actualResult = default; + UInt64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Byte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Byte.cs index ff7cb0002b986..4a8fedd70e41b 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Byte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Byte.cs @@ -292,12 +292,20 @@ private void ValidateResult(Byte[] left, Byte[] right, Byte result, [CallerMembe bool succeeded = true; Byte actualResult = default; + Byte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Byte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Byte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Double.cs index 0d45f6141701e..f2dc915d8f5f0 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Double.cs @@ -292,12 +292,20 @@ private void ValidateResult(Double[] left, Double[] right, Double result, [Calle bool succeeded = true; Double actualResult = default; + Double intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Double)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Double)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int16.cs index 9157e7e74ef04..5284a97fb9ae6 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int16.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int16[] left, Int16[] right, Int16 result, [CallerMe bool succeeded = true; Int16 actualResult = default; + Int16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int32.cs index a679da2b0b0d1..475030d60dc2c 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int32.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int32[] left, Int32[] right, Int32 result, [CallerMe bool succeeded = true; Int32 actualResult = default; + Int32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int64.cs index d75a81fa8e6ee..4a4a585c0bd24 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Int64.cs @@ -292,12 +292,20 @@ private void ValidateResult(Int64[] left, Int64[] right, Int64 result, [CallerMe bool succeeded = true; Int64 actualResult = default; + Int64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Int64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Int64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.SByte.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.SByte.cs index 8e0702b107d84..ede755893fa9e 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.SByte.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.SByte.cs @@ -292,12 +292,20 @@ private void ValidateResult(SByte[] left, SByte[] right, SByte result, [CallerMe bool succeeded = true; SByte actualResult = default; + SByte intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (SByte)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (SByte)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Single.cs index 5ec606f2ebe8d..35458c0ea7233 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.Single.cs @@ -292,12 +292,20 @@ private void ValidateResult(Single[] left, Single[] right, Single result, [Calle bool succeeded = true; Single actualResult = default; + Single intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (Single)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (Single)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt16.cs index 44bb84adf3168..48281f753dd49 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt16.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt16.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16 result, [Calle bool succeeded = true; UInt16 actualResult = default; + UInt16 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt16)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt16)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt32.cs index 47cf417978b53..f5fad8875afb6 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt32.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32 result, [Calle bool succeeded = true; UInt32 actualResult = default; + UInt32 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt32)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt32)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt64.cs index 448ae871bb2ca..d3ad3662cfbcc 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Dot.UInt64.cs @@ -292,12 +292,20 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64 result, [Calle bool succeeded = true; UInt64 actualResult = default; + UInt64 intermResult = default; for (var i = 0; i < Op1ElementCount; i++) { - actualResult += (UInt64)(left[i] * right[i]); + if ((i % Vector128.Count) == 0) + { + actualResult += intermResult; + intermResult = default; + } + intermResult += (UInt64)(left[i] * right[i]); } + actualResult += intermResult; + if (actualResult != result) { succeeded = false; diff --git a/src/tests/JIT/Intrinsics/CreateSpan_il.il b/src/tests/JIT/Intrinsics/CreateSpan_il.il index d6a269b6f4d5f..cd950298337bb 100644 --- a/src/tests/JIT/Intrinsics/CreateSpan_il.il +++ b/src/tests/JIT/Intrinsics/CreateSpan_il.il @@ -100,7 +100,7 @@ .class explicit ansi sealed nested private '__StaticArrayInitTypeSize=16' extends [System.Runtime]System.ValueType { - .pack 1 + .pack 4 .size 16 } // end of class '__StaticArrayInitTypeSize=16' diff --git a/src/tests/JIT/Methodical/eh/basics/emptyfinally.il b/src/tests/JIT/Methodical/eh/basics/emptyfinally.il index 0ad150dd5b198..4e2f8081fa6b0 100644 --- a/src/tests/JIT/Methodical/eh/basics/emptyfinally.il +++ b/src/tests/JIT/Methodical/eh/basics/emptyfinally.il @@ -48,7 +48,7 @@ .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallywith2endfinally.il b/src/tests/JIT/Methodical/eh/basics/tryfinallywith2endfinally.il index 10f663b48244f..d1131b696ded0 100644 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallywith2endfinally.il +++ b/src/tests/JIT/Methodical/eh/basics/tryfinallywith2endfinally.il @@ -38,7 +38,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallywith2reachableendfinally.il b/src/tests/JIT/Methodical/eh/basics/tryfinallywith2reachableendfinally.il index f92dc8acf5cbe..99322c0371165 100644 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallywith2reachableendfinally.il +++ b/src/tests/JIT/Methodical/eh/basics/tryfinallywith2reachableendfinally.il @@ -44,7 +44,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/deadcode/deadcodeincatch.il b/src/tests/JIT/Methodical/eh/deadcode/deadcodeincatch.il index d0fad14bb4304..38bb6144f35b9 100644 --- a/src/tests/JIT/Methodical/eh/deadcode/deadcodeincatch.il +++ b/src/tests/JIT/Methodical/eh/deadcode/deadcodeincatch.il @@ -113,7 +113,7 @@ } // end of method Class1::inFinally .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/deadcode/deadoponerrorinfunclet.il b/src/tests/JIT/Methodical/eh/deadcode/deadoponerrorinfunclet.il index a16deba23f93d..f2c24d3916e13 100644 --- a/src/tests/JIT/Methodical/eh/deadcode/deadoponerrorinfunclet.il +++ b/src/tests/JIT/Methodical/eh/deadcode/deadoponerrorinfunclet.il @@ -66,7 +66,7 @@ extends [mscorlib]System.Object { .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry.il b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry.il index 045eb725be549..876d61b6d7cac 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry.il +++ b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry.il @@ -66,7 +66,7 @@ ret } .method private hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittonestedsibling.il b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittonestedsibling.il index c3fd5fd153494..16b22c14b97f8 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittonestedsibling.il +++ b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittonestedsibling.il @@ -56,7 +56,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/2branchesoutoftry.il b/src/tests/JIT/Methodical/eh/leaves/2branchesoutoftry.il index fe173773ddcb5..25cd53f952756 100644 --- a/src/tests/JIT/Methodical/eh/leaves/2branchesoutoftry.il +++ b/src/tests/JIT/Methodical/eh/leaves/2branchesoutoftry.il @@ -38,7 +38,7 @@ extends [mscorlib]System.Object { .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/backwardleaveincatch.il b/src/tests/JIT/Methodical/eh/leaves/backwardleaveincatch.il index 7622150ab520d..0083d08b13c3d 100644 --- a/src/tests/JIT/Methodical/eh/leaves/backwardleaveincatch.il +++ b/src/tests/JIT/Methodical/eh/leaves/backwardleaveincatch.il @@ -75,7 +75,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithcatch.il b/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithcatch.il index 59dc610160c67..05affd9b7f796 100644 --- a/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithcatch.il +++ b/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithcatch.il @@ -74,7 +74,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithfinally.il b/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithfinally.il index f1c07aba492b0..127425504c0a7 100644 --- a/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithfinally.il +++ b/src/tests/JIT/Methodical/eh/leaves/branchbackwardswithfinally.il @@ -74,7 +74,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/branchoutofnestedtryfinally.il b/src/tests/JIT/Methodical/eh/leaves/branchoutofnestedtryfinally.il index b17ba77507675..de2ec0385b8cd 100644 --- a/src/tests/JIT/Methodical/eh/leaves/branchoutofnestedtryfinally.il +++ b/src/tests/JIT/Methodical/eh/leaves/branchoutofnestedtryfinally.il @@ -83,7 +83,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/branchoutoftryfinally.il b/src/tests/JIT/Methodical/eh/leaves/branchoutoftryfinally.il index 34a79462a7c04..e0c653e4f5616 100644 --- a/src/tests/JIT/Methodical/eh/leaves/branchoutoftryfinally.il +++ b/src/tests/JIT/Methodical/eh/leaves/branchoutoftryfinally.il @@ -39,7 +39,7 @@ extends [mscorlib]System.Object { .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/forwardleaveincatch.il b/src/tests/JIT/Methodical/eh/leaves/forwardleaveincatch.il index 831f8227f79d9..d500275f8d4b9 100644 --- a/src/tests/JIT/Methodical/eh/leaves/forwardleaveincatch.il +++ b/src/tests/JIT/Methodical/eh/leaves/forwardleaveincatch.il @@ -74,7 +74,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/leaveinsameregion.il b/src/tests/JIT/Methodical/eh/leaves/leaveinsameregion.il index 677873d6cc29c..c6b6aa006c745 100644 --- a/src/tests/JIT/Methodical/eh/leaves/leaveinsameregion.il +++ b/src/tests/JIT/Methodical/eh/leaves/leaveinsameregion.il @@ -63,7 +63,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/leaveintotrybody.il b/src/tests/JIT/Methodical/eh/leaves/leaveintotrybody.il index 56f4feee5d43c..8ccab02bdd3b0 100644 --- a/src/tests/JIT/Methodical/eh/leaves/leaveintotrybody.il +++ b/src/tests/JIT/Methodical/eh/leaves/leaveintotrybody.il @@ -55,7 +55,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyintrycatchwithleaveintotry.il b/src/tests/JIT/Methodical/eh/leaves/tryfinallyintrycatchwithleaveintotry.il index 8ee803a7a8f21..6dc5ca240c8c1 100644 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyintrycatchwithleaveintotry.il +++ b/src/tests/JIT/Methodical/eh/leaves/tryfinallyintrycatchwithleaveintotry.il @@ -56,7 +56,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/mixedhandler/catchfiltercatch.il b/src/tests/JIT/Methodical/eh/mixedhandler/catchfiltercatch.il index 29dd18a373382..30b494ed6ae54 100644 --- a/src/tests/JIT/Methodical/eh/mixedhandler/catchfiltercatch.il +++ b/src/tests/JIT/Methodical/eh/mixedhandler/catchfiltercatch.il @@ -54,7 +54,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/mixedhandler/filterfiltercatchcatch.il b/src/tests/JIT/Methodical/eh/mixedhandler/filterfiltercatchcatch.il index 4f64c5669c2ac..cef244dd43f09 100644 --- a/src/tests/JIT/Methodical/eh/mixedhandler/filterfiltercatchcatch.il +++ b/src/tests/JIT/Methodical/eh/mixedhandler/filterfiltercatchcatch.il @@ -54,7 +54,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyinsidecatch.il b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyinsidecatch.il index cbc8f49a802c3..ea985dc848fe7 100644 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyinsidecatch.il +++ b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyinsidecatch.il @@ -54,7 +54,7 @@ } .method public hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.il b/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.il index df5dc52f71d07..1d34d53210cc7 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.il +++ b/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.il @@ -50,7 +50,7 @@ } // end of method Test::.ctor .method private hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 @@ -59,7 +59,8 @@ // Code size 23 (0x17) .maxstack 2 .locals init (class Test_twoEndFinallys V_0) - IL_0000: ldarg.0 + ldc.i4.s 0 + IL_0000: newarr [mscorlib]System.String IL_0001: call class Test_twoEndFinallys Test_twoEndFinallys::TwoEndFinallys(string[]) IL_0006: stloc.0 IL_0007: ldloc.0 diff --git a/src/tests/JIT/Methodical/inlining/dev10_bug719093/variancesmall.il b/src/tests/JIT/Methodical/inlining/dev10_bug719093/variancesmall.il index 65bea4b23998b..6b2bb0bade822 100644 --- a/src/tests/JIT/Methodical/inlining/dev10_bug719093/variancesmall.il +++ b/src/tests/JIT/Methodical/inlining/dev10_bug719093/variancesmall.il @@ -290,7 +290,7 @@ } .method private hidebysig static int32 - Main(string[] args) cil managed + Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/classic.il b/src/tests/JIT/Methodical/nonvirtualcall/classic.il index 58ad342c484d4..6eaeded7ecc14 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/classic.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/classic.il @@ -681,7 +681,7 @@ IL_000e: ret } // end of method Program::CallFromInsideGrandChild - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/delegate.il b/src/tests/JIT/Methodical/nonvirtualcall/delegate.il index 91b24d2723fad..00a20015f576c 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/delegate.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/delegate.il @@ -566,7 +566,7 @@ IL_007f: ret } // end of method Program::CallDelegateFromGrandChild - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics.il b/src/tests/JIT/Methodical/nonvirtualcall/generics.il index 1a23c734a0e14..9bbb9f408d822 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/generics.il @@ -693,7 +693,7 @@ IL_000e: ret } // end of method Program::CallFromInsideGrandChild - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics2.il b/src/tests/JIT/Methodical/nonvirtualcall/generics2.il index 59635af68e3bd..c75da589bb866 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics2.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/generics2.il @@ -728,7 +728,7 @@ IL_000e: ret } // end of method Program::CallFromInsideGrandChild - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.il b/src/tests/JIT/Methodical/nonvirtualcall/tailcall.il index 9bbb008aa5de5..959f4fb2a3c50 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/tailcall.il @@ -601,7 +601,7 @@ IL_000e: ret } // end of method Program::CallFromInsideGrandChild - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.il b/src/tests/JIT/Methodical/nonvirtualcall/valuetype.il index 25897d22e7940..44bc21e2a7975 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.il +++ b/src/tests/JIT/Methodical/nonvirtualcall/valuetype.il @@ -114,7 +114,7 @@ IL_0037: ret } // end of method Program::CallDummy - .method public hidebysig static int32 Main(string[] args) cil managed + .method public hidebysig static int32 Main() cil managed { .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 diff --git a/src/tests/JIT/Methodical/xxblk/dynblk_order.il b/src/tests/JIT/Methodical/xxblk/dynblk_order.il new file mode 100644 index 0000000000000..f4d24714c31ad --- /dev/null +++ b/src/tests/JIT/Methodical/xxblk/dynblk_order.il @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Tests that cpblk/initblk importation sastifies ordering constraints. + +.assembly extern System.Runtime { } +.assembly extern System.Console { } +.assembly extern xunit.core {} + +.assembly DynBlkOrder {} + +.typedef [System.Runtime]System.OverflowException as OverflowException +.typedef [System.Runtime]System.IndexOutOfRangeException as IndexOutOfRangeException + +.class DynBlkOrder extends [System.Runtime]System.Object +{ + .method static int32 Main() + { + .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( + 01 00 00 00 + ) + .entrypoint + .locals (void* dst, void*[] srcArr, int32 srcIdx, int32 size) + + ldloca dst + ldloca srcArr + ldloca srcIdx + ldloca size + call void DynBlkOrder::InitValues(void*&, void*[]&, int32&, int32&) + + .try + { + ldloc dst + ldloc srcArr + ldloc srcIdx + ldelem.i + ldloc size + conv.ovf.u + cpblk + + leave FAIL + } + catch IndexOutOfRangeException + { + leave INITBLK + } + catch OverflowException + { + leave FAIL1 + } + + INITBLK: + .try + { + ldloc dst + ldloc srcArr + ldloc srcIdx + ldelem.i + conv.i4 + ldloc size + conv.ovf.u + initblk + + leave FAIL + } + catch IndexOutOfRangeException + { + leave SUCCESS + } + catch OverflowException + { + leave FAIL2 + } + + SUCCESS: + ldc.i4 100 + ret + + FAIL: + ldc.i4 99 + ret + + FAIL1: + ldc.i4 101 + ret + + FAIL2: + ldc.i4 102 + ret + } + + .method static void InitValues(void*& pSrc, void*[]& pSrcArr, int32& pSrcIdx, int32& pSize) noinlining + { + ldarg pSrc + ldc.i4 0 + conv.u + stind.i + + ldarg pSrcArr + ldc.i4 0 + newarr int32 + stind.ref + + ldarg pSrcIdx + ldc.i4 1 + stind.i4 + + ldarg pSize + ldc.i4 -1 + stind.i4 + + ret + } +} diff --git a/src/tests/JIT/Methodical/xxblk/dynblk_order_d.ilproj b/src/tests/JIT/Methodical/xxblk/dynblk_order_d.ilproj new file mode 100644 index 0000000000000..7a8255ed9d1e6 --- /dev/null +++ b/src/tests/JIT/Methodical/xxblk/dynblk_order_d.ilproj @@ -0,0 +1,12 @@ + + + Exe + 1 + + + Full + + + + + diff --git a/src/tests/JIT/Methodical/xxblk/dynblk_order_ro.ilproj b/src/tests/JIT/Methodical/xxblk/dynblk_order_ro.ilproj new file mode 100644 index 0000000000000..1a281b5960752 --- /dev/null +++ b/src/tests/JIT/Methodical/xxblk/dynblk_order_ro.ilproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + PdbOnly + True + + + + + diff --git a/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.cs b/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.cs index f85ed85ceb0ee..8bd8ef2652224 100644 --- a/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.cs +++ b/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.cs @@ -10,8 +10,11 @@ private static int Main() int Var1, Temp; try { - for (Temp = int.MaxValue - 3; Temp <= int.MaxValue - 1; Temp++) - Var1 = (int)(2 + Temp); + checked + { + for (Temp = int.MaxValue - 3; Temp <= int.MaxValue - 1; Temp++) + Var1 = (int)(2 + Temp); + } } catch (Exception ex) { diff --git a/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.csproj b/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.csproj index 0ac905c8265b7..68c5b85dcaba4 100644 --- a/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.csproj +++ b/src/tests/JIT/Regression/Dev11/dev11_4421/Dev11_4421.csproj @@ -5,7 +5,6 @@ PdbOnly True - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs new file mode 100644 index 0000000000000..7535cd334d962 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs @@ -0,0 +1,559 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +class Program +{ + // CompareEqual + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Byte_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_SByte_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt16_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int16_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt32_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int32_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Byte_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_SByte_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt16_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int16_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt32_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int32_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Single_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + // CompareEqual Swapped + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Byte_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_SByte_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt16_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int16_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt32_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int32_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Single_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Byte_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_SByte_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt16_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int16_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt32_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int32_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Single_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + // Validation + + unsafe static bool ValidateResult_Vector64(Vector64 result, T expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (8 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue)) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector64(Vector64 result, Vector64 expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (8 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue.GetElement(i))) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector128(Vector128 result, T expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (16 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue)) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector128(Vector128 result, Vector128 expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (16 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue.GetElement(i))) + { + succeeded = false; + } + } + + return succeeded; + } + + static int Tests_AdvSimd() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Byte_Zero(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_SByte_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt16_Zero(Vector64.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int16_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt32_Zero(Vector64.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int32_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Single_Zero(Vector64.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Byte_Zero(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_SByte_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt16_Zero(Vector128.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int16_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt32_Zero(Vector128.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int32_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Single_Zero(Vector128.Zero), Single.NaN)) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Swapped() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Byte_Zero_Swapped(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_SByte_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt16_Zero_Swapped(Vector64.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int16_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt32_Zero_Swapped(Vector64.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int32_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Single_Zero_Swapped(Vector64.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Byte_Zero_Swapped(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_SByte_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt16_Zero_Swapped(Vector128.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int16_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt32_Zero_Swapped(Vector128.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int32_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Single_Zero_Swapped(Vector128.Zero), Single.NaN)) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Arm64() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero(Vector128.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero(Vector128.Zero), UInt64.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero(Vector64.Zero), Vector64.CreateScalar(Single.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero(Vector64.Zero), Vector64.CreateScalar(Double.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero(Vector64.Zero), Vector64.CreateScalar(UInt64.MaxValue))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero(Vector64.Zero), Vector64.CreateScalar(-1L))) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Arm64_Swapped() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero_Swapped(Vector128.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero_Swapped(Vector128.Zero), UInt64.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(Single.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(Double.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(UInt64.MaxValue))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(-1L))) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Main(string[] args) + { + var result = 100; + + if (AdvSimd.IsSupported) + { + Console.WriteLine("Testing AdvSimd"); + + if (result != -1) + { + result = Tests_AdvSimd(); + } + if (result != -1) + { + result = Tests_AdvSimd_Swapped(); + } + + if (result == -1) + { + Console.WriteLine("AdvSimd Tests Failed"); + } + else + { + Console.WriteLine("AdvSimd Tests Passed"); + } + } + else + { + Console.WriteLine("Skipped AdvSimd Tests"); + } + + if (AdvSimd.Arm64.IsSupported) + { + Console.WriteLine("Testing AdvSimd_Arm64"); + + if (result != -1) + { + result = Tests_AdvSimd_Arm64(); + } + if (result != -1) + { + result = Tests_AdvSimd_Arm64_Swapped(); + } + + if (result == -1) + { + Console.WriteLine("AdvSimd_Arm64 Tests Failed"); + } + else + { + Console.WriteLine("AdvSimd_Arm64 Tests Passed"); + } + } + else + { + Console.WriteLine("Skipped AdvSimd_Arm64 Tests"); + } + + return result; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj new file mode 100644 index 0000000000000..bf6f589eb325b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs index 543e6b5804158..656da5bdb1aaf 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs @@ -664,7 +664,7 @@ static bool ValidateVector256() { bool succeeded = true; - if (Avx.IsSupported) + if (Avx2.IsSupported) { succeeded &= Vector256.IsHardwareAccelerated; succeeded &= Vector256.Count == 32; diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.cs b/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.cs new file mode 100644 index 0000000000000..a4abd8fd4bf63 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Found by Antigen + +public class Runtime_63942 +{ + public static int Main() + { + var _ = 3.14.ToString(); + return 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.csproj new file mode 100644 index 0000000000000..9756f0815d4d6 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_63942/Runtime_63942.csproj @@ -0,0 +1,21 @@ + + + Exe + True + + + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.cs b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.cs new file mode 100644 index 0000000000000..c12db7ffb3b9a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.cs @@ -0,0 +1,9215 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Runtime_64125.cs is AUTOGENERATED. DO NOT MODIFY the file manually. +// Instead use the following command to generate the .cs file from .tt file. +// "%DevEnvDir%\TextTransform.exe" Runtime_64125.tt + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Runtime_64125 +{ + [StructLayout(LayoutKind.Explicit, Size=1)] + struct Struct1Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=2)] + struct Struct2Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=3)] + struct Struct3Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=4)] + struct Struct4Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=7)] + struct Struct7Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=8)] + struct Struct8Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=15)] + struct Struct15Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=16)] + struct Struct16Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=31)] + struct Struct31Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=32)] + struct Struct32Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=63)] + struct Struct63Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=64)] + struct Struct64Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=127)] + struct Struct127Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=128)] + struct Struct128Bytes + { + } + + [StructLayout(LayoutKind.Explicit, Size=65648)] + struct AnyOffset + { + [FieldOffset(252)] + public byte fieldAtOffset252; + [FieldOffset(255)] + public byte fieldAtOffset255; + [FieldOffset(504)] + public byte fieldAtOffset504; + [FieldOffset(1008)] + public byte fieldAtOffset1008; + [FieldOffset(4095)] + public byte fieldAtOffset4095; + [FieldOffset(8190)] + public byte fieldAtOffset8190; + [FieldOffset(16380)] + public byte fieldAtOffset16380; + [FieldOffset(32760)] + public byte fieldAtOffset32760; + [FieldOffset(65520)] + public byte fieldAtOffset65520; + } + + class AnyLocation + { + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset252 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset255 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset504 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset1008 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset4095 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset8190 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset16380 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset32760 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy1BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct1Bytes*)&dst->fieldAtOffset65520 = *(Struct1Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset252 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset255 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset504 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset1008 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset4095 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset8190 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset16380 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset32760 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy2BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct2Bytes*)&dst->fieldAtOffset65520 = *(Struct2Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset252 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset255 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset504 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset1008 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset4095 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset8190 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset16380 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset32760 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy3BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct3Bytes*)&dst->fieldAtOffset65520 = *(Struct3Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset252 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset255 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset504 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset1008 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset4095 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset8190 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset16380 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset32760 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy4BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct4Bytes*)&dst->fieldAtOffset65520 = *(Struct4Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset252 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset255 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset504 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset1008 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset4095 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset8190 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset16380 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset32760 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy7BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct7Bytes*)&dst->fieldAtOffset65520 = *(Struct7Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset252 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset255 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset504 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset1008 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset4095 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset8190 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset16380 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset32760 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy8BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct8Bytes*)&dst->fieldAtOffset65520 = *(Struct8Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset252 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset255 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset504 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset1008 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset4095 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset8190 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset16380 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset32760 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy15BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct15Bytes*)&dst->fieldAtOffset65520 = *(Struct15Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset252 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset255 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset504 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset1008 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset4095 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset8190 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset16380 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset32760 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy16BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct16Bytes*)&dst->fieldAtOffset65520 = *(Struct16Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset252 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset255 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset504 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset1008 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset4095 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset8190 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset16380 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset32760 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy31BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct31Bytes*)&dst->fieldAtOffset65520 = *(Struct31Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset252 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset255 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset504 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset1008 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset4095 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset8190 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset16380 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset32760 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy32BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct32Bytes*)&dst->fieldAtOffset65520 = *(Struct32Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset252 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset255 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset504 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset1008 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset4095 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset8190 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset16380 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset32760 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy63BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct63Bytes*)&dst->fieldAtOffset65520 = *(Struct63Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset252 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset255 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset504 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset1008 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset4095 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset8190 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset16380 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset32760 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy64BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct64Bytes*)&dst->fieldAtOffset65520 = *(Struct64Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset252 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset255 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset504 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset1008 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset4095 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset8190 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset16380 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset32760 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy127BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct127Bytes*)&dst->fieldAtOffset65520 = *(Struct127Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset252ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset252; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset255ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset255; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset504ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset504; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset1008ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset1008; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset4095ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset4095; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset8190ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset8190; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset16380ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset16380; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset32760ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset32760; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset252(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset252 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset255(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset255 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset504(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset504 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset1008(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset1008 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset4095(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset4095 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset8190(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset8190 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset16380(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset16380 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset32760(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset32760 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy128BytesFromLocationAtOffset65520ToLocationAtOffset65520(AnyOffset* dst, AnyOffset* src) + { + *(Struct128Bytes*)&dst->fieldAtOffset65520 = *(Struct128Bytes*)&src->fieldAtOffset65520; + } + + } + + class Program + { + static unsafe void Init(byte* bytes, int byteCount) + { + for (int i = 0; i < byteCount; i++) + { + bytes[i] = TestLibrary.Generator.GetByte(); + } + } + + static unsafe bool MemoryCompare(byte* left, byte* right, int byteCount) + { + for (int i = 0; i < byteCount; i++) + { + if (left[i] != right[i]) return false; + } + + return true; + } + + static unsafe int Main(string[] args) + { + var anyLocation = new AnyLocation(); + + var src = new AnyOffset(); + var dst = new AnyOffset(); + + Init((byte*)&src, sizeof(AnyOffset)); + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 1)) return 0; + anyLocation.Copy1BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 1)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 2)) return 0; + anyLocation.Copy2BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 2)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 3)) return 0; + anyLocation.Copy3BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 3)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 4)) return 0; + anyLocation.Copy4BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 4)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 7)) return 0; + anyLocation.Copy7BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 7)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 8)) return 0; + anyLocation.Copy8BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 8)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 15)) return 0; + anyLocation.Copy15BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 15)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 16)) return 0; + anyLocation.Copy16BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 16)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 31)) return 0; + anyLocation.Copy31BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 31)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 32)) return 0; + anyLocation.Copy32BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 32)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 63)) return 0; + anyLocation.Copy63BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 63)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 64)) return 0; + anyLocation.Copy64BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 64)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 127)) return 0; + anyLocation.Copy127BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 127)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset252ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset252, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset255ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset255, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset504ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset504, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset1008ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset1008, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset4095ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset4095, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset8190ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset8190, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset16380ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset16380, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset32760ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset32760, &dst.fieldAtOffset65520, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset252(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset252, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset255(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset255, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset504(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset504, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset1008(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset1008, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset4095(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset4095, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset8190(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset8190, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset16380(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset16380, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset32760(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset32760, 128)) return 0; + anyLocation.Copy128BytesFromLocationAtOffset65520ToLocationAtOffset65520(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset65520, &dst.fieldAtOffset65520, 128)) return 0; + + return 100; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.csproj new file mode 100644 index 0000000000000..8f58ccf6438da --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.csproj @@ -0,0 +1,11 @@ + + + Exe + True + True + + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.tt b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.tt new file mode 100644 index 0000000000000..b53191dbcb97e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_64125/Runtime_64125.tt @@ -0,0 +1,113 @@ +<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ output extension=".cs" #> +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Runtime_64125.cs is AUTOGENERATED. DO NOT MODIFY the file manually. +// Instead use the following command to generate the .cs file from .tt file. +// "%DevEnvDir%\TextTransform.exe" Runtime_64125.tt + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Runtime_64125 +{ +<# + int[] byteCounts = new int[] { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; + int[] offsets = new int[] { 252, 255, 504, 1008, 4095, 8190, 16380, 32760, 65520 }; + + int maximumByteCount = byteCounts.Max(); + int maximumOffset = offsets.Max(); + + foreach (int byteCount in byteCounts) + { +#> + [StructLayout(LayoutKind.Explicit, Size=<#= byteCount #>)] + struct Struct<#= byteCount #>Bytes + { + } + +<# + } +#> + [StructLayout(LayoutKind.Explicit, Size=<#= maximumByteCount + maximumOffset #>)] + struct AnyOffset + { +<# + foreach (int fieldOffset in offsets) + { +#> + [FieldOffset(<#= fieldOffset #>)] + public byte fieldAtOffset<#= fieldOffset #>; +<# + } +#> + } + + class AnyLocation + { +<# + foreach (int byteCount in byteCounts) + foreach (int srcOffset in offsets) + foreach (int dstOffset in offsets) + { + string structByteCount = $"Struct{byteCount}Bytes"; +#> + [MethodImpl(MethodImplOptions.NoInlining)] + public unsafe void Copy<#= byteCount #>BytesFromLocationAtOffset<#= srcOffset #>ToLocationAtOffset<#= dstOffset #>(AnyOffset* dst, AnyOffset* src) + { + *(<#= structByteCount #>*)&dst->fieldAtOffset<#= dstOffset #> = *(<#= structByteCount #>*)&src->fieldAtOffset<#= srcOffset #>; + } + +<# + } +#> + } + + class Program + { + static unsafe void Init(byte* bytes, int byteCount) + { + for (int i = 0; i < byteCount; i++) + { + bytes[i] = TestLibrary.Generator.GetByte(); + } + } + + static unsafe bool MemoryCompare(byte* left, byte* right, int byteCount) + { + for (int i = 0; i < byteCount; i++) + { + if (left[i] != right[i]) return false; + } + + return true; + } + + static unsafe int Main(string[] args) + { + var anyLocation = new AnyLocation(); + + var src = new AnyOffset(); + var dst = new AnyOffset(); + + Init((byte*)&src, sizeof(AnyOffset)); +<# + foreach (int byteCount in byteCounts) + foreach (int srcOffset in offsets) + foreach (int dstOffset in offsets) + { +#> + anyLocation.Copy<#= byteCount #>BytesFromLocationAtOffset<#= srcOffset #>ToLocationAtOffset<#= dstOffset #>(&dst, &src); + if (!MemoryCompare(&src.fieldAtOffset<#= srcOffset #>, &dst.fieldAtOffset<#= dstOffset #>, <#= byteCount #>)) return 0; +<# + } +#> + + return 100; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.cs b/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.cs new file mode 100644 index 0000000000000..725475cc4a718 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.cs @@ -0,0 +1,33 @@ +// 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.Runtime.CompilerServices; + +public class Runtime_64208 +{ + public static int Main(string[] args) + { + if (Method0() != null) + { + return 101; + } + + return 100; + } + + public struct S1 + { + public string string_0; + } + + static S1 s_s1_32 = new S1(); + + public static S1 LeafMethod15() => s_s1_32; + + public static string Method0() + { + return LeafMethod15().string_0; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.csproj new file mode 100644 index 0000000000000..00fe72ae9b9cd --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_64208/Runtime_64208.csproj @@ -0,0 +1,17 @@ + + + Exe + True + + + + + + + \ No newline at end of file diff --git a/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.cs b/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.cs new file mode 100644 index 0000000000000..22b7c3b94e693 --- /dev/null +++ b/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// "cpblk/initblk" should not generate non-null assertions because the +// indirections they represent may not be realized (in case the "size" +// was zero). + +using System; +using System.Runtime.CompilerServices; + +public class DynBlkNullAssertions +{ + public static int Main() + { + if (!TestCpBlk(ref Unsafe.NullRef(), ref Unsafe.NullRef(), 0)) + { + return 101; + } + if (!TestInitBlk(ref Unsafe.NullRef(), 0, 0)) + { + return 102; + } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestCpBlk(ref byte dst, ref byte src, uint size) + { + Unsafe.CopyBlock(ref dst, ref src, size); + + return Unsafe.AreSame(ref dst, ref Unsafe.NullRef()); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestInitBlk(ref byte dst, byte value, uint size) + { + Unsafe.InitBlock(ref dst, value, size); + + return Unsafe.AreSame(ref dst, ref Unsafe.NullRef()); + } +} diff --git a/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.csproj b/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.csproj new file mode 100644 index 0000000000000..5d8fe22529764 --- /dev/null +++ b/src/tests/JIT/opt/AssertionPropagation/DynBlkNullAssertions.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + True + + + + + diff --git a/src/tests/JIT/opt/IsKnownConstant/StringEquals.cs b/src/tests/JIT/opt/IsKnownConstant/StringEquals.cs new file mode 100644 index 0000000000000..4a109ae5d6548 --- /dev/null +++ b/src/tests/JIT/opt/IsKnownConstant/StringEquals.cs @@ -0,0 +1,99 @@ +// 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.Runtime.CompilerServices; + +public class Program +{ + public static int Main() + { + AssertEquals(true, TestEquals1("")); + AssertEquals(false, TestEquals1(null)); + AssertEquals(false, TestEquals1("1")); + + AssertEquals(true, TestEquals2("")); + AssertEquals(false, TestEquals2(null)); + AssertEquals(false, TestEquals2("1")); + + AssertEquals(true, TestEquals3("")); + AssertEquals(false, TestEquals3(null)); + AssertEquals(false, TestEquals3("1")); + + AssertEquals(true, TestEquals4("")); + AssertEquals(false, TestEquals4(null)); + AssertEquals(false, TestEquals4("1")); + + AssertEquals(true, TestEquals5("")); + AssertEquals(false, TestEquals5(null)); + AssertEquals(false, TestEquals5("1")); + + AssertEquals(false, TestEquals6("")); + AssertEquals(true, TestEquals6(null)); + AssertEquals(false, TestEquals6("1")); + + AssertEquals(false, TestEquals7()); + AssertEquals(false, TestEquals8()); + + AssertEquals(true, TestEquals5("")); + AssertEquals(false, TestEquals5(null)); + AssertEquals(false, TestEquals5("1")); + + AssertEquals(true, TestStartWith("c")); + AssertEquals(false, TestStartWith("C")); + AssertThrowsNRE(() => TestStartWith(null)); + + return 100; + } + + private static void AssertEquals(bool expected, bool actual, [CallerLineNumber]int l = 0) + { + if (expected != actual) + throw new InvalidOperationException(); + } + + private static void AssertThrowsNRE(Action a) + { + try + { + a(); + } + catch (NullReferenceException) + { + return; + } + throw new InvalidOperationException(); + } + + private static string NullStr() => null; + private static string EmptyStr() => ""; + private static string NonEmptyStr() => "1"; + + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals1(string str) => str == ""; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals2(string str) => str == string.Empty; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals3(string str) => "" == str; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals4(string str) => string.Empty == str; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals5(string str) => string.Empty == str; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals6(string str) => string.Equals(NullStr(), str); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals7() => string.Equals(NullStr(), EmptyStr()); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestEquals8() => string.Equals(NullStr(), NonEmptyStr()); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestStartWith(string str) => str.StartsWith('c'); +} diff --git a/src/tests/JIT/opt/IsKnownConstant/StringEquals.csproj b/src/tests/JIT/opt/IsKnownConstant/StringEquals.csproj new file mode 100644 index 0000000000000..6946bed81bfd5 --- /dev/null +++ b/src/tests/JIT/opt/IsKnownConstant/StringEquals.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSets.cs b/src/tests/JIT/opt/ValueNumbering/ExceptionSets.cs new file mode 100644 index 0000000000000..6a413303ad194 --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSets.cs @@ -0,0 +1,37 @@ +// 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.Runtime.CompilerServices; + +#pragma warning disable CS0253 // Possible unintended reference comparison + +class ExceptionSets +{ + public static int Main() + { + try + { + TestObjGetType(null, 0); + return 101; + } + catch (NullReferenceException) { } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool TestObjGetType(object a, int i) + { + var fls = false; + var c1 = i == 0; + var c2 = c1; + + if (((a.GetType() == a) & fls) | (i == 0)) + { + return true; + } + + return c2; + } +} diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSets.csproj b/src/tests/JIT/opt/ValueNumbering/ExceptionSets.csproj new file mode 100644 index 0000000000000..5d8fe22529764 --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSets.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + True + + + + + diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.cs b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.cs new file mode 100644 index 0000000000000..103f6b6c8547c --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.cs @@ -0,0 +1,40 @@ +// 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.Runtime.Intrinsics; +using System.Runtime.CompilerServices; + +// We're testing whether HWI nodes with > 2 operands propagate exception sets correctly. +// +class ExceptionSetsPropagation_Hwi +{ + public static int Main() + { + try + { + Problem(-1, false, false); + } + catch (OverflowException) + { + return 100; + } + + return 101; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool Problem(int a, bool c1, bool c2) + { + var zero = 0; + c1 = a == 0; + c2 = c1; + + if ((Vector128.Create((int)checked((uint)a), a, a, a).GetElement(0) * zero) + a == 0) + { + return false; + } + + return c2; + } +} diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.csproj b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.csproj new file mode 100644 index 0000000000000..5d8fe22529764 --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_Hwi.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + True + + + + + diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.il b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.il new file mode 100644 index 0000000000000..312eb5dcb545e --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.il @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern xunit.core { } +.assembly extern System.Runtime { } +.assembly extern System.Console { } + +.assembly ExceptionSetsPropagation_LclHeap { } + +.class ExceptionSetsPropagation_LclHeap extends [System.Runtime]System.Object +{ + .method public static int32 Main() + { + .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (01 00 00 00) + .entrypoint + + .try + { + ldc.i4 300 + conv.i + call bool ExceptionSetsPropagation_LclHeap::Problem(native int) + pop + leave FAIL + } + catch [System.Runtime]System.OverflowException + { + pop + leave SUCCESS + } + + SUCCESS: + ldc.i4 100 + ret + + FAIL: + ldc.i4 101 + ret + } + + .method private static bool Problem(native int a) + { + .locals (bool c1, bool c2) + + ldarg a + localloc + ldc.i4 0 + conv.i + and + ldarg a + ceq + stloc c1 + + ldloc c1 + stloc c2 + + ldarg a + conv.ovf.i1 + conv.i + localloc + ldc.i4 0 + conv.i + and + ldarg a + ceq + brtrue RET + + ldstr "The expected OverflowException was not thrown!" + call void [System.Console]System.Console::WriteLine(string) + + RET: + ldloc c2 + ret + } +} + diff --git a/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.ilproj b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.ilproj new file mode 100644 index 0000000000000..477cccfe1def0 --- /dev/null +++ b/src/tests/JIT/opt/ValueNumbering/ExceptionSetsPropagation_LclHeap.ilproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + True + + + + + diff --git a/src/tests/Loader/classloader/RefFields/InvalidCSharp.il b/src/tests/Loader/classloader/RefFields/InvalidCSharp.il new file mode 100644 index 0000000000000..cb012cf23b7ec --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/InvalidCSharp.il @@ -0,0 +1,137 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) } + +.assembly InvalidCSharp { } + +.class public auto ansi sealed beforefieldinit InvalidCSharp.InvalidStructWithRefField + extends [System.Runtime]System.ValueType +{ + // Type requires IsByRefLikeAttribute to be valid. + .field public string& invalid +} + +// This is invalid metadata and is unable to be loaded. +// - [field sig] (0x80131815 (VER_E_FIELD_SIG)) +// +// .class public auto ansi sealed beforefieldinit InvalidCSharp.InvalidStructWithStaticRefField +// extends [System.Runtime]System.ValueType +// { +// .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( +// 01 00 00 00 +// ) +// .field public static string& invalid +// } + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithRefField + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public string& Str + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + string& + ) cil managed + { + ldarg.0 + ldarg.1 + stfld string& InvalidCSharp.WithRefField::Str + ret + } + + .method public hidebysig + instance bool ConfirmFieldInstance ( + string + ) cil managed + { + ldarg.0 + ldfld string& InvalidCSharp.WithRefField::Str + ldind.ref + ldarg.1 + ceq + ret + } +} + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithRefStructField + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public valuetype InvalidCSharp.WithRefField& Field + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + valuetype InvalidCSharp.WithRefField& + ) cil managed + { + ldarg.0 + ldarg.1 + stfld valuetype InvalidCSharp.WithRefField& InvalidCSharp.WithRefStructField::Field + ret + } + + .method public hidebysig + instance bool ConfirmFieldInstance ( + valuetype InvalidCSharp.WithRefField& + ) cil managed + { + ldarg.0 + ldfld valuetype InvalidCSharp.WithRefField& InvalidCSharp.WithRefStructField::Field + ldind.ref + ldarg.1 + ldind.ref + ceq + ret + } +} + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithTypedReferenceField`1 + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public typedref Field + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + !T& + ) cil managed + { + ldarg.0 + ldarg.1 + mkrefany !T + stfld typedref valuetype InvalidCSharp.WithTypedReferenceField`1::Field + ret + } + + .method public hidebysig + instance class [System.Runtime]System.Type GetFieldType () cil managed + { + ldarg.0 + ldfld typedref valuetype InvalidCSharp.WithTypedReferenceField`1::Field + refanytype + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle ) + ret + } + + .method public hidebysig + instance bool ConfirmFieldInstance ( + !T + ) cil managed + { + ldarg.0 + ldfld typedref valuetype InvalidCSharp.WithTypedReferenceField`1::Field + refanyval !T + ldind.ref + ldarg.1 + ceq + ret + } +} diff --git a/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj b/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj new file mode 100644 index 0000000000000..d577c8f9c7a1a --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj @@ -0,0 +1,8 @@ + + + Library + + + + + diff --git a/src/tests/Loader/classloader/RefFields/Validate.cs b/src/tests/Loader/classloader/RefFields/Validate.cs new file mode 100644 index 0000000000000..3e8d3b76d23d0 --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/Validate.cs @@ -0,0 +1,97 @@ +// 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.IO; +using System.Runtime.CompilerServices; +using InvalidCSharp; + +using Xunit; + +class Validate +{ + [Fact] + public static void Validate_Invalid_RefField_Fails() + { + Console.WriteLine($"{nameof(Validate_Invalid_RefField_Fails)}..."); + Assert.Throws(() => { var t = typeof(InvalidStructWithRefField); }); + } + + [Fact] + public static void Validate_RefStructWithRefField_Load() + { + Console.WriteLine($"{nameof(Validate_RefStructWithRefField_Load)}..."); + var t = typeof(WithRefField); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Create_RefField_Worker(string str, int depth) + { + if (depth == 5) + { + return; + } + + WithRefField s = new(ref str); + string newStr = new(str); + + Create_RefField_Worker(str + $" {depth}", depth + 1); + Assert.False(s.ConfirmFieldInstance(newStr)); + Assert.True(s.ConfirmFieldInstance(str)); + } + + [Fact] + public static void Validate_Create_RefField() + { + var str = nameof(Validate_Create_RefField); + Console.WriteLine($"{str}..."); + Create_RefField_Worker(str, 1); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Create_RefStructField_Worker(string str, int depth) + { + if (depth == 5) + { + return; + } + + WithRefField s = new(ref str); + WithRefStructField t = new(ref s); + + Create_RefStructField_Worker(str + $" {depth}", depth + 1); + Assert.True(t.ConfirmFieldInstance(ref s)); + } + + [Fact] + public static void Validate_Create_RefStructField() + { + var str = nameof(Validate_Create_RefStructField); + Console.WriteLine($"{str}..."); + Create_RefStructField_Worker(str, 1); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Create_TypedReferenceRefField_Worker(Validate v, int depth) + { + if (depth == 5) + { + return; + } + + WithTypedReferenceField s = new(ref v); + + Create_TypedReferenceRefField_Worker(v, depth + 1); + Assert.Equal(typeof(Validate), s.GetFieldType()); + Assert.True(s.ConfirmFieldInstance(v)); + } + + [Fact] + public static void Validate_Create_TypedReferenceRefField() + { + Console.WriteLine($"{nameof(Validate_Create_TypedReferenceRefField)}..."); + + Validate v = new(); + Create_TypedReferenceRefField_Worker(v, 1); + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/RefFields/Validate.csproj b/src/tests/Loader/classloader/RefFields/Validate.csproj new file mode 100644 index 0000000000000..96fedddd4bdda --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/Validate.csproj @@ -0,0 +1,12 @@ + + + true + Exe + + + + + + + + diff --git a/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.cs b/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.cs new file mode 100644 index 0000000000000..1de3b4442c7fb --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.cs @@ -0,0 +1,60 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; + +[StructLayout(LayoutKind.Explicit)] +public struct S +{ +} + +[StructLayout(LayoutKind.Explicit)] +public struct S2 +{ +} + +[StructLayout(LayoutKind.Explicit)] +public class C +{ +} + +[StructLayout(LayoutKind.Explicit)] +public class C2 +{ +} + +public class Test_explicitStruct_empty +{ + // Mark as no-inlining so any test failures will show the right stack trace even after + // we consolidate test assemblies. + [Fact] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void EmptyExplicitStructCanBeLoadedAndCreated() + { + S s = new S(); + } + + [Fact] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void EmptyExplicitStructCanBeLoadedAndCreatedThroughReflection() + { + object s = Activator.CreateInstance(Type.GetType("S2")); + } + + [Fact] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void EmptyExplicitClassCanBeLoadedAndCreated() + { + C c = new C(); + } + + [Fact] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void EmptyExplicitClassCanBeLoadedAndCreatedThroughReflection() + { + object c = Activator.CreateInstance(Type.GetType("C2")); + } +} diff --git a/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.csproj b/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.csproj new file mode 100644 index 0000000000000..a304092ec069b --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/Regressions/empty/explicitStruct_empty.csproj @@ -0,0 +1,5 @@ + + + + + diff --git a/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs b/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs new file mode 100644 index 0000000000000..2e01b96bf31d5 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var type = Type.GetType("_测试数据记录仪_Iiİı_åäö_Controller_DataLogger1_log_all_", false); +var obj = Activator.CreateInstance(type!); +Console.WriteLine(obj?.GetType().Name); + +return 100; + +public class _测试数据记录仪_Iiİı_åäö_Controller_DataLogger1_log_all_ +{ +} diff --git a/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj b/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj new file mode 100644 index 0000000000000..b72e9a46cf95a --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj @@ -0,0 +1,17 @@ + + + + Exe + enable + enable + 1 + + + true + + + + + + + diff --git a/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs b/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs new file mode 100644 index 0000000000000..bffbf999e7396 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public class Program +{ + private interface IFoo + { + bool IsValid { get; } + } + + private class Foo : IFoo + { + public bool IsValid { get; set; } + } + + public static int Main(string[] args) + { + bool warmup = new Foo().IsValid; + CatchIgnore(() => + CatchRethrow(() => + { + IFoo[] foos = {new Foo(), null}; + foreach (var foo in foos) + { + bool check = foo.IsValid; + } + })); + + return 100; + } + + public static void CatchRethrow(Action action) + { + try + { + action.Invoke(); + } + catch (Exception e) + { + Console.Out.WriteLine("catch"); + Console.Out.Flush(); + throw new Exception("catch", e); + } + } + + public static void CatchIgnore(Action action) + { + try + { + action.Invoke(); + } + catch (Exception) + { + Console.Out.WriteLine("ignore"); + Console.Out.Flush(); + } + } +} diff --git a/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj b/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj new file mode 100644 index 0000000000000..0fce5a0556f40 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj @@ -0,0 +1,9 @@ + + + Exe + 1 + + + + + diff --git a/src/tests/ilverify/ILTests/ValueTypeTests.il b/src/tests/ilverify/ILTests/ValueTypeTests.il index a52cb76522464..8eb3aac002de8 100644 --- a/src/tests/ilverify/ILTests/ValueTypeTests.il +++ b/src/tests/ilverify/ILTests/ValueTypeTests.il @@ -26,3 +26,16 @@ } } +.class public sequential ansi sealed beforefieldinit ValueTypeFieldTests + extends [System.Runtime]System.ValueType +{ + .field public int32 InstanceField + + .method public static int32 ValueType.UnboxLdfld_Valid(object o) cil managed + { + ldarg.0 + unbox ValueTypeFieldTests + ldfld int32 ValueTypeFieldTests::InstanceField + ret + } +} diff --git a/src/tests/issues.targets b/src/tests/issues.targets index f6ffb0f93efa2..d14ab8edbdbc1 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -820,6 +820,9 @@ https://github.com/dotnet/runtime/issues/615 + + https://github.com/dotnet/runtime/issues/64419 + Not compatible with crossgen2 @@ -920,15 +923,9 @@ https://github.com/dotnet/runtimelab/issues/206 - - https://github.com/dotnet/runtimelab/issues/168 - https://github.com/dotnet/runtimelab/issues/176: VARIANT marshalling - - https://github.com/dotnet/runtimelab/issues/176: VARIANT marshalling - https://github.com/dotnet/runtimelab/issues/170 @@ -1329,7 +1326,7 @@ - + @@ -1985,6 +1982,9 @@ Tests coreclr JIT's debug info generation + + https://github.com/dotnet/runtime/issues/64127 + @@ -2505,6 +2505,9 @@ https://github.com/dotnet/runtime/issues/54376 + + needs triage + @@ -2586,6 +2589,9 @@ expected failure: overlapped structs fail at AOT compile time, not runtime + + expected failure: unsupported type with ref field fails at AOT compile time, not runtime + https://github.com/dotnet/runtime/issues/57361 @@ -2795,6 +2801,14 @@ https://github.com/dotnet/runtime/issues/57512 + + + This test includes an intentionally-invalid UnmanagedCallersOnly method. Invalid UnmanagedCallersOnly methods cause failures at AOT-time. + + + + https://github.com/dotnet/runtime/issues/64179 + @@ -3338,6 +3352,9 @@ needs triage + + needs triage + diff --git a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs index 658ab86b07822..eb4c63f1d1e5e 100644 --- a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs +++ b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Runtime; using System.Runtime.InteropServices; using BindingFlags = System.Reflection.BindingFlags; @@ -40,6 +41,7 @@ private static int Main() TestDrawCircle.Run(); TestValueTypeDup.Run(); TestFunctionPointers.Run(); + TestGCInteraction.Run(); #else Console.WriteLine("Preinitialization is disabled in multimodule builds for now. Skipping test."); #endif @@ -834,6 +836,39 @@ public static void Run() } } +class TestGCInteraction +{ + class WithFrozenObjects + { + internal readonly static string s_someStringLiteral = "Some string literal"; + internal readonly static object s_someObject = new object(); + } + + public static void Run() + { + Assert.IsPreinitialized(typeof(WithFrozenObjects)); + + var holder = new object[] + { + WithFrozenObjects.s_someStringLiteral, + WithFrozenObjects.s_someObject, + }; + + var h1 = new DependentHandle(WithFrozenObjects.s_someObject, WithFrozenObjects.s_someStringLiteral); + var h2 = new DependentHandle(WithFrozenObjects.s_someStringLiteral, WithFrozenObjects.s_someObject); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + Assert.AreSame(holder[0], WithFrozenObjects.s_someStringLiteral); + Assert.AreSame(holder[1], WithFrozenObjects.s_someObject); + + h1.Dispose(); + h2.Dispose(); + } +} + static class Assert { private static bool HasCctor(Type type) diff --git a/src/tests/profiler/native/gcprofiler/gcprofiler.cpp b/src/tests/profiler/native/gcprofiler/gcprofiler.cpp index 42666a2d8eac8..ed6312cd89c46 100644 --- a/src/tests/profiler/native/gcprofiler/gcprofiler.cpp +++ b/src/tests/profiler/native/gcprofiler/gcprofiler.cpp @@ -37,6 +37,10 @@ HRESULT GCProfiler::Shutdown() { printf("GCProfiler::Shutdown: FAIL: Expected GarbageCollectionFinished to be called\n"); } + else if (_allocatedByClassCalls == 0) + { + printf("GCProfiler::Shutdown: FAIL: Expected ObjectsAllocatedByClass to be called\n"); + } else if (_pohObjectsSeenRootReferences == 0 || _pohObjectsSeenObjectReferences == 0) { printf("GCProfiler::Shutdown: FAIL: no POH objects seen. root references=%d object references=%d\n", @@ -86,6 +90,20 @@ HRESULT GCProfiler::GarbageCollectionFinished() return S_OK; } +HRESULT GCProfiler::ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]) +{ + SHUTDOWNGUARD(); + + _allocatedByClassCalls++; + if (_gcStarts != _allocatedByClassCalls) + { + _failures++; + printf("GCProfiler::ObjectsAllocatedByClass: FAIL: Expected ObjectsAllocatedByClass Calls == GCStart. AllocatedByClassCalls=%d, GCStart=%d\n", (int)_allocatedByClassCalls, (int)_gcStarts); + } + + return S_OK; +} + HRESULT GCProfiler::ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]) { SHUTDOWNGUARD(); diff --git a/src/tests/profiler/native/gcprofiler/gcprofiler.h b/src/tests/profiler/native/gcprofiler/gcprofiler.h index ab519f6f53399..eebdb06853f7a 100644 --- a/src/tests/profiler/native/gcprofiler/gcprofiler.h +++ b/src/tests/profiler/native/gcprofiler/gcprofiler.h @@ -16,6 +16,7 @@ class GCProfiler : public Profiler GCProfiler() : Profiler(), _gcStarts(0), _gcFinishes(0), + _allocatedByClassCalls(0), _failures(0), _pohObjectsSeenRootReferences(0), _pohObjectsSeenObjectReferences(0), @@ -28,12 +29,14 @@ class GCProfiler : public Profiler virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished(); + virtual HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]); virtual HRESULT STDMETHODCALLTYPE ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]); virtual HRESULT STDMETHODCALLTYPE RootReferences(ULONG cRootRefs, ObjectID rootRefIds[]); private: std::atomic _gcStarts; std::atomic _gcFinishes; + std::atomic _allocatedByClassCalls; std::atomic _failures; std::atomic _pohObjectsSeenRootReferences; std::atomic _pohObjectsSeenObjectReferences;